Example #1
0
def _get_band_images(channel_data, channel_ids, color_mode, size, depth):
    bands = {}
    for channel, channel_id in zip(channel_data, channel_ids):

        pil_band = _channel_id_to_PIL(channel_id, color_mode)
        if pil_band is None:
            warnings.warn("Unsupported channel type (%d)" % channel_id)
            continue

        if channel.compression in [Compression.RAW, Compression.ZIP, Compression.ZIP_WITH_PREDICTION]:
            if depth == 8:
                im = _from_8bit_raw(channel.data, size)
            elif depth == 16:
                im = _from_16bit_raw(channel.data, size)
            elif depth == 32:
                im = _from_32bit_raw(channel.data, size)
            else:
                warnings.warn("Unsupported depth (%s)" % depth)
                continue

        elif channel.compression == Compression.PACK_BITS:
            if depth != 8:
                warnings.warn("Depth %s is unsupported for PackBits compression" % depth)
                continue
            im = frombytes('L', size, channel.data, "packbits", 'L')
        else:
            if Compression.is_known(channel.compression):
                warnings.warn("Compression method is not implemented (%s)" % channel.compression)
            else:
                warnings.warn("Unknown compression method (%s)" % channel.compression)
            continue

        bands[pil_band] = im.convert('L')
    return bands
Example #2
0
def _get_band_images(channel_data, channel_ids, color_mode, size, depth):
    bands = {}
    for channel, channel_id in zip(channel_data, channel_ids):

        pil_band = _channel_id_to_PIL(channel_id, color_mode)
        if pil_band is None:
            warnings.warn("Unsupported channel type (%d)" % channel_id)
            continue

        if channel.compression in [Compression.RAW, Compression.ZIP, Compression.ZIP_WITH_PREDICTION]:
            if depth == 8:
                im = _from_8bit_raw(channel.data, size)
            elif depth == 16:
                im = _from_16bit_raw(channel.data, size)
            elif depth == 32:
                im = _from_32bit_raw(channel.data, size)
            else:
                warnings.warn("Unsupported depth (%s)" % depth)
                continue

        elif channel.compression == Compression.PACK_BITS:
            if depth != 8:
                warnings.warn("Depth %s is unsupported for PackBits compression" % depth)
                continue
            im = frombytes('L', size, channel.data, "packbits", 'L')
        else:
            if Compression.is_known(channel.compression):
                warnings.warn("Compression method is not implemented (%s)" % channel.compression)
            else:
                warnings.warn("Unknown compression method (%s)" % channel.compression)
            continue

        bands[pil_band] = im.convert('L')
    return bands
Example #3
0
def _decompress_channel(channel, depth, size):
    if channel.compression in (Compression.RAW, Compression.ZIP,
                               Compression.ZIP_WITH_PREDICTION):
        if depth == 8:
            im = _from_8bit_raw(channel.data, size)
        elif depth == 16:
            im = _from_16bit_raw(channel.data, size)
        elif depth == 32:
            im = _from_32bit_raw(channel.data, size)
        else:
            warnings.warn("Unsupported depth (%s)" % depth)
            return None

    elif channel.compression == Compression.PACK_BITS:
        if depth != 8:
            warnings.warn("Depth %s is unsupported for PackBits compression" %
                          depth)
        im = frombytes('L', size, channel.data, "packbits", 'L')
    else:
        if Compression.is_known(channel.compression):
            warnings.warn("Compression method is not implemented "
                          "(%s)" % channel.compression)
        else:
            warnings.warn("Unknown compression method (%s)" %
                          channel.compression)
        return None
    return im.convert('L')
Example #4
0
 def set_data(self, size, data, depth, compression=0, version=1):
     self.data = compress(data, compression, size[0], size[1], depth,
                          version)
     self.depth = int(depth)
     self.pixel_depth = int(depth)
     self.rectangle = (0, 0, int(size[1]), int(size[0]))
     self.compression = Compression(compression)
     self.is_written = True
Example #5
0
    def read(cls, fp):
        """Read the element from a file-like object.

        :param fp: file-like object
        :rtype: :py:class:`.ChannelData`
        """
        compression = Compression(read_fmt('H', fp)[0])
        data = fp.read()
        return cls(compression, data)
Example #6
0
def read_image_data(fp, header):
    """
    Reads merged image pixel data which is stored at the end of PSD file.
    """
    w, h = header.width, header.height
    bytes_per_pixel = header.depth // 8
    compress_type = read_fmt("H", fp)[0]

    logger.debug('reading composite image data...')
    logger.debug('  start_pos=%s, compress_type=%s',
                 fp.tell() - 2, Compression.name_of(compress_type))

    if compress_type == Compression.RAW:
        data_size = w * h * bytes_per_pixel
        logger.debug('  data size = %sx%sx%s=%s bytes', w, h, bytes_per_pixel, data_size)

    elif compress_type == Compression.PACK_BITS:
        channel_byte_counts = []
        for _ in range(header.number_of_channels):
            channel_byte_counts.append(read_be_array("H", h, fp))

    # are there any ZIP-encoded composite images in a wild?
    elif compress_type in (Compression.ZIP, Compression.ZIP_WITH_PREDICTION):
        warnings.warn(
            "%s compression of composite image is not supported." %
            Compression.name_of(compress_type)
        )
        return []

    else:
        warnings.warn("Bad compression type %s" % compress_type)
        return []

    channel_data = []
    for channel_id in range(header.number_of_channels):
        if compress_type == Compression.PACK_BITS:
            byte_counts = channel_byte_counts[channel_id]
            data_size = sum(byte_counts)
            logger.debug('  data size = %s bytes', data_size)

        data = fp.read(data_size)
        channel_data.append(ChannelData(compress_type, data))

    return channel_data
Example #7
0
def _channels_data_to_PIL(channels_data, channel_types, size, depth, icc_profile):
    if Image is None:
        raise Exception("This module requires PIL (or Pillow) installed.")

    if size == (0, 0):
        return

    bands = {}

    for channel, channel_type in zip(channels_data, channel_types):
        pil_band = channel_id_to_PIL(channel_type)
        if pil_band is None:
            warnings.warn("Unsupported channel type (%d)" % channel_type)
            continue

        if channel.compression in [Compression.RAW, Compression.ZIP, Compression.ZIP_WITH_PREDICTION]:
            if depth == 8:
                im = _from_8bit_raw(channel.data, size)
            elif depth == 16:
                im = _from_16bit_raw(channel.data, size)
            elif depth == 32:
                im = _from_32bit_raw(channel.data, size)
            else:
                warnings.warn("Unsupported depth (%s)" % depth)
                continue

        elif channel.compression == Compression.PACK_BITS:
            if depth != 8:
                warnings.warn("Depth %s is unsupported for PackBits compression" % depth)
                continue
            im = frombytes('L', size, channel.data, "packbits", 'L')

        else:
            if Compression.is_known(channel.compression):
                warnings.warn("Compression method is not implemented (%s)" % channel.compression)
            else:
                warnings.warn("Unknown compression method (%s)" % channel.compression)
            continue

        bands[pil_band] = im.convert('L')

    mode = _get_mode(bands.keys())
    merged_image = Image.merge(mode, [bands[band] for band in mode])

    if mode == 'CMYK':
        # invert CMYK data
        merged_image = frombytes('CMYK', size, merged_image.tobytes(), 'raw',
                                 'CMYK;I')
        # convert with inner profile, better brightness
        merged_image = merged_image.convert('RGB')

    elif icc_profile is not None:
        display_profile = ImageCms.createProfile('sRGB') # XXX: ImageCms.get_display_profile()?
        ImageCms.profileToProfile(merged_image, icc_profile, display_profile, inPlace=True)

    return merged_image
Example #8
0
    def read(cls, fp):
        """Read the element from a file-like object.

        :param fp: file-like object
        :rtype: :py:class:`.ImageData`
        """
        start_pos = fp.tell()
        compression = Compression(read_fmt('H', fp)[0])
        data = fp.read()  # TODO: Parse data here. Need header.
        logger.debug('  read image data, len=%d' % (fp.tell() - start_pos))
        return cls(compression, data)
Example #9
0
def _channels_data_to_PIL(channels_data, channel_types, size, depth, icc_profile):
    if Image is None:
        raise Exception("This module requires PIL (or Pillow) installed.")

    if size == (0, 0):
        return

    bands = {}

    for channel, channel_type in zip(channels_data, channel_types):

        pil_band = channel_id_to_PIL(channel_type)
        if pil_band is None:
            warnings.warn("Unsupported channel type (%d)" % channel_type)
            continue

        if channel.compression in [Compression.RAW, Compression.ZIP, Compression.ZIP_WITH_PREDICTION]:
            if depth == 8:
                im = _from_8bit_raw(channel.data, size)
            elif depth == 16:
                im = _from_16bit_raw(channel.data, size)
            elif depth == 32:
                im = _from_32bit_raw(channel.data, size)
            else:
                warnings.warn("Unsupported depth (%s)" % depth)
                continue

        elif channel.compression == Compression.PACK_BITS:
            if depth != 8:
                warnings.warn("Depth %s is unsupported for PackBits compression" % depth)
                continue
            im = frombytes('L', size, channel.data, "packbits", 'L')
        else:
            if Compression.is_known(channel.compression):
                warnings.warn("Compression method is not implemented (%s)" % channel.compression)
            else:
                warnings.warn("Unknown compression method (%s)" % channel.compression)
            continue

        bands[pil_band] = im.convert('L')

    mode = _get_mode(bands.keys())
    merged_image = Image.merge(mode, [bands[band] for band in mode])

    if icc_profile is not None:
        display_profile = ImageCms.createProfile('sRGB') # XXX: ImageCms.get_display_profile()?
        ImageCms.profileToProfile(merged_image, icc_profile, display_profile, inPlace=True)

    return merged_image
Example #10
0
def _decompress_pattern_channel(channel):
    depth = channel.depth
    size = (channel.rectangle[3], channel.rectangle[2])
    if channel.compression in (Compression.RAW, Compression.ZIP,
                               Compression.ZIP_WITH_PREDICTION):
        if depth == 8:
            im = _from_8bit_raw(channel.data.value, size)
        elif depth == 16:
            im = _from_16bit_raw(channel.data.value, size)
        elif depth == 32:
            im = _from_32bit_raw(channel.data.value, size)
        else:
            warnings.warn("Unsupported depth (%s)" % depth)
            return None
    elif channel.compression == Compression.PACK_BITS:
        if depth != 8:
            warnings.warn(
                "Depth %s is unsupported for PackBits compression" % depth)
        try:
            import packbits
            channel_data = packbits.decode(channel.data.value)
        except ImportError as e:
            warnings.warn("Install packbits (%s)" % e)
            channel_data = b'\x00' * (size[0] * size[1])  # Default fill
        except IndexError as e:
            warnings.warn("Failed to decode pattern (%s)" % e)
            channel_data = b'\x00' * (size[0] * size[1])  # Default fill
        # Packbit pattern tends not to have the correct size ???
        padding = len(channel_data) - size[0] * size[1]
        if padding < 0:
            warnings.warn('Broken pattern data (%g for %g)' % (
                len(channel_data), size[0] * size[1]))
            channel_data += b'\x00' * -padding  # Append default fill
            padding = 0
        im = frombytes('L', size, channel_data[padding:], "raw", 'L')
    else:
        if Compression.is_known(channel.compression):
            warnings.warn(
                "Compression method is not implemented "
                "(%s)" % channel.compression)
        else:
            warnings.warn(
                "Unknown compression method (%s)" % channel.compression)
        return None
    return im.convert('L')
Example #11
0
 def read(cls, fp):
     start_pos = fp.tell()
     compression = Compression(read_fmt('H', fp)[0])
     data = fp.read()  # TODO: Parse data here. Need header.
     logger.debug('  read image data, len=%d' % (fp.tell() - start_pos))
     return cls(compression, data)
Example #12
0
def _get_band_images(layer, channel_data, channel_ids, color_mode, size,
                     depth):
    bands = {}
    for channel, channel_id in zip(channel_data, channel_ids):
        im = None
        mask_im = None
        mask_size = None
        pil_band = _channel_id_to_PIL(channel_id, color_mode)
        if pil_band is None:
            warnings.warn("Unsupported channel type (%d)" % channel_id)
            continue

        if channel.compression in [
                Compression.RAW, Compression.ZIP,
                Compression.ZIP_WITH_PREDICTION
        ]:
            if pil_band == 'M':
                mask_size = (channel.mask_data.width(),
                             channel.mask_data.height())
                if mask_size[0] == 0 or mask_size[1] == 0:
                    # warnings.warn("Empty layer mask found on layer '%s', ignoring it." % layer.name)
                    continue
                try:
                    mask_im = _from_8bit_raw(channel.data, mask_size)
                except Exception as e:
                    warnings.warn("Failed parsing layer mask! " + str(e))
                    continue
            elif depth == 8:
                im = _from_8bit_raw(channel.data, size)
            elif depth == 16:
                im = _from_16bit_raw(channel.data, size)
            elif depth == 32:
                im = _from_32bit_raw(channel.data, size)
            else:
                warnings.warn("Unsupported depth (%s)" % depth)
                continue

        elif channel.compression == Compression.PACK_BITS:
            if depth != 8:
                warnings.warn(
                    "Depth %s is unsupported for PackBits compression" % depth)
                continue
            if pil_band == 'M':
                mask_size = (channel.mask_data.width(),
                             channel.mask_data.height())
                if mask_size[0] == 0 or mask_size[1] == 0:
                    # warnings.warn("Empty layer mask found on layer '%s', ignoring it." % layer.name)
                    continue
                try:
                    mask_im = frombytes('L', mask_size, channel.data,
                                        "packbits", 'L')
                except Exception as e:
                    warnings.warn("Failed parsing layer mask! " + str(e))
                    continue
            else:
                im = frombytes('L', size, channel.data, "packbits", 'L')
        else:
            if Compression.is_known(channel.compression):
                warnings.warn("Compression method is not implemented (%s)" %
                              channel.compression)
            else:
                warnings.warn("Unknown compression method (%s)" %
                              channel.compression)
            continue
        if pil_band == 'M':
            if layer_mask_callback(layer) == False:
                continue
            im = Image.new('L', size, 255)
            offset = (channel.mask_data.left - layer.left,
                      channel.mask_data.top - layer.top)
            im.paste(mask_im, offset)

        bands[pil_band] = im.convert('L')
    return bands
Example #13
0
 def __repr__(self):
     return "ChannelData(compression=%r %s, len(data)=%r)" % (
         self.compression, Compression.name_of(self.compression),
         len(self.data) if self.data is not None else None
     )
Example #14
0
 def read(cls, fp, length=0, **kwargs):
     compression = Compression(read_fmt('H', fp)[0])
     data = fp.read(length)
     return cls(compression, data)
Example #15
0
 def read(cls, fp):
     compression = Compression(read_fmt('H', fp)[0])
     data = fp.read()
     return cls(compression, data)
Example #16
0
def _read_channel_image_data(fp, layer, depth):
    """
    Reads image data for all channels in a layer.
    """
    bytes_per_pixel = depth // 8
    channel_data = []

    for channel in layer.channels:
        logger.debug("  reading %s", channel)

        if channel.id == ChannelID.USER_LAYER_MASK:
            w, h = layer.mask_data.width(), layer.mask_data.height()
        elif channel.id == ChannelID.REAL_USER_LAYER_MASK:
            w, h = layer.mask_data.real_width(), layer.mask_data.real_height()
        else:
            w, h = layer.width(), layer.height()

        start_pos = fp.tell()
        compress_type = read_fmt("H", fp)[0]

        logger.debug("    start_pos=%s, compress_type=%s",
                     start_pos, Compression.name_of(compress_type))

        # read or calculate data size
        if compress_type == Compression.RAW:
            data_size = w * h * bytes_per_pixel
            logger.debug('    data size = %sx%sx%s=%s bytes', w, h, bytes_per_pixel, data_size)

        elif compress_type == Compression.PACK_BITS:
            byte_counts = read_be_array("H", h, fp)
            data_size = sum(byte_counts)
            logger.debug('    data size = %s bytes', data_size)

        elif compress_type in (Compression.ZIP, Compression.ZIP_WITH_PREDICTION):
            data_size = channel.length - 2
            logger.debug('    data size = %s-2=%s bytes', channel.length, data_size)

        else:
            warnings.warn("Bad compression type %s" % compress_type)
            return []

        # read the data itself
        if data_size > channel.length:
            warnings.warn("Incorrect data size: %s > %s" % (data_size, channel.length))
        else:
            data = fp.read(data_size)
            if compress_type == Compression.ZIP:
                data = zlib.decompress(data)
            elif compress_type == Compression.ZIP_WITH_PREDICTION:
                data = zlib.decompress(data)
                data = compression.decode_prediction(data, w, h, bytes_per_pixel)
                if data is None:
                    warnings.warn("Prediction decode failed!")
                    return []

            channel_data.append(ChannelData(compress_type, data))

        remaining_length = channel.length - (fp.tell() - start_pos)
        if remaining_length > 0:
            fp.seek(remaining_length, 1)
            logger.debug('    skipping %s bytes', remaining_length)

    return channel_data
Example #17
0
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 idx, channel in enumerate(layer.channels):
        logger.debug("  reading %s", channel)
        if channel.id == ChannelID.USER_LAYER_MASK:
            w, h = layer.mask_data.width(), layer.mask_data.height()
        else:
            w, h = layer.width(), layer.height()

        start_pos = fp.tell()
        compress_type = read_fmt("H", fp)[0]

        logger.debug("    start_pos=%s, compress_type=%s",
                     start_pos, Compression.name_of(compress_type))

        data = None

        # read data size
        if compress_type == Compression.RAW:
            data_size = w * h * bytes_per_pixel
            logger.debug('    data size = %sx%sx%s=%s bytes', w, h, bytes_per_pixel, data_size)

        elif compress_type == Compression.PACK_BITS:
            byte_counts = read_be_array("H", h, fp)
            sum_counts = sum(byte_counts)
            data_size = sum_counts * bytes_per_pixel
            logger.debug('    data size = %sx%s=%s bytes', sum_counts, bytes_per_pixel, data_size)

        elif compress_type == Compression.ZIP:
            data_size = channel.length - 2
            logger.debug('    data size = %s-2=%s bytes', channel.length, data_size)

        elif compress_type == Compression.ZIP_WITH_PREDICTION:
            data_size = channel.length - 2
            logger.debug('    data size = %s-2=%s bytes', channel.length, data_size)

        else:
            warnings.warn("Bad compression type %s" % compress_type)
            return []

        # read the data itself
        if data_size > channel.length:
            warnings.warn("Incorrect data size: %s > %s" % (data_size, channel.length))
        else:
            raw_data = fp.read(data_size)
            if compress_type in (Compression.RAW, Compression.PACK_BITS):
                data = raw_data
            elif compress_type == Compression.ZIP:
                data = zlib.decompress(raw_data)
            elif compress_type == Compression.ZIP_WITH_PREDICTION:
                decompressed = zlib.decompress(raw_data)
                data = compression.decode_prediction(decompressed, w, h, bytes_per_pixel)

            if data is None:
                return []

            channel_data.append(ChannelData(compress_type, data))

        remaining_bytes = channel.length - (fp.tell() - start_pos) - 2
        if remaining_bytes > 0:
            fp.seek(remaining_bytes, 1)
            logger.debug('    skipping %s bytes', remaining_bytes)

    return channel_data
Example #18
0
 def __repr__(self):
     return "ChannelData(compression=%r %s, len(data)=%r)" % (
         self.compression, Compression.name_of(self.compression),
         len(self.data) if self.data is not None else None)
Example #19
0
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 idx, channel in enumerate(layer.channels):
        logger.debug("  reading %s", channel)
        if channel.id == ChannelID.USER_LAYER_MASK:
            w, h = layer.mask_data.width(), layer.mask_data.height()
        elif channel.id == ChannelID.REAL_USER_LAYER_MASK:
            w, h = layer.mask_data.real_width(), layer.mask_data.real_height()
        else:
            w, h = layer.width(), layer.height()

        start_pos = fp.tell()
        compress_type = read_fmt("H", fp)[0]

        logger.debug("    start_pos=%s, compress_type=%s", start_pos,
                     Compression.name_of(compress_type))

        data = None

        # read data size
        if compress_type == Compression.RAW:
            data_size = w * h * bytes_per_pixel
            logger.debug('    data size = %sx%sx%s=%s bytes', w, h,
                         bytes_per_pixel, data_size)

        elif compress_type == Compression.PACK_BITS:
            byte_counts = read_be_array("H", h, fp)
            data_size = sum(byte_counts)
            logger.debug('    data size = %s bytes', data_size)

        elif compress_type in (Compression.ZIP,
                               Compression.ZIP_WITH_PREDICTION):
            data_size = channel.length - 2
            logger.debug('    data size = %s-2=%s bytes', channel.length,
                         data_size)

        else:
            warnings.warn("Bad compression type %s" % compress_type)
            return []

        # read the data itself
        if data_size > channel.length:
            warnings.warn("Incorrect data size: %s > %s" %
                          (data_size, channel.length))
        else:
            raw_data = fp.read(data_size)
            if compress_type in (Compression.RAW, Compression.PACK_BITS):
                data = raw_data
            elif compress_type == Compression.ZIP:
                data = zlib.decompress(raw_data)
            elif compress_type == Compression.ZIP_WITH_PREDICTION:
                decompressed = zlib.decompress(raw_data)
                data = compression.decode_prediction(decompressed, w, h,
                                                     bytes_per_pixel)

            if data is None:
                return []

            channel_data.append(ChannelData(compress_type, data))

        remaining_length = channel.length - (fp.tell() - start_pos)
        if remaining_length > 0:
            fp.seek(remaining_length, 1)
            logger.debug('    skipping %s bytes', remaining_length)

    return channel_data