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
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 )
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
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)
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
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