Commits

Mikhail Korobov committed e28623d

32bit images are unsupported now

  • Participants
  • Parent commits 87a251d

Comments (0)

Files changed (7)

File psd_tools/reader/color_mode_data.py

 # -*- coding: utf-8 -*-
-from __future__ import absolute_import
+from __future__ import absolute_import, unicode_literals, division
 import logging
 from psd_tools.utils import read_fmt
 

File psd_tools/reader/header.py

     if not ColorMode.is_known(header.color_mode):
         warnings.warn("Unknown color mode: %s" % header.color_mode)
 
+    if header.depth != 8:
+        warnings.warn("Bit depth is unsupported (%s)" % header.depth)
+
     logger.debug(header)
     return header

File psd_tools/reader/image_resources.py

         block = _read_block(fp, encoding)
         logger.debug("%r", block)
         blocks.append(block)
+
     return blocks
 
 def _read_block(fp, encoding):

File psd_tools/reader/layers.py

                                      trimmed_repr(self.data))
 
 
-def read(fp, encoding):
+def read(fp, encoding, header):
     """
     Reads layers and masks information.
     """
     length = read_fmt("I", fp)[0]
     start_position = fp.tell()
 
-    layers = _read_layers(fp, encoding)
+    layers = _read_layers(fp, encoding, header.depth)
 
     # XXX: are tagged blocks really after the layers?
     # XXX: does global mask reading really work?
 
     return LayerAndMaskData(layers, global_mask_info)
 
-def _read_layers(fp, encoding):
+def _read_layers(fp, encoding, depth):
     """
     Reads info about layers.
     """
 
     channel_image_data = []
     for layer in layer_records:
-        data = _read_channel_image_data(fp, layer)
+        data = _read_channel_image_data(fp, layer, depth)
         channel_image_data.append(data)
 
     return Layers(length, layer_count, layer_records, channel_image_data)
 
     return LayerBlendingRanges(composite_ranges, channel_ranges)
 
-def _read_channel_image_data(fp, layer):
+def _read_channel_image_data(fp, layer, depth):
     """
     Reads image data for all channels in a layer.
     """
     channel_data = []
 
+    bytes_per_pixel = depth // 8
+
     for channel in layer.channels:
 
         if channel.id == ChannelID.USER_LAYER_MASK:
         compression = read_fmt("H", fp)[0]
 
         if compression == Compression.RAW:
-            data = fp.read(w*h)
+            data_size = w * h * bytes_per_pixel
+            data = fp.read(data_size)
             channel_data.append(ChannelData(compression, data))
 
         elif compression == Compression.PACK_BITS:
             byte_counts = read_be_array("H", h, fp)
-            data = fp.read(sum(byte_counts))
+            data = fp.read(sum(byte_counts) * bytes_per_pixel)
             channel_data.append(ChannelData(compression, data))
 
         elif Compression.is_known(compression):

File psd_tools/reader/reader.py

         header,
         psd_tools.reader.color_mode_data.read(fp),
         psd_tools.reader.image_resources.read(fp, encoding),
-        psd_tools.reader.layers.read(fp, encoding),
+        psd_tools.reader.layers.read(fp, encoding, header),
         psd_tools.reader.layers.read_image_data(fp, header)
     )

File psd_tools/user_api/layers.py

         if set(band_keys) == set(list(mode)):
             return mode
 
-def _channels_data_to_PIL(channels_data, channel_types, size):
+def _channels_data_to_PIL(channels_data, channel_types, size, depth):
     from PIL import Image
     if hasattr(Image, 'frombytes'):
         frombytes = Image.frombytes
         return
 
     bands = {}
+    if depth == 8:
+        pil_depth = 'L'
+    elif depth == 32:
+        pil_depth = 'I'
+    else:
+        warnings.warn("Unsupported depth (%s)" % depth)
+        return
 
     for channel, channel_type in zip(channels_data, channel_types):
 
             warnings.warn("Unsupported channel type (%d)" % channel_type)
             continue
         if channel.compression == Compression.RAW:
-            bands[pil_band] = frombytes("L", size, channel.data, "raw", 'L')
+            bands[pil_band] = frombytes(pil_depth, size, channel.data, "raw", pil_depth)
         elif channel.compression == Compression.PACK_BITS:
-            bands[pil_band] = frombytes("L", size, channel.data, "packbits", 'L')
+            bands[pil_band] = frombytes(pil_depth, size, channel.data, "packbits", pil_depth)
         elif Compression.is_known(channel.compression):
             warnings.warn("Compression method is not implemented (%s)" % channel.compression)
         else:
     channels_data = layers.channel_image_data[layer_index]
     size = layer.width(), layer.height()
     channel_types = [info.id for info in layer.channels]
+    depth = decoded_data.header.depth
 
-    return _channels_data_to_PIL(channels_data, channel_types, size)
+    return _channels_data_to_PIL(channels_data, channel_types, size, depth)
 
 def composite_image_to_PIL(decoded_data):
     header = decoded_data.header
         decoded_data.image_data,
         channel_types,
         size,
+        header.depth
     )

File tests/test_api.py

     ('mask.psd',                (87, 7),      (0xFF, 0xFF, 0xFF)), # mask truncates the layer here
 #    ('note.psd',                (30, 30),     (0, 0, 0)), # what is it?
     ('smart-object-slice.psd',  (70, 80),     (0xAC, 0x19, 0x19)), # XXX: what is this test about?
-    ('transparentbg.psd',       (10, 15),     (0, 0, 0)),
 )
 
 PIXEL_VALUES_32BIT = (
     ('gradient fill.psd',       (10, 15),     (0, 0, 0)),
     ('pen-text.psd',            (30, 30),     (0, 0, 0)),
     ('vector mask.psd',         (10, 15),     (0, 0, 0)),
+    ('transparentbg.psd',       (10, 15),     (0, 0, 0)),
 )
 
 
     assert layer.blend_mode == BlendMode.NORMAL
 
 
-@pytest.mark.parametrize(["filename", "probe_point", "pixel_value"], PIXEL_VALUES + PIXEL_VALUES_32BIT)
-def test_composite_image_pixels(filename, probe_point, pixel_value):
+def _assert_image_pixel(filename, probe_point, pixel_value):
     psd = PSDImage(decode_psd(filename))
     image = psd.composite_image()
     assert image.getpixel(probe_point) == pixel_value
+
+@pytest.mark.parametrize(["filename", "probe_point", "pixel_value"], PIXEL_VALUES)
+def test_composite_image_pixels(filename, probe_point, pixel_value):
+    _assert_image_pixel(filename, probe_point, pixel_value)
+
+@pytest.mark.xfail
+@pytest.mark.parametrize(["filename", "probe_point", "pixel_value"], PIXEL_VALUES_32BIT)
+def test_composite_image_pixels_32bit(filename, probe_point, pixel_value):
+    _assert_image_pixel(filename, probe_point, pixel_value)
+