def create_fill(layer): from PIL import Image mode = get_pil_mode(layer._psd.color_mode, True) size = (layer.width, layer.height) fill_image = None stroke = layer.tagged_blocks.get_data(Tag.VECTOR_STROKE_DATA) # Apply fill. if Tag.VECTOR_STROKE_CONTENT_DATA in layer.tagged_blocks: setting = layer.tagged_blocks.get_data(Tag.VECTOR_STROKE_CONTENT_DATA) if stroke and bool(stroke.get('fillEnabled', True)) is False: fill_image = Image.new(mode, size) elif Enum.Pattern in setting: fill_image = draw_pattern_fill(size, layer._psd, setting) elif Key.Gradient in setting: fill_image = draw_gradient_fill(size, setting) else: fill_image = draw_solid_color_fill(size, setting) elif Tag.SOLID_COLOR_SHEET_SETTING in layer.tagged_blocks: setting = layer.tagged_blocks.get_data(Tag.SOLID_COLOR_SHEET_SETTING) fill_image = draw_solid_color_fill(size, setting) elif Tag.PATTERN_FILL_SETTING in layer.tagged_blocks: setting = layer.tagged_blocks.get_data(Tag.PATTERN_FILL_SETTING) fill_image = draw_pattern_fill(size, layer._psd, setting) elif Tag.GRADIENT_FILL_SETTING in layer.tagged_blocks: setting = layer.tagged_blocks.get_data(Tag.GRADIENT_FILL_SETTING) fill_image = draw_gradient_fill(size, setting) return fill_image
def create_stroke_effect(alpha, setting, psd, mask_given=False): offset = alpha.info['offset'] if mask_given: mask = alpha else: mask = create_stroke_mask(alpha, setting) paint = setting.get(Key.PaintType).enum if paint == Enum.SolidColor: result = draw_solid_color_fill(mask.size, setting) elif paint == Enum.GradientFill: result = draw_gradient_fill(mask.size, setting) elif paint == Enum.Pattern: result = draw_pattern_fill(mask.size, psd, setting) result.putalpha(mask) result.info['offset'] = offset return result
def test_draw_gradient_fill(): psd = PSDImage.open(full_name('layers-minimal/gradient-fill.psd')) setting = psd[0].tagged_blocks.get_data(Tag.GRADIENT_FILL_SETTING) draw_gradient_fill(psd.size, setting) for angle in (-90., 0., 90., 180.): setting.get(Key.Angle.value).value = angle draw_gradient_fill(psd.size, setting) setting.get(b'Type').enum = Enum.Radial.value draw_gradient_fill(psd.size, setting)
def apply_effect(layer, backdrop, base_image): """Apply effect to the image. ..note: Correct effect order is the following. All the effects are first applied to the original image then blended together. * dropshadow * outerglow * (original) * patternoverlay * gradientoverlay * coloroverlay * innershadow * innerglow * bevelemboss * satin * stroke """ from PIL import ImageChops for effect in layer.effects: if effect.__class__.__name__ == 'PatternOverlay': image = draw_pattern_fill(base_image.size, layer._psd, effect.value) if base_image.mode.endswith('A'): alpha = base_image.getchannel('A') if image.mode.endswith('A'): alpha = ImageChops.darker(alpha, image.getchannel('A')) image.putalpha(alpha) backdrop = blend(backdrop, image, (0, 0), effect.blend_mode) for effect in layer.effects: if effect.__class__.__name__ == 'GradientOverlay': image = draw_gradient_fill(base_image.size, effect.value) if base_image.mode.endswith('A'): alpha = base_image.getchannel('A') if image.mode.endswith('A'): alpha = ImageChops.darker(alpha, image.getchannel('A')) image.putalpha(alpha) backdrop = blend(backdrop, image, (0, 0), effect.blend_mode) for effect in layer.effects: if effect.__class__.__name__ == 'ColorOverlay': image = draw_solid_color_fill(base_image.size, effect.value) if base_image.mode.endswith('A'): alpha = base_image.getchannel('A') if image.mode.endswith('A'): alpha = ImageChops.darker(alpha, image.getchannel('A')) image.putalpha(alpha) backdrop = blend(backdrop, image, (0, 0), effect.blend_mode) for effect in layer.effects: if effect.__class__.__name__ == 'Stroke': from PIL import ImageOps if layer.has_vector_mask(): alpha = draw_vector_mask(layer) elif base_image.mode.endswith('A'): alpha = base_image.getchannel('A') else: alpha = base_image.convert('L') alpha.info['offset'] = base_image.info['offset'] flat = alpha.getextrema()[0] < 255 # Expand the image size setting = effect.value size = int(setting.get(Key.SizeKey)) offset = backdrop.info['offset'] backdrop = ImageOps.expand(backdrop, size) backdrop.info['offset'] = tuple(x - size for x in offset) offset = alpha.info['offset'] alpha = ImageOps.expand(alpha, size) alpha.info['offset'] = tuple(x - size for x in offset) if not layer.has_vector_mask() and setting.get( Key.Style).enum == Enum.InsetFrame and flat: image = create_stroke_effect(alpha, setting, layer._psd, True) backdrop.paste(image) else: image = create_stroke_effect(alpha, setting, layer._psd) backdrop = blend(backdrop, image, (0, 0), effect.blend_mode) return backdrop