mirror of
https://github.com/openvinotoolkit/stable-diffusion-webui.git
synced 2024-12-14 22:53:25 +03:00
Delete venv/Lib/site-packages directory
This commit is contained in:
parent
2e8b5418e3
commit
9170224d23
@ -1,489 +0,0 @@
|
|||||||
3.1.8
|
|
||||||
=====
|
|
||||||
|
|
||||||
recalculate bits used after all flags created (sometimes needed when a custom
|
|
||||||
`__new__` is in place.
|
|
||||||
|
|
||||||
|
|
||||||
3.1.7
|
|
||||||
=====
|
|
||||||
|
|
||||||
update flag creation to (possibly) add bitwise operator methods to newly
|
|
||||||
created flags
|
|
||||||
|
|
||||||
update extend_enum() to work with 3.11 flags
|
|
||||||
|
|
||||||
|
|
||||||
3.1.6
|
|
||||||
=====
|
|
||||||
|
|
||||||
Update `dir()` on mixed enums to include mixed data type methods and
|
|
||||||
attributes.
|
|
||||||
|
|
||||||
Rename `enum_property` to `property` to match stdlib. Recommended usage is
|
|
||||||
`aenum.property` (prefix with module name).
|
|
||||||
|
|
||||||
Remove quadritic creation behavior.
|
|
||||||
|
|
||||||
|
|
||||||
BREAKING CHANGE BUG FIX that won't affect most people
|
|
||||||
|
|
||||||
Enums with a custom `__new__` that:
|
|
||||||
|
|
||||||
- use the enum machinery to generate the values; AND
|
|
||||||
- have keyword arguments set to a default (like `None`)
|
|
||||||
|
|
||||||
will fail to generate a missing value. To fix: remove the default value and
|
|
||||||
instead specify it on the member creation line.
|
|
||||||
|
|
||||||
BREAKING CHANGE
|
|
||||||
|
|
||||||
In Python 3.11 the `str()` of mixed enums will now match its `format()` which
|
|
||||||
will be the normal `str()` of the data type -- so for an IntEnum you'll see
|
|
||||||
`5` instead of `Perm.R|X`. This affects IntEnum, StrEnum, and IntFlag.
|
|
||||||
|
|
||||||
|
|
||||||
3.1.5
|
|
||||||
=====
|
|
||||||
|
|
||||||
fix support of `auto()` kwds
|
|
||||||
|
|
||||||
|
|
||||||
3.1.3
|
|
||||||
=====
|
|
||||||
|
|
||||||
rename `aenum.property` to `aenum.enum_property`
|
|
||||||
|
|
||||||
fix `enum_property` to work with `_init_` attributes
|
|
||||||
|
|
||||||
|
|
||||||
3.1.2
|
|
||||||
=====
|
|
||||||
|
|
||||||
fix `extend_enum()` for unhashable values
|
|
||||||
|
|
||||||
|
|
||||||
3.1.1
|
|
||||||
=====
|
|
||||||
|
|
||||||
fix `extend_enum()` for most cases
|
|
||||||
|
|
||||||
|
|
||||||
3.1.0
|
|
||||||
=====
|
|
||||||
|
|
||||||
AddValue is similar to the old AutoNumber: it will always activate, but
|
|
||||||
uses _generate_next_value_ to get the next value (so the user has some
|
|
||||||
control over the return data type instead of always getting an int).
|
|
||||||
|
|
||||||
|
|
||||||
BREAKING CHANGES
|
|
||||||
|
|
||||||
AutoValue is gone. It was superflous and its removal simplified the code.
|
|
||||||
Simply put the fields needed in an `_init_` and `_generate_next_value_`
|
|
||||||
will be called to supply the missing values (this is probably already what
|
|
||||||
is happening).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
3.0.0
|
|
||||||
=====
|
|
||||||
|
|
||||||
standard Enum usage is unchanged
|
|
||||||
|
|
||||||
BREAKING CHANGES
|
|
||||||
|
|
||||||
Enum
|
|
||||||
- the more esoteric method of creating Enums have been modified or removed
|
|
||||||
- AutoNumber setting is gone, inherit from AutoNumberEnum instead
|
|
||||||
- creating members without specifying anything is removed (if you don't
|
|
||||||
know what this means, you weren't doing it)
|
|
||||||
|
|
||||||
Flag
|
|
||||||
- unique flags are canonical (i.e. flags with powers of two values such as
|
|
||||||
1, 2, 4, 8, 16, etc.)
|
|
||||||
- non-unique flags are aliases (i.e. values such as 3 or 7)
|
|
||||||
- iteration of Flag and flag members only uses canonical flags
|
|
||||||
|
|
||||||
|
|
||||||
ENHANCEMENTS
|
|
||||||
|
|
||||||
Member creation has been redone to match Python 3.10's methods. This also
|
|
||||||
allows all supported Pythons (2.7, 3.3+) to use the __set_name__ and
|
|
||||||
__init_subclass__ protocols (more robustly than in aenum 2.2.5)
|
|
||||||
|
|
||||||
|
|
||||||
CHANGES
|
|
||||||
|
|
||||||
enum_property() has been renamed to property() (old name still available, but
|
|
||||||
deprecated).
|
|
||||||
|
|
||||||
bin() replacement shows negative integers in twos-complement
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
2.2.5
|
|
||||||
=====
|
|
||||||
|
|
||||||
call __init_subclass__ after members have been added, and in Pythons < 3.6
|
|
||||||
call __set_name__ in Pythons < 3.6
|
|
||||||
do not convert/disallow private names
|
|
||||||
add iteration/len support to NamedConstant
|
|
||||||
|
|
||||||
|
|
||||||
2.2.4
|
|
||||||
=====
|
|
||||||
|
|
||||||
add support to Constant to retrieve members by value
|
|
||||||
|
|
||||||
--> class K(Constant):
|
|
||||||
... one = 1
|
|
||||||
... two = 2
|
|
||||||
|
|
||||||
--> K.one
|
|
||||||
<K.one: 1>
|
|
||||||
|
|
||||||
--> K(1)
|
|
||||||
<K.one: 1>
|
|
||||||
|
|
||||||
add pickle/deepcopy support to Constant
|
|
||||||
|
|
||||||
add support for Constant to use other Constant values
|
|
||||||
(resulting members /are not/ the same)
|
|
||||||
|
|
||||||
--> class C(Constant)
|
|
||||||
... one = K.one
|
|
||||||
... three = 3
|
|
||||||
|
|
||||||
--> C.one == K.one
|
|
||||||
True
|
|
||||||
|
|
||||||
--> C.one is K.one
|
|
||||||
False
|
|
||||||
|
|
||||||
AutoNumber and auto() now work together
|
|
||||||
|
|
||||||
Enum members are now added to the class as enum_property, which supports
|
|
||||||
unshadowing of parent class attributes when called on an Enum member:
|
|
||||||
|
|
||||||
--> class StrEnum(str, Enum):
|
|
||||||
... lower = 'lower'
|
|
||||||
... upper = 'upper'
|
|
||||||
... mixed = 'mixed'
|
|
||||||
|
|
||||||
--> StrEnum.lower
|
|
||||||
<StrEnum.lower: 'lower'>
|
|
||||||
|
|
||||||
--> StrEnum.lower.upper()
|
|
||||||
'LOWER'
|
|
||||||
|
|
||||||
--> StrEnum.upper
|
|
||||||
<StrEnum.upper: 'upper'>
|
|
||||||
|
|
||||||
--> StrEnum.upper.upper()
|
|
||||||
'UPPER'
|
|
||||||
|
|
||||||
|
|
||||||
2.2.3
|
|
||||||
=====
|
|
||||||
|
|
||||||
use members' type's methods __str__, __repr__, __format__, and
|
|
||||||
__reduce_ex__ if directly assigned in Enum class body; i.e.:
|
|
||||||
|
|
||||||
--> class Color(str, Enum):
|
|
||||||
... red = 'red'
|
|
||||||
... green = 'green'
|
|
||||||
... blue = 'blue'
|
|
||||||
... __str__ = str.__str__
|
|
||||||
|
|
||||||
--> print(repr(Color.green))
|
|
||||||
<Color.green: 'green'>
|
|
||||||
|
|
||||||
--> print(Color.green)
|
|
||||||
green
|
|
||||||
|
|
||||||
|
|
||||||
2.2.2
|
|
||||||
=====
|
|
||||||
|
|
||||||
replace _RouteClassAttributeToGetattr with enum_property (it is still
|
|
||||||
available as an alias)
|
|
||||||
|
|
||||||
support constant() and auto() being used together:
|
|
||||||
|
|
||||||
--> class Fruit(Flag):
|
|
||||||
... _order_ = 'apple banana lemon orange'
|
|
||||||
... apple = auto()
|
|
||||||
... banana = auto()
|
|
||||||
... lemon = auto()
|
|
||||||
... orange = auto()
|
|
||||||
... CitrusTypes = constant(lemon | orange)
|
|
||||||
|
|
||||||
--> list(Fruit)
|
|
||||||
[Fruit.apple, Fruit.banana, Fruit.lemon, Fruit.orange]
|
|
||||||
|
|
||||||
--> list(Fruit.CitrusTypes)
|
|
||||||
[Fruit.orange, Fruit.lemon]
|
|
||||||
|
|
||||||
--> Fruit.orange in Fruit.CitrusTypes
|
|
||||||
True
|
|
||||||
|
|
||||||
|
|
||||||
2.2.1
|
|
||||||
=====
|
|
||||||
|
|
||||||
allow Enums to be called without a value
|
|
||||||
|
|
||||||
class Color(Enum):
|
|
||||||
black = 0
|
|
||||||
red = 1
|
|
||||||
green = 2
|
|
||||||
blue = 3
|
|
||||||
#
|
|
||||||
@classmethod
|
|
||||||
def _missing_value_(cls, value):
|
|
||||||
if value is no_arg:
|
|
||||||
return cls.black
|
|
||||||
|
|
||||||
>>> Color()
|
|
||||||
<Color.black: 0>
|
|
||||||
|
|
||||||
allow Enum name use while constructing Enum (Python 3.4+ only)
|
|
||||||
|
|
||||||
--> class Color(Enum):
|
|
||||||
... _order_ = 'BLACK WHITE'
|
|
||||||
... BLACK = Color('black', '#000')
|
|
||||||
... WHITE = Color('white', '#fff')
|
|
||||||
... #
|
|
||||||
... def __init__(self, label, hex):
|
|
||||||
... self.label = label
|
|
||||||
... self.hex = hex
|
|
||||||
|
|
||||||
|
|
||||||
2.2.0
|
|
||||||
=====
|
|
||||||
|
|
||||||
BREAKING CHANGE
|
|
||||||
---------------
|
|
||||||
In Python 3+ classes defined inside an Enum no longer become members by
|
|
||||||
default; in Python 2 they still become members, but see below.
|
|
||||||
|
|
||||||
For cross-compatibility and full control two decorators are provided:
|
|
||||||
|
|
||||||
- @member --> forces item to become a member
|
|
||||||
- @nonmember --> excludes item from becoming a member
|
|
||||||
|
|
||||||
So to have an Enum that behaves the same in Python 2 and 3, use the
|
|
||||||
decorators (and other compatibility shims):
|
|
||||||
|
|
||||||
class Color(Enum):
|
|
||||||
|
|
||||||
_order_ = 'red green blue'
|
|
||||||
|
|
||||||
red = 1
|
|
||||||
green = 2
|
|
||||||
blue = 3
|
|
||||||
|
|
||||||
@nonmember
|
|
||||||
class Shades(Enum):
|
|
||||||
|
|
||||||
_order_ = 'light medium dark'
|
|
||||||
|
|
||||||
light = 1
|
|
||||||
medium = 2
|
|
||||||
dark = 3
|
|
||||||
|
|
||||||
|
|
||||||
2.1.4
|
|
||||||
=====
|
|
||||||
|
|
||||||
EnumMeta:
|
|
||||||
- change __member_new__ to __new_member__ (as the stdlib enum does)
|
|
||||||
- assign member name to enum() instances (an Enum helper for defining members)
|
|
||||||
- handle empty iterables when using functional API
|
|
||||||
- make auto() work with previous enum members
|
|
||||||
- keep searching mixins until base class is found
|
|
||||||
|
|
||||||
Enum:
|
|
||||||
- fix bug in Flag checks (ensure it is a Flag before checking the name)
|
|
||||||
- add multiple mixin support
|
|
||||||
- do not allow blank names (functional API)
|
|
||||||
- raise TypeError if _missing_* returns wrong type
|
|
||||||
- fix __format__ to honor custom __str__
|
|
||||||
|
|
||||||
extend_enum:
|
|
||||||
- support stdlib Enums
|
|
||||||
- use _generate_next_value_ if value not provided
|
|
||||||
|
|
||||||
general:
|
|
||||||
- standardize exception formatting
|
|
||||||
- use getfullargspec() in Python 3 (avoids deprecation warnings)
|
|
||||||
|
|
||||||
|
|
||||||
2.1.2
|
|
||||||
=====
|
|
||||||
|
|
||||||
when order is callable, save it for subclass use
|
|
||||||
|
|
||||||
|
|
||||||
2.1.1
|
|
||||||
=====
|
|
||||||
|
|
||||||
correctly raise TypeError for non-Enum containment checks
|
|
||||||
support combining names with | for Flag key access
|
|
||||||
support _order_ being a callable
|
|
||||||
|
|
||||||
|
|
||||||
2.1.0
|
|
||||||
=====
|
|
||||||
|
|
||||||
support Flags being combined with other data types:
|
|
||||||
- add _create_pseudo_member_values_
|
|
||||||
- add default __new__ and temporary _init_
|
|
||||||
|
|
||||||
|
|
||||||
2.0.10
|
|
||||||
======
|
|
||||||
|
|
||||||
ensure _ignore_ is set when _settings_ specified in body which includes
|
|
||||||
AutoValue
|
|
||||||
|
|
||||||
make Flag members iterable
|
|
||||||
|
|
||||||
|
|
||||||
2.0.9
|
|
||||||
=====
|
|
||||||
|
|
||||||
fix missing comma in __all__
|
|
||||||
fix extend_enum with custom __new__ methods
|
|
||||||
fix MultiValue with AutoNumber without _init_
|
|
||||||
|
|
||||||
|
|
||||||
2.0.8
|
|
||||||
=====
|
|
||||||
|
|
||||||
extend_enum now handles aliases and multivalues correctly
|
|
||||||
|
|
||||||
|
|
||||||
2.0.7
|
|
||||||
=====
|
|
||||||
|
|
||||||
support mixin types with extend_enum
|
|
||||||
init and AutoNumber can now work together
|
|
||||||
add test for new Enum using EnumMeta
|
|
||||||
add tests for variations of multivalue and init
|
|
||||||
prevent deletion of NamedConstant.constant
|
|
||||||
|
|
||||||
|
|
||||||
2.0.6
|
|
||||||
=====
|
|
||||||
|
|
||||||
constants cannot be deleted (they already couldn't be changed)
|
|
||||||
constants can be used to define other constants
|
|
||||||
|
|
||||||
|
|
||||||
2.0.5
|
|
||||||
=====
|
|
||||||
|
|
||||||
_init_ and MultiValue can now work together
|
|
||||||
|
|
||||||
|
|
||||||
2.0.4
|
|
||||||
=====
|
|
||||||
|
|
||||||
_init_ and AutoValue (and _generate_next_value_) can now work together to
|
|
||||||
supply missing values even when some of the required values per member are
|
|
||||||
absent
|
|
||||||
|
|
||||||
|
|
||||||
2.0.3
|
|
||||||
=====
|
|
||||||
|
|
||||||
add _missing_value_ and _missing_name_ methods, deprecate _missing_
|
|
||||||
make enum instances comparable
|
|
||||||
|
|
||||||
|
|
||||||
2.0.2
|
|
||||||
=====
|
|
||||||
|
|
||||||
both EnumMeta.__getattr__ and Enum.__new__ fall back to _missing_
|
|
||||||
|
|
||||||
|
|
||||||
2.0.1
|
|
||||||
=====
|
|
||||||
|
|
||||||
auto() now works with other data types
|
|
||||||
AutoNumber supports legacy Enums (fixed regression)
|
|
||||||
|
|
||||||
|
|
||||||
2.0.0
|
|
||||||
=====
|
|
||||||
|
|
||||||
Flag and IntFlag added.
|
|
||||||
|
|
||||||
|
|
||||||
1.4.7
|
|
||||||
=====
|
|
||||||
|
|
||||||
fix %-interpolation bug
|
|
||||||
defined SqlLiteEnum only if sqlite exists
|
|
||||||
support pyflakes
|
|
||||||
|
|
||||||
|
|
||||||
1.4.6
|
|
||||||
=====
|
|
||||||
|
|
||||||
version numbering error
|
|
||||||
|
|
||||||
|
|
||||||
1.4.5
|
|
||||||
=====
|
|
||||||
|
|
||||||
revert AutoNumberEnum to custom __new__ instead of AutoNumber
|
|
||||||
use _ignore_ to shield against AutoNumber magic
|
|
||||||
inherit start and init settings from base Enums
|
|
||||||
|
|
||||||
|
|
||||||
1.4.4
|
|
||||||
=====
|
|
||||||
|
|
||||||
enabled export as a decorator
|
|
||||||
enabled _order_ to replace __order__
|
|
||||||
enabled python2 support for settings, init, and start
|
|
||||||
|
|
||||||
|
|
||||||
1.4.3
|
|
||||||
=====
|
|
||||||
|
|
||||||
support _ignore_ for dynamically creating class bodies
|
|
||||||
|
|
||||||
|
|
||||||
1.4.2
|
|
||||||
=====
|
|
||||||
|
|
||||||
MultiValue, NoAlias, Unique, and init now work with Python 2
|
|
||||||
|
|
||||||
|
|
||||||
1.4.1
|
|
||||||
=====
|
|
||||||
|
|
||||||
Py3: added Enum creation flags: Auto, MultiValue, NoAlias, Unique
|
|
||||||
|
|
||||||
fixed extend_enum to honor Enum flags
|
|
||||||
|
|
||||||
|
|
||||||
1.4.0
|
|
||||||
=====
|
|
||||||
|
|
||||||
When possible aenum inherits from Python's own enum.
|
|
||||||
|
|
||||||
Breaking change: enum members now default to evaluating as True to maintain
|
|
||||||
compatibility with the stdlib.
|
|
||||||
|
|
||||||
Add your own __bool__ (__nonzero__ in Python 2) if need this behavior:
|
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return bool(self.value)
|
|
||||||
__nonzero__ = __bool__
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
|||||||
Copyright (c) 2015, 2016, 2017, 2018 Ethan Furman.
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions
|
|
||||||
are met:
|
|
||||||
|
|
||||||
Redistributions of source code must retain the above
|
|
||||||
copyright notice, this list of conditions and the
|
|
||||||
following disclaimer.
|
|
||||||
|
|
||||||
Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer in the documentation and/or other materials
|
|
||||||
provided with the distribution.
|
|
||||||
|
|
||||||
Neither the name Ethan Furman nor the names of any
|
|
||||||
contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written
|
|
||||||
permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
||||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
||||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
||||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
||||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
POSSIBILITY OF SUCH DAMAGE.
|
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
@ -1,7 +0,0 @@
|
|||||||
from operator import div as _div_
|
|
||||||
from inspect import getargspec
|
|
||||||
|
|
||||||
def raise_with_traceback(exc, tb):
|
|
||||||
raise exc, None, tb
|
|
||||||
|
|
||||||
__all__ = ['_div_', 'getargspec', 'raise_with_traceback']
|
|
@ -1,12 +0,0 @@
|
|||||||
from inspect import getfullargspec as _getfullargspec
|
|
||||||
|
|
||||||
def getargspec(method):
|
|
||||||
args, varargs, keywords, defaults, _, _, _ = _getfullargspec(method)
|
|
||||||
return args, varargs, keywords, defaults
|
|
||||||
|
|
||||||
def raise_with_traceback(exc, tb):
|
|
||||||
raise exc.with_traceback(tb)
|
|
||||||
|
|
||||||
def raise_from_none(exc):
|
|
||||||
raise exc from None
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,2 +0,0 @@
|
|||||||
"""Use this module to apply a number of blending modes to a background and foreground image
|
|
||||||
"""
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,511 +0,0 @@
|
|||||||
"""Provide blending functions and types.
|
|
||||||
|
|
||||||
Adapted from https://github.com/addisonElliott/pypdn/blob/master/pypdn/reader.py
|
|
||||||
and https://gitlab.com/inklabapp/pyora/-/blob/master/pyora/BlendNonSep.py
|
|
||||||
MIT License Copyright (c) 2020 FredHappyface
|
|
||||||
|
|
||||||
Credits to:
|
|
||||||
|
|
||||||
MIT License Copyright (c) 2019 Paul Jewell
|
|
||||||
For implementing blending from the Open Raster Image Spec
|
|
||||||
|
|
||||||
MIT License Copyright (c) 2018 Addison Elliott
|
|
||||||
For implementing blending from Paint.NET
|
|
||||||
|
|
||||||
MIT License Copyright (c) 2017 pashango
|
|
||||||
For implementing a number of blending functions used by other popular image
|
|
||||||
editors
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
import numpy as np
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
from .blendtype import BlendType
|
|
||||||
|
|
||||||
|
|
||||||
def normal(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.NORMAL."""
|
|
||||||
del background # we don't care about this
|
|
||||||
return foreground
|
|
||||||
|
|
||||||
|
|
||||||
def multiply(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.MULTIPLY."""
|
|
||||||
return np.clip(foreground * background, 0.0, 1.0)
|
|
||||||
|
|
||||||
|
|
||||||
def additive(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.ADDITIVE."""
|
|
||||||
return np.minimum(background + foreground, 1.0)
|
|
||||||
|
|
||||||
|
|
||||||
def colourburn(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.COLOURBURN."""
|
|
||||||
with np.errstate(divide="ignore"):
|
|
||||||
return np.where(
|
|
||||||
foreground != 0.0, np.maximum(1.0 - ((1.0 - background) / foreground), 0.0), 0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def colourdodge(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.COLOURDODGE."""
|
|
||||||
with np.errstate(divide="ignore"):
|
|
||||||
return np.where(foreground != 1.0, np.minimum(background / (1.0 - foreground), 1.0), 1.0)
|
|
||||||
|
|
||||||
|
|
||||||
def reflect(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.REFLECT."""
|
|
||||||
with np.errstate(divide="ignore"):
|
|
||||||
return np.where(
|
|
||||||
foreground != 1.0, np.minimum((background ** 2) / (1.0 - foreground), 1.0), 1.0
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def glow(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.GLOW."""
|
|
||||||
with np.errstate(divide="ignore"):
|
|
||||||
return np.where(
|
|
||||||
background != 1.0, np.minimum((foreground ** 2) / (1.0 - background), 1.0), 1.0
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def overlay(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.OVERLAY."""
|
|
||||||
return np.where(
|
|
||||||
background < 0.5,
|
|
||||||
2 * background * foreground,
|
|
||||||
1.0 - (2 * (1.0 - background) * (1.0 - foreground)),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def difference(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.DIFFERENCE."""
|
|
||||||
return np.abs(background - foreground)
|
|
||||||
|
|
||||||
|
|
||||||
def negation(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.NEGATION."""
|
|
||||||
return np.maximum(background - foreground, 0.0)
|
|
||||||
|
|
||||||
|
|
||||||
def lighten(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.LIGHTEN."""
|
|
||||||
return np.maximum(background, foreground)
|
|
||||||
|
|
||||||
|
|
||||||
def darken(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.DARKEN."""
|
|
||||||
return np.minimum(background, foreground)
|
|
||||||
|
|
||||||
|
|
||||||
def screen(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.SCREEN."""
|
|
||||||
return background + foreground - background * foreground
|
|
||||||
|
|
||||||
|
|
||||||
def xor(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.XOR."""
|
|
||||||
# XOR requires int values so convert to uint8
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
return imageIntToFloat(imageFloatToInt(background) ^ imageFloatToInt(foreground))
|
|
||||||
|
|
||||||
|
|
||||||
def softlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.SOFTLIGHT."""
|
|
||||||
return (1.0 - background) * background * foreground + background * (
|
|
||||||
1.0 - (1.0 - background) * (1.0 - foreground)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def hardlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.HARDLIGHT."""
|
|
||||||
return np.where(
|
|
||||||
foreground < 0.5,
|
|
||||||
np.minimum(background * 2 * foreground, 1.0),
|
|
||||||
np.minimum(1.0 - ((1.0 - background) * (1.0 - (foreground - 0.5) * 2.0)), 1.0),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def grainextract(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.GRAINEXTRACT."""
|
|
||||||
return np.clip(background - foreground + 0.5, 0.0, 1.0)
|
|
||||||
|
|
||||||
|
|
||||||
def grainmerge(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.GRAINMERGE."""
|
|
||||||
return np.clip(background + foreground - 0.5, 0.0, 1.0)
|
|
||||||
|
|
||||||
|
|
||||||
def divide(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.DIVIDE."""
|
|
||||||
return np.minimum((256.0 / 255.0 * background) / (1.0 / 255.0 + foreground), 1.0)
|
|
||||||
|
|
||||||
|
|
||||||
def pinlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.PINLIGHT."""
|
|
||||||
return np.minimum(background, 2 * foreground) * (foreground < 0.5) + np.maximum(
|
|
||||||
background, 2 * (foreground - 0.5)
|
|
||||||
) * (foreground >= 0.5)
|
|
||||||
|
|
||||||
|
|
||||||
def vividlight(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.VIVIDLIGHT."""
|
|
||||||
return colourburn(background, foreground * 2) * (foreground < 0.5) + colourdodge(
|
|
||||||
background, 2 * (foreground - 0.5)
|
|
||||||
) * (foreground >= 0.5)
|
|
||||||
|
|
||||||
|
|
||||||
def exclusion(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.EXCLUSION."""
|
|
||||||
return background + foreground - (2.0 * background * foreground)
|
|
||||||
|
|
||||||
|
|
||||||
def _lum(colours: np.ndarray) -> np.ndarray:
|
|
||||||
"""Luminosity.
|
|
||||||
|
|
||||||
:param colours: x by x by 3 matrix of rgb color components of pixels
|
|
||||||
:return: x by x by 3 matrix of luminosity of pixels
|
|
||||||
"""
|
|
||||||
return (colours[:, :, 0] * 0.299) + (colours[:, :, 1] * 0.587) + (colours[:, :, 2] * 0.114)
|
|
||||||
|
|
||||||
|
|
||||||
def _setLum(originalColours: np.ndarray, newLuminosity: np.ndarray) -> np.ndarray:
|
|
||||||
"""Set a new luminosity value for the matrix of color."""
|
|
||||||
_colours = originalColours.copy()
|
|
||||||
_luminosity = _lum(_colours)
|
|
||||||
deltaLum = newLuminosity - _luminosity
|
|
||||||
_colours[:, :, 0] += deltaLum
|
|
||||||
_colours[:, :, 1] += deltaLum
|
|
||||||
_colours[:, :, 2] += deltaLum
|
|
||||||
_luminosity = _lum(_colours)
|
|
||||||
_minColours = np.min(_colours, axis=2)
|
|
||||||
_MaxColours = np.max(_colours, axis=2)
|
|
||||||
for i in range(_colours.shape[0]):
|
|
||||||
for j in range(_colours.shape[1]):
|
|
||||||
_colour = _colours[i][j]
|
|
||||||
newLuminosity = _luminosity[i, j]
|
|
||||||
minColour = _minColours[i, j]
|
|
||||||
maxColour = _MaxColours[i, j]
|
|
||||||
if minColour < 0:
|
|
||||||
_colours[i][j] = newLuminosity + (
|
|
||||||
((_colour - newLuminosity) * newLuminosity) / (newLuminosity - minColour)
|
|
||||||
)
|
|
||||||
if maxColour > 1:
|
|
||||||
_colours[i][j] = newLuminosity + (
|
|
||||||
((_colour - newLuminosity) * (1 - newLuminosity)) / (maxColour - newLuminosity)
|
|
||||||
)
|
|
||||||
return _colours
|
|
||||||
|
|
||||||
|
|
||||||
def _sat(colours: np.ndarray) -> np.ndarray:
|
|
||||||
"""Saturation.
|
|
||||||
|
|
||||||
:param colours: x by x by 3 matrix of rgb color components of pixels
|
|
||||||
:return: int of saturation of pixels
|
|
||||||
"""
|
|
||||||
return np.max(colours, axis=2) - np.min(colours, axis=2)
|
|
||||||
|
|
||||||
|
|
||||||
def _setSat(originalColours: np.ndarray, newSaturation: np.ndarray) -> np.ndarray:
|
|
||||||
"""Set a new saturation value for the matrix of color.
|
|
||||||
|
|
||||||
The current implementation cannot be vectorized in an efficient manner,
|
|
||||||
so it is very slow,
|
|
||||||
O(m*n) at least. This might be able to be improved with openCL if that is
|
|
||||||
the direction that the lib takes.
|
|
||||||
:param c: x by x by 3 matrix of rgb color components of pixels
|
|
||||||
:param s: int of the new saturation value for the matrix
|
|
||||||
:return: x by x by 3 matrix of luminosity of pixels
|
|
||||||
"""
|
|
||||||
_colours = originalColours.copy()
|
|
||||||
for i in range(_colours.shape[0]):
|
|
||||||
for j in range(_colours.shape[1]):
|
|
||||||
_colour = _colours[i][j]
|
|
||||||
minI = 0
|
|
||||||
midI = 1
|
|
||||||
maxI = 2
|
|
||||||
if _colour[midI] < _colour[minI]:
|
|
||||||
minI, midI = midI, minI
|
|
||||||
if _colour[maxI] < _colour[midI]:
|
|
||||||
midI, maxI = maxI, midI
|
|
||||||
if _colour[midI] < _colour[minI]:
|
|
||||||
minI, midI = midI, minI
|
|
||||||
if _colour[maxI] - _colour[minI] > 0.0:
|
|
||||||
_colours[i][j][midI] = ((_colour[midI] - _colour[minI]) * newSaturation[i, j]) / (
|
|
||||||
_colour[maxI] - _colour[minI]
|
|
||||||
)
|
|
||||||
_colours[i][j][maxI] = newSaturation[i, j]
|
|
||||||
else:
|
|
||||||
_colours[i][j][midI] = 0
|
|
||||||
_colours[i][j][maxI] = 0
|
|
||||||
_colours[i][j][minI] = 0
|
|
||||||
return _colours
|
|
||||||
|
|
||||||
|
|
||||||
def hue(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.HUE."""
|
|
||||||
return _setLum(_setSat(foreground, _sat(background)), _lum(background))
|
|
||||||
|
|
||||||
|
|
||||||
def saturation(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.SATURATION."""
|
|
||||||
return _setLum(_setSat(background, _sat(foreground)), _lum(background))
|
|
||||||
|
|
||||||
|
|
||||||
def colour(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.COLOUR."""
|
|
||||||
return _setLum(foreground, _lum(background))
|
|
||||||
|
|
||||||
|
|
||||||
def luminosity(background: np.ndarray, foreground: np.ndarray) -> np.ndarray:
|
|
||||||
"""BlendType.LUMINOSITY."""
|
|
||||||
return _setLum(background, _lum(foreground))
|
|
||||||
|
|
||||||
|
|
||||||
def destin(
|
|
||||||
backgroundAlpha: np.ndarray,
|
|
||||||
foregroundAlpha: np.ndarray,
|
|
||||||
backgroundColour: np.ndarray,
|
|
||||||
foregroundColour: np.ndarray,
|
|
||||||
):
|
|
||||||
"""'clip' composite mode.
|
|
||||||
|
|
||||||
All parts of 'layer above' which are alpha in 'layer below' will be made
|
|
||||||
also alpha in 'layer above'
|
|
||||||
(to whatever degree of alpha they were)
|
|
||||||
|
|
||||||
Destination which overlaps the source, replaces the source.
|
|
||||||
|
|
||||||
Fa = 0; Fb = αs
|
|
||||||
co = αb x Cb x αs
|
|
||||||
αo = αb x αs
|
|
||||||
"""
|
|
||||||
del foregroundColour # Not used by function
|
|
||||||
outAlpha = backgroundAlpha * foregroundAlpha
|
|
||||||
with np.errstate(divide="ignore", invalid="ignore"):
|
|
||||||
outRGB = np.divide(
|
|
||||||
np.multiply((backgroundAlpha * foregroundAlpha)[:, :, None], backgroundColour),
|
|
||||||
outAlpha[:, :, None],
|
|
||||||
)
|
|
||||||
return outRGB, outAlpha
|
|
||||||
|
|
||||||
|
|
||||||
def destout(
|
|
||||||
backgroundAlpha: np.ndarray,
|
|
||||||
foregroundAlpha: np.ndarray,
|
|
||||||
backgroundColour: np.ndarray,
|
|
||||||
foregroundColour: np.ndarray,
|
|
||||||
):
|
|
||||||
"""Reverse 'Clip' composite mode.
|
|
||||||
|
|
||||||
All parts of 'layer below' which are alpha in 'layer above' will be made
|
|
||||||
also alpha in 'layer below'
|
|
||||||
(to whatever degree of alpha they were)
|
|
||||||
|
|
||||||
"""
|
|
||||||
del foregroundColour # Not used by function
|
|
||||||
outAlpha = backgroundAlpha * (1 - foregroundAlpha)
|
|
||||||
with np.errstate(divide="ignore", invalid="ignore"):
|
|
||||||
outRGB = np.divide(
|
|
||||||
np.multiply((backgroundAlpha * (1 - foregroundAlpha))[:, :, None], backgroundColour),
|
|
||||||
outAlpha[:, :, None],
|
|
||||||
)
|
|
||||||
return outRGB, outAlpha
|
|
||||||
|
|
||||||
|
|
||||||
def destatop(
|
|
||||||
backgroundAlpha: np.ndarray,
|
|
||||||
foregroundAlpha: np.ndarray,
|
|
||||||
backgroundColour: np.ndarray,
|
|
||||||
foregroundColour: np.ndarray,
|
|
||||||
):
|
|
||||||
"""Place the layer below above the 'layer above' in places where the 'layer above' exists...
|
|
||||||
|
|
||||||
where 'layer below' does not exist, but 'layer above' does, place 'layer-above'
|
|
||||||
|
|
||||||
"""
|
|
||||||
outAlpha = (foregroundAlpha * (1 - backgroundAlpha)) + (backgroundAlpha * foregroundAlpha)
|
|
||||||
with np.errstate(divide="ignore", invalid="ignore"):
|
|
||||||
outRGB = np.divide(
|
|
||||||
np.multiply((foregroundAlpha * (1 - backgroundAlpha))[:, :, None], foregroundColour)
|
|
||||||
+ np.multiply((backgroundAlpha * foregroundAlpha)[:, :, None], backgroundColour),
|
|
||||||
outAlpha[:, :, None],
|
|
||||||
)
|
|
||||||
return outRGB, outAlpha
|
|
||||||
|
|
||||||
|
|
||||||
def srcatop(
|
|
||||||
backgroundAlpha: np.ndarray,
|
|
||||||
foregroundAlpha: np.ndarray,
|
|
||||||
backgroundColour: np.ndarray,
|
|
||||||
foregroundColour: np.ndarray,
|
|
||||||
):
|
|
||||||
"""Place the layer below above the 'layer above' in places where the 'layer above' exists."""
|
|
||||||
outAlpha = (foregroundAlpha * backgroundAlpha) + (backgroundAlpha * (1 - foregroundAlpha))
|
|
||||||
with np.errstate(divide="ignore", invalid="ignore"):
|
|
||||||
outRGB = np.divide(
|
|
||||||
np.multiply((foregroundAlpha * backgroundAlpha)[:, :, None], foregroundColour)
|
|
||||||
+ np.multiply((backgroundAlpha * (1 - foregroundAlpha))[:, :, None], backgroundColour),
|
|
||||||
outAlpha[:, :, None],
|
|
||||||
)
|
|
||||||
|
|
||||||
return outRGB, outAlpha
|
|
||||||
|
|
||||||
|
|
||||||
def imageIntToFloat(image: np.ndarray) -> np.ndarray:
|
|
||||||
"""Convert a numpy array representing an image to an array of floats.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
image (np.ndarray): numpy array of ints
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
np.ndarray: numpy array of floats
|
|
||||||
"""
|
|
||||||
return image / 255
|
|
||||||
|
|
||||||
|
|
||||||
def imageFloatToInt(image: np.ndarray) -> np.ndarray:
|
|
||||||
"""Convert a numpy array representing an image to an array of ints.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
image (np.ndarray): numpy array of floats
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
np.ndarray: numpy array of ints
|
|
||||||
"""
|
|
||||||
return (image * 255).astype(np.uint8)
|
|
||||||
|
|
||||||
|
|
||||||
def blend(background: np.ndarray, foreground: np.ndarray, blendType: BlendType) -> np.ndarray:
|
|
||||||
"""Blend pixels.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
background (np.ndarray): background
|
|
||||||
foreground (np.ndarray): foreground
|
|
||||||
blendType (BlendType): the blend type
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
np.ndarray: new array representing the image
|
|
||||||
|
|
||||||
background: np.ndarray,
|
|
||||||
foreground: np.ndarray and the return are in the form
|
|
||||||
|
|
||||||
[[[0. 0. 0.]
|
|
||||||
[0. 0. 0.]
|
|
||||||
[0. 0. 0.]
|
|
||||||
...
|
|
||||||
[0. 0. 0.]
|
|
||||||
[0. 0. 0.]
|
|
||||||
[0. 0. 0.]]
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
[[0. 0. 0.]
|
|
||||||
[0. 0. 0.]
|
|
||||||
[0. 0. 0.]
|
|
||||||
...
|
|
||||||
[0. 0. 0.]
|
|
||||||
[0. 0. 0.]
|
|
||||||
[0. 0. 0.]]]
|
|
||||||
"""
|
|
||||||
blendLookup = {
|
|
||||||
BlendType.NORMAL: normal,
|
|
||||||
BlendType.MULTIPLY: multiply,
|
|
||||||
BlendType.COLOURBURN: colourburn,
|
|
||||||
BlendType.COLOURDODGE: colourdodge,
|
|
||||||
BlendType.REFLECT: reflect,
|
|
||||||
BlendType.OVERLAY: overlay,
|
|
||||||
BlendType.DIFFERENCE: difference,
|
|
||||||
BlendType.LIGHTEN: lighten,
|
|
||||||
BlendType.DARKEN: darken,
|
|
||||||
BlendType.SCREEN: screen,
|
|
||||||
BlendType.SOFTLIGHT: softlight,
|
|
||||||
BlendType.HARDLIGHT: hardlight,
|
|
||||||
BlendType.GRAINEXTRACT: grainextract,
|
|
||||||
BlendType.GRAINMERGE: grainmerge,
|
|
||||||
BlendType.DIVIDE: divide,
|
|
||||||
BlendType.HUE: hue,
|
|
||||||
BlendType.SATURATION: saturation,
|
|
||||||
BlendType.COLOUR: colour,
|
|
||||||
BlendType.LUMINOSITY: luminosity,
|
|
||||||
BlendType.XOR: xor,
|
|
||||||
BlendType.NEGATION: negation,
|
|
||||||
BlendType.PINLIGHT: pinlight,
|
|
||||||
BlendType.VIVIDLIGHT: vividlight,
|
|
||||||
BlendType.EXCLUSION: exclusion,
|
|
||||||
}
|
|
||||||
|
|
||||||
if blendType not in blendLookup:
|
|
||||||
return normal(background, foreground)
|
|
||||||
return blendLookup[blendType](background, foreground)
|
|
||||||
|
|
||||||
|
|
||||||
def blendLayers(
|
|
||||||
background: Image.Image,
|
|
||||||
foreground: Image.Image,
|
|
||||||
blendType: BlendType | tuple[str, ...],
|
|
||||||
opacity: float = 1.0,
|
|
||||||
) -> Image.Image:
|
|
||||||
"""Blend layers using numpy array.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
background (Image.Image): background layer
|
|
||||||
foreground (Image.Image): foreground layer (must be same size as background)
|
|
||||||
blendType (BlendType): The blendtype
|
|
||||||
opacity (float): The opacity of the foreground image
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Image.Image: combined image
|
|
||||||
"""
|
|
||||||
# Convert the Image.Image to a numpy array
|
|
||||||
npForeground: np.ndarray = imageIntToFloat(np.array(foreground.convert("RGBA")))
|
|
||||||
npBackground: np.ndarray = imageIntToFloat(np.array(background.convert("RGBA")))
|
|
||||||
|
|
||||||
# Get the alpha from the layers
|
|
||||||
backgroundAlpha = npBackground[:, :, 3]
|
|
||||||
foregroundAlpha = npForeground[:, :, 3] * opacity
|
|
||||||
combinedAlpha = backgroundAlpha * foregroundAlpha
|
|
||||||
|
|
||||||
# Get the colour from the layers
|
|
||||||
backgroundColor = npBackground[:, :, 0:3]
|
|
||||||
foregroundColor = npForeground[:, :, 0:3]
|
|
||||||
|
|
||||||
# Some effects require alpha
|
|
||||||
alphaFunc = {
|
|
||||||
BlendType.DESTIN: destin,
|
|
||||||
BlendType.DESTOUT: destout,
|
|
||||||
BlendType.SRCATOP: srcatop,
|
|
||||||
BlendType.DESTATOP: destatop,
|
|
||||||
}
|
|
||||||
|
|
||||||
if blendType in alphaFunc:
|
|
||||||
return Image.fromarray(
|
|
||||||
imageFloatToInt(
|
|
||||||
np.clip(
|
|
||||||
np.dstack(
|
|
||||||
alphaFunc[blendType](
|
|
||||||
backgroundAlpha, foregroundAlpha, backgroundColor, foregroundColor
|
|
||||||
)
|
|
||||||
),
|
|
||||||
a_min=0,
|
|
||||||
a_max=1,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Get the colours and the alpha for the new image
|
|
||||||
colorComponents = (
|
|
||||||
(backgroundAlpha - combinedAlpha)[:, :, None] * backgroundColor
|
|
||||||
+ (foregroundAlpha - combinedAlpha)[:, :, None] * foregroundColor
|
|
||||||
+ combinedAlpha[:, :, None] * blend(backgroundColor, foregroundColor, blendType)
|
|
||||||
)
|
|
||||||
alphaComponent = backgroundAlpha + foregroundAlpha - combinedAlpha
|
|
||||||
|
|
||||||
return Image.fromarray(
|
|
||||||
imageFloatToInt(np.clip(np.dstack((colorComponents, alphaComponent)), a_min=0, a_max=1))
|
|
||||||
)
|
|
@ -1,72 +0,0 @@
|
|||||||
"""Specify supported blend types."""
|
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from aenum import MultiValueEnum
|
|
||||||
|
|
||||||
|
|
||||||
class BlendType(str, MultiValueEnum):
|
|
||||||
"""Specify supported blend types.
|
|
||||||
|
|
||||||
NORMAL = "bm:normal", "normal"
|
|
||||||
MULTIPLY = "bm:multiply", "multiply"
|
|
||||||
ADDITIVE = "bm:additive", "additive"
|
|
||||||
COLOURBURN = "bm:colourburn", "colourburn"
|
|
||||||
COLOURDODGE = "bm:colourdodge", "colourdodge"
|
|
||||||
REFLECT = "bm:reflect", "reflect"
|
|
||||||
GLOW = "bm:glow", "glow"
|
|
||||||
OVERLAY = "bm:overlay", "overlay"
|
|
||||||
DIFFERENCE = "bm:difference", "difference"
|
|
||||||
NEGATION = "bm:negation", "negation"
|
|
||||||
LIGHTEN = "bm:lighten", "lighten"
|
|
||||||
DARKEN = "bm:darken", "darken"
|
|
||||||
SCREEN = "bm:screen", "screen"
|
|
||||||
XOR = "bm:xor", "xor"
|
|
||||||
SOFTLIGHT = "bm:softlight", "softlight"
|
|
||||||
HARDLIGHT = "bm:hardlight", "hardlight"
|
|
||||||
GRAINEXTRACT = "bm:grainextract", "grainextract"
|
|
||||||
GRAINMERGE = "bm:grainmerge", "grainmerge"
|
|
||||||
DIVIDE = "bm:divide", "divide"
|
|
||||||
HUE = "bm:hue", "hue"
|
|
||||||
SATURATION = "bm:saturation", "saturation"
|
|
||||||
COLOUR = "bm:colour", "colour"
|
|
||||||
LUMINOSITY = "bm:luminosity", "luminosity"
|
|
||||||
PINLIGHT = "bm:pinlight", "pinlight"
|
|
||||||
VIVIDLIGHT = "bm:vividlight", "vividlight"
|
|
||||||
EXCLUSION = "bm:exclusion", "exclusion"
|
|
||||||
DESTIN = "bm:destin", "destin"
|
|
||||||
DESTOUT = "bm:destout", "destout"
|
|
||||||
SRCATOP = "bm:srcatop", "srcatop"
|
|
||||||
DESTATOP = "bm:destatop", "destatop"
|
|
||||||
"""
|
|
||||||
|
|
||||||
NORMAL = "bm:normal", "normal"
|
|
||||||
MULTIPLY = "bm:multiply", "multiply"
|
|
||||||
ADDITIVE = "bm:additive", "additive"
|
|
||||||
COLOURBURN = "bm:colourburn", "colourburn"
|
|
||||||
COLOURDODGE = "bm:colourdodge", "colourdodge"
|
|
||||||
REFLECT = "bm:reflect", "reflect"
|
|
||||||
GLOW = "bm:glow", "glow"
|
|
||||||
OVERLAY = "bm:overlay", "overlay"
|
|
||||||
DIFFERENCE = "bm:difference", "difference"
|
|
||||||
NEGATION = "bm:negation", "negation"
|
|
||||||
LIGHTEN = "bm:lighten", "lighten"
|
|
||||||
DARKEN = "bm:darken", "darken"
|
|
||||||
SCREEN = "bm:screen", "screen"
|
|
||||||
XOR = "bm:xor", "xor"
|
|
||||||
SOFTLIGHT = "bm:softlight", "softlight"
|
|
||||||
HARDLIGHT = "bm:hardlight", "hardlight"
|
|
||||||
GRAINEXTRACT = "bm:grainextract", "grainextract"
|
|
||||||
GRAINMERGE = "bm:grainmerge", "grainmerge"
|
|
||||||
DIVIDE = "bm:divide", "divide"
|
|
||||||
HUE = "bm:hue", "hue"
|
|
||||||
SATURATION = "bm:saturation", "saturation"
|
|
||||||
COLOUR = "bm:colour", "colour"
|
|
||||||
LUMINOSITY = "bm:luminosity", "luminosity"
|
|
||||||
PINLIGHT = "bm:pinlight", "pinlight"
|
|
||||||
VIVIDLIGHT = "bm:vividlight", "vividlight"
|
|
||||||
EXCLUSION = "bm:exclusion", "exclusion"
|
|
||||||
DESTIN = "bm:destin", "destin"
|
|
||||||
DESTOUT = "bm:destout", "destout"
|
|
||||||
SRCATOP = "bm:srcatop", "srcatop"
|
|
||||||
DESTATOP = "bm:destatop", "destatop"
|
|
@ -1,48 +0,0 @@
|
|||||||
"""Do stuff to images to prepare them.
|
|
||||||
"""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
|
|
||||||
from deprecation import deprecated
|
|
||||||
from PIL import Image
|
|
||||||
|
|
||||||
|
|
||||||
@deprecated(deprecated_in="2021.1", removed_in="", details="use renderWAlphaOffset")
|
|
||||||
def rasterImageOA( # pylint:disable=missing-function-docstring
|
|
||||||
image: Image.Image, size: tuple[int, int], alpha: float = 1.0, offsets: tuple[int, int] = (0, 0)
|
|
||||||
) -> Image.Image:
|
|
||||||
warnings.warn(
|
|
||||||
"Call to deprecated function rasterImageOA.", category=DeprecationWarning, stacklevel=2
|
|
||||||
)
|
|
||||||
return renderWAlphaOffset(image, size, alpha, offsets)
|
|
||||||
|
|
||||||
|
|
||||||
@deprecated(deprecated_in="2021.1", removed_in="", details="use renderWAlphaOffset")
|
|
||||||
def rasterImageOffset( # pylint:disable=missing-function-docstring
|
|
||||||
image: Image.Image, size: tuple[int, int], offsets: tuple[int, int] = (0, 0)
|
|
||||||
) -> Image.Image:
|
|
||||||
warnings.warn(
|
|
||||||
"Call to deprecated function rasterImageOffset.", category=DeprecationWarning, stacklevel=2
|
|
||||||
)
|
|
||||||
return renderWAlphaOffset(image, size, 1, offsets)
|
|
||||||
|
|
||||||
|
|
||||||
def renderWAlphaOffset(
|
|
||||||
image: Image.Image, size: tuple[int, int], alpha: float = 1.0, offsets: tuple[int, int] = (0, 0)
|
|
||||||
) -> Image.Image:
|
|
||||||
"""Render an image with offset and alpha to a given size.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
image (Image.Image): pil image to draw
|
|
||||||
size (tuple[int, int]): width, height as a tuple
|
|
||||||
alpha (float, optional): alpha transparency. Defaults to 1.0.
|
|
||||||
offsets (tuple[int, int], optional): x, y offsets as a tuple.
|
|
||||||
Defaults to (0, 0).
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Image.Image: new image
|
|
||||||
"""
|
|
||||||
imageOffset = Image.new("RGBA", size)
|
|
||||||
imageOffset.paste(image.convert("RGBA"), offsets, image.convert("RGBA"))
|
|
||||||
return Image.blend(Image.new("RGBA", size), imageOffset, alpha)
|
|
Loading…
Reference in New Issue
Block a user