Skip to content

Commit

Permalink
Merge pull request #104 from psd-tools/1.8.12
Browse files Browse the repository at this point in the history
1.8.12
  • Loading branch information
kyamagu committed Mar 25, 2019
2 parents 490200d + 1a76b91 commit bca07fc
Show file tree
Hide file tree
Showing 9 changed files with 42 additions and 20 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
1.8.12 (2019-03-25)
-------------------

- add apply_icc option in pil io.

1.8.11 (2019-03-14)
-------------------

Expand Down
6 changes: 3 additions & 3 deletions docs/reference/psd_tools.psd.descriptor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ Double
.. autoclass:: psd_tools.psd.descriptor.Double
:members:

Enum
----
Enumerated
----------

.. autoclass:: psd_tools.psd.descriptor.Enum
.. autoclass:: psd_tools.psd.descriptor.Enumerated
:members:

EnumeratedReference
Expand Down
8 changes: 4 additions & 4 deletions src/psd_tools/api/composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def _blend(target, image, offset, mask=None):
return target


def compose(layers, bbox=None, layer_filter=None, color=None):
def compose(layers, bbox=None, layer_filter=None, color=None, **kwargs):
"""
Compose layers to a single :py:class:`PIL.Image`.
If the layers do not have visible pixels, the function returns `None`.
Expand Down Expand Up @@ -129,7 +129,7 @@ def _default_filter(layer):
if intersect(layer.bbox, bbox) == (0, 0, 0, 0):
continue

image = layer.compose()
image = layer.compose(**kwargs)
if image is None:
continue

Expand All @@ -144,12 +144,12 @@ def _default_filter(layer):
return result


def compose_layer(layer, force=False):
def compose_layer(layer, force=False, **kwargs):
"""Compose a single layer with pixels."""
from PIL import Image, ImageChops
assert layer.bbox != (0, 0, 0, 0), 'Layer bbox is (0, 0, 0, 0)'

image = layer.topil()
image = layer.topil(**kwargs)
if image is None or force:
image = create_fill(layer)

Expand Down
10 changes: 5 additions & 5 deletions src/psd_tools/api/layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,14 +329,14 @@ def origination(self):
]
return self._origination

def topil(self):
def topil(self, **kwargs):
"""
Get PIL Image of the layer.
:return: :py:class:`PIL.Image`, or `None` if the layer has no pixels.
"""
if self.has_pixels():
return convert_layer_to_pil(self)
return convert_layer_to_pil(self, **kwargs)
return None

def compose(self, *args, **kwargs):
Expand Down Expand Up @@ -482,14 +482,14 @@ def __setitem__(self, key, value):
def __delitem__(self, key):
return self._layers.__delitem__(key)

def compose(self):
def compose(self, **kwargs):
"""
Compose layer and masks (mask, vector mask, and clipping layers).
:return: PIL Image object, or None if the layer has no pixels.
"""
from psd_tools.api.composer import compose
return compose(self)
return compose(self, **kwargs)

def descendants(self, include_clip=True):
"""
Expand Down Expand Up @@ -858,7 +858,7 @@ def __init__(self, *args):
if hasattr(self.__class__, '_KEY'):
self._data = self.tagged_blocks.get_data(self.__class__._KEY)

def compose(self):
def compose(self, **kwargs):
"""
Adjustment layer is never composed.
Expand Down
8 changes: 4 additions & 4 deletions src/psd_tools/api/pil_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def extract_pil_mode(psd):
return get_pil_mode(psd.header.color_mode, alpha)


def convert_image_data_to_pil(psd):
def convert_image_data_to_pil(psd, apply_icc=True, **kwargs):
"""Convert ImageData to PIL Image."""
from PIL import Image, ImageOps
header = psd.header
Expand All @@ -57,14 +57,14 @@ def convert_image_data_to_pil(psd):
image = Image.merge(mode, channels[:(len(channels) - alpha)])
if mode == 'CMYK':
image = image.point(lambda x: 255 - x)
if 'ICC_PROFILE' in psd.image_resources:
if apply_icc and 'ICC_PROFILE' in psd.image_resources:
image = _apply_icc(image, psd.image_resources.get_data('ICC_PROFILE'))
if alpha and mode in ('L', 'RGB'):
image.putalpha(channels[-1])
return _remove_white_background(image)


def convert_layer_to_pil(layer):
def convert_layer_to_pil(layer, apply_icc=True, **kwargs):
"""Convert Layer to PIL Image."""
from PIL import Image
header = layer._psd._record.header
Expand Down Expand Up @@ -95,7 +95,7 @@ def convert_layer_to_pil(layer):
else:
logger.debug('Alpha channel is not supported in %s' % (mode))

if 'ICC_PROFILE' in layer._psd.image_resources:
if apply_icc and 'ICC_PROFILE' in layer._psd.image_resources:
image = _apply_icc(
image, layer._psd.image_resources.get_data('ICC_PROFILE')
)
Expand Down
15 changes: 12 additions & 3 deletions src/psd_tools/api/psd_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,15 +114,15 @@ def save(self, fp, mode='wb'):
with open(fp, mode) as f:
self._record.write(f)

def topil(self):
def topil(self, **kwargs):
"""
Get PIL Image.
:return: :py:class:`PIL.Image`, or `None` if the composed image is not
available.
"""
if self.has_preview():
return pil_io.convert_image_data_to_pil(self._record)
return pil_io.convert_image_data_to_pil(self._record, **kwargs)
return None

def compose(self, force=False, bbox=None, **kwargs):
Expand All @@ -135,7 +135,9 @@ def compose(self, force=False, bbox=None, **kwargs):
:return: :py:class:`PIL.Image`, or `None` if there is no pixel.
"""
from psd_tools.api.composer import compose
image = self.topil() if (not force or len(self) == 0) else None
image = None
if not force or len(self) == 0:
image = self.topil(**kwargs)
if image is None:
image = compose(self, bbox=bbox or self.viewbox, **kwargs)
return image
Expand Down Expand Up @@ -348,6 +350,13 @@ def image_resources(self):
version_info = psd.image_resources.get_data('VERSION_INFO')
slices = psd.image_resources.get_data('SLICES')
Image resources contain an ICC profile. The following shows how to
export a PNG file with embedded ICC profile::
icc_profile = psd.image_resources.get_data('ICC_PROFILE')
image = psd.compose(apply_icc=False)
image.save('output.png', icc_profile=icc_profile)
"""
return self._record.image_resources

Expand Down
2 changes: 1 addition & 1 deletion src/psd_tools/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '1.8.11'
__version__ = '1.8.12'
Binary file not shown.
8 changes: 8 additions & 0 deletions tests/psd_tools/api/test_composer.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,11 @@ def test_compose_artboard():
artboard_image = artboard.compose()
assert artboard_image.size == artboard.size
assert artboard.size != extract_bbox(artboard)


def test_apply_icc_profile():
filepath = full_name('colorprofiles/north_america_newspaper.psd')
psd = PSDImage.open(filepath)
no_icc = psd.compose(apply_icc=False)
with_icc = psd.compose(apply_icc=True)
assert no_icc.getextrema() != with_icc.getextrema()

0 comments on commit bca07fc

Please sign in to comment.