Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
image = processor.process(image)
return image
def __eq__(self, other):
if not isinstance(other, (type(self), type(self).base_type())):
return NotImplemented
return super(Pipe, self).__eq__(other)
@export
class Pipeline(MutableSequence):
""" A mutable linear pipeline of processors to be applied en masse.
Derived from a `pilkit` class:
`pilkit.processors.base.ProcessorPipeline`
"""
__slots__ = tuplize('list')
@classmethod
def base_type(cls):
return list
@wraps(list.__init__)
def __init__(self, *args):
base_type = type(self).base_type()
if len(args) == 0:
self.list = base_type()
if len(args) == 1:
target = args[0]
if type(target) is type(self):
self.list = copy(target.list)
elif type(target) is base_type:
self.list = copy(target)
# encoding: utf-8
from __future__ import print_function
from PIL import ImageOps, ImageChops, ImageEnhance as enhancers
from clu.abstract import Slotted
from clu.predicates import tuplize
from instakit.abc import abstract, ABC, Processor
from instakit.exporting import Exporter
exporter = Exporter(path=__file__)
export = exporter.decorator()
@export
class EnhanceNop(ABC, metaclass=Slotted):
__slots__ = tuplize('image')
def __init__(self, image=None):
self.image = image
def adjust(self, *args, **kwargs):
return self.image
@export
class Adjustment(Processor):
""" Base type for image adjustment processors """
__slots__ = tuplize('value')
def __init__(self, value=1.0):
""" Initialize the adjustment with a float value """
self.value = value
""" Normalize contrast throughout the image, via histogram """
__slots__ = tuplize('cutoff', 'ignore')
def __init__(self, cutoff=0, ignore=None):
self.cutoff, self.ignore = cutoff, ignore
def process(self, image):
return ImageOps.autocontrast(image, cutoff=self.cutoff,
ignore=self.ignore)
@export
class Solarize(Processor):
""" Invert all pixel values above an 8-bit threshold """
__slots__ = tuplize('threshold')
def __init__(self, threshold=128):
self.threshold = min(max(1, threshold), 255)
def process(self, image):
return ImageOps.solarize(image, threshold=self.threshold)
@export
class Posterize(Processor):
""" Reduce the number of bits (1 to 8) per channel """
__slots__ = tuplize('bits')
def __init__(self, bits=4):
self.bits = min(max(1, bits), 8)
exporter = Exporter(path=__file__)
export = exporter.decorator()
if not hasattr(__builtins__, 'cmp'):
def cmp(a, b):
return (a > b) - (a < b)
@export
class Pipe(Sequence):
""" A static linear pipeline of processors to be applied en masse.
Derived from a `pilkit` class:
`pilkit.processors.base.ProcessorPipeline`
"""
__slots__ = tuplize('tuple')
@classmethod
def base_type(cls):
return tuple
@wraps(tuple.__init__)
def __init__(self, *args):
self.tuple = tuplize(*args)
def iterate(self):
yield from self.tuple
@wraps(tuple.__len__)
def __len__(self):
return len(self.tuple)
class Equalize(Processor):
""" Apply a non-linear mapping to the image, via histogram """
__slots__ = tuplize('mask')
def __init__(self, mask=None):
self.mask = hasattr(mask, 'copy') and mask.copy() or mask
def process(self, image):
return ImageOps.equalize(image, mask=self.mask)
@export
class AutoContrast(Processor):
""" Normalize contrast throughout the image, via histogram """
__slots__ = tuplize('cutoff', 'ignore')
def __init__(self, cutoff=0, ignore=None):
self.cutoff, self.ignore = cutoff, ignore
def process(self, image):
return ImageOps.autocontrast(image, cutoff=self.cutoff,
ignore=self.ignore)
@export
class Solarize(Processor):
""" Invert all pixel values above an 8-bit threshold """
__slots__ = tuplize('threshold')
def __init__(self, threshold=128):
self.threshold = min(max(1, threshold), 255)
@export
class EnhanceNop(ABC, metaclass=Slotted):
__slots__ = tuplize('image')
def __init__(self, image=None):
self.image = image
def adjust(self, *args, **kwargs):
return self.image
@export
class Adjustment(Processor):
""" Base type for image adjustment processors """
__slots__ = tuplize('value')
def __init__(self, value=1.0):
""" Initialize the adjustment with a float value """
self.value = value
@abstract
def adjust(self, image):
""" Adjust the image, using the float value with which
the adjustment was first initialized
"""
...
def process(self, image):
return (self.value == 1.0) and image or self.adjust(image)
@export
def __init__(self, *args):
self.tuple = tuplize(*args)
image = Enhancement(image).enhance(self.value)
return image
@export
class Invert(Processor):
""" Perform a simple inversion of the image values """
def process(self, image):
return ImageChops.invert(image)
@export
class Equalize(Processor):
""" Apply a non-linear mapping to the image, via histogram """
__slots__ = tuplize('mask')
def __init__(self, mask=None):
self.mask = hasattr(mask, 'copy') and mask.copy() or mask
def process(self, image):
return ImageOps.equalize(image, mask=self.mask)
@export
class AutoContrast(Processor):
""" Normalize contrast throughout the image, via histogram """
__slots__ = tuplize('cutoff', 'ignore')
def __init__(self, cutoff=0, ignore=None):
self.cutoff, self.ignore = cutoff, ignore
>>> bfork = BandFork(None)
>>> bfork['G'] = Atkinson()
>>> bfork.process(my_image)
BandFork inherits from `instakit.abc.Fork`, which itself is not just
an Instakit Processor. The Fork ABC implements the required methods
of an Instakit Processor Container†, through which it furnishes an
interface to individual bands -- also generally known as channels,
per the language of the relevant Photoshop UI elements -- of image
data.
† q.v. the `instakit.abc` module source code supra.
‡ q.v. the `collections.abc` module, and the `MutableMapping`
abstract base class within, supra.
"""
__slots__ = tuplize('mode_t')
def __init__(self, processor_factory, *args, **kwargs):
""" Initialize a BandFork instance, using the given callable value
for `processor_factory` and any band-appropriate keyword-arguments,
e.g. `(R=MyProcessor, G=MyOtherProcessor, B=None)`
"""
# Call `super(…)`, passing `processor_factory`:
super(BandFork, self).__init__(processor_factory, *args, **kwargs)
# Reset `self.mode_t` if a new mode was specified --
# N.B. we can’t use the “self.mode” property during “__init__(…)”:
self.mode_t = kwargs.pop('mode', Mode.RGB)
@property
def mode(self):
return self.mode_t
exporter = Exporter(path=__file__)
export = exporter.decorator()
try:
import six
except ImportError:
class FakeSix(object):
@property
def string_types(self):
return tuple()
six = FakeSix()
export(wrap_value, name='wrap_value')
export(none_function, name='none_function')
export(tuplize, name='tuplize')
export(uniquify, name='uniquify')
export(listify, name='listify')
export(SimpleNamespace)
export(Namespace)
export(stringify, name='stringify')
export(string_types)
export(byte_types)
export(suffix_searcher)
export(u8encode)
export(u8bytes)
export(u8str)
# Assign the modules’ `__all__` and `__dir__` using the exporter: