class Sharpen(Layer): ___ = Layer.Register('sharpen', lambda d: Sharpen(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.amount = Layer.arg(d) def apply(self, ctxt, image): return ImageEnhance.Sharpness(image).enhance(self.amount)
class Contrast(Layer): ___ = Layer.Register('contrast', lambda d: Contrast(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.amount = Layer.arg(d) def apply(self, ctxt, image): return ImageEnhance.Contrast(image).enhance(self.amount)
class ChangeHue(Layer): ___ = Layer.Register('hue', lambda d: ChangeHue(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.color = Layer.arg(d) self.range = self.attr('range', [.2, .5]) def apply(self, ctxt, image): return change_hue(image, self.color, self.range)
class Mask(Layer): ___ = Layer.Register('mask', lambda d: Mask(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.color = Layer.arg(d) def apply(self, ctxt, image): image = image.convert('RGBA') solid = Image.new('RGBA', image.size, self.color) mask = Image.new('RGBA', image.size, None) mask.paste(solid, (0, 0), image) return mask
class Opacity(Layer): ___ = Layer.Register('opacity', lambda d: Opacity(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.opacity = min(Layer.arg(d), 100.0) / 100.0 def apply(self, ctxt, image): if self.verbose: print(' Opacity: ', self.opacity, '%') a = np.array(image) a = a.T a[3] = (a[3] * self.opacity) return Image.fromarray(a.T)
class Halo(Layer): ___ = Layer.Register('halo', lambda d: Halo(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.color = Layer.arg(d) self.radius = self.attr('gauss-blur-radius', 2) def apply(self, ctxt, image): mask = Mask({'mask': self.color, 'ctor': 'mask'}) im = mask.apply(ctxt, image) im = im.filter(ImageFilter.GaussianBlur(self.radius)) im = Image.composite(im, image, ImageChops.invert(im)) return im.filter(ImageFilter.Kernel((3, 3), bloomKernel, 1, 0))
class Flip(Layer): Func = { 'HORIZONTAL': ImageOps.mirror, 'VERTICAL': ImageOps.flip, 'H': ImageOps.mirror, 'V': ImageOps.flip } ___ = Layer.Register('flip', lambda d: Flip(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.mode = Layer.arg(d) def apply(self, ctxt, image): return Flip.Func[self.mode](image)
class Dots(Layer): ___ = Layer.Register('dots', lambda d: Dots(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.color = Layer.arg(d) self.r1 = self.attr('radius', 2) self.r2 = self.attr('distance', 5) + self.r1 self.grad = self.attr('grad', True) self.opacity = int(255 * min(self.attr('opacity', 100.0), 100.0) / 100.0) assert self.attr('box') self.attr('units') def apply(self, ctxt, image): dots(image, self.box, self.r1, self.r2, self.color, self.grad, self.opacity) return image
class Filter(Layer): Names = { 'BLUR': ImageFilter.BLUR, 'CONTOUR': ImageFilter.CONTOUR, 'DETAIL': ImageFilter.DETAIL, 'EDGE_ENHANCE': ImageFilter.EDGE_ENHANCE, 'EDGE_ENHANCE_MORE': ImageFilter.EDGE_ENHANCE_MORE, 'FIND_EDGES': ImageFilter.FIND_EDGES, 'SHARPEN': ImageFilter.SHARPEN, 'SMOOTH': ImageFilter.SMOOTH, 'SMOOTH_MORE': ImageFilter.SMOOTH_MORE } ___ = Layer.Register('filter', lambda d: Filter(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.filter = Layer.arg(d) def apply(self, ctxt, image): return image.filter(Filter.Names[self.filter])
class Crop(Layer): GetOrigin = { 'CENTER': lambda s, b: [(x - y) / 2 for x, y in zip(s, b[2:])], 'NW': lambda s, b: [0, 0], 'NE': lambda s, b: [s[0] - b[2], 0], 'SW': lambda s, b: [0, s[1]], 'SE': lambda s, b: [(x - y) for x, y in zip(s, b[2:])], } ___ = Layer.Register('crop', lambda d: Crop(d)) def __init__(self, d, verbose=False): Layer.__init__(self, d, verbose) self.origin = Layer.arg(d) assert self.attr('box') self.attr('units') def apply(self, ctxt, image): box = self.box.convert(image.size).box orig = Crop.GetOrigin[self.origin](image.size, box) box = [x + o for x, o in zip(box, orig + orig)] if self.verbose: print(' Cropbox:', self.box, box, 'alignment=' + self.origin) return image.crop(box)
class AutoCrop(Layer): ___ = Layer.Register('auto-crop', lambda d: AutoCrop(d)) def __init__(self, d={}, name='image', verbose=False): self.name = name Layer.__init__(self, d, verbose) self.i = Layer.arg(d) self.threshold = self.attr('threshold', 200) self.imgs = {} self.mod = None def clone(self, d): obj = Layer.clone(self, d) obj.imgs = self.imgs return obj def down(self, im, threshold): a = np.array(im) a = a.T f = np.all(np.mean(a, axis=0) >= threshold, axis=0) y = min(np.nonzero(f)) if len(y): y = min(y) return [ self.cut(im.crop((0, 0, im.size[0], y)), threshold), self.cut(im.crop((0, y, im.size[0], im.size[1])), threshold) ] def across(self, im, threshold): a = np.array(im) a = a.T f = np.all(np.mean(a, axis=0) >= threshold, axis=1) x = min(np.nonzero(f)) if len(x): x = min(x) return [ self.cut(im.crop((0, 0, x, im.size[1])), threshold), self.cut(im.crop((x, 0, im.size[0], im.size[1])), threshold) ] @property def count(self): return len(self.imgs) def cut(self, im, threshold): im = autocrop(im, threshold) if not self.down(im, threshold) and not self.across(im, threshold): name = path.splitext(self.name)[0] + str(self.count).zfill(3) self.imgs[name] = im return self.imgs def apply(self, ctxt, image): if self.mod: self.mod.verbose = self.verbose return self.mod.apply(image) if len(self.imgs) == 0: self.cut(image, self.threshold) if self.verbose: print(' Cropped:', len(self.imgs), 'images') if self.verbose: print(' Indexing:', self.i, '/', len(self.imgs)) try: return self.imgs[self.i] except KeyError as e: print(e) return self.errorImage(e)