diff --git a/ppl2psd.py b/ppl2psd.py index b3b1e83..699ebe0 100644 --- a/ppl2psd.py +++ b/ppl2psd.py @@ -518,7 +518,17 @@ def build_psd(layers, width: int, height: int, out_path: str, workers: int, if visible and opacity > 0: merged.paste(img, (lx, ly), img) merged_rgb = merged.convert("RGB") # transparent -> black - merged_channels = channel_blocks(merged_rgb, workers, progress)[0:3] + # Merged image data is written RAW (compression=0) for maximum + # compatibility with third-party viewers, which often only parse RAW + # merged data and stretch RLE data. Per spec there is ONE 2-byte + # compression field followed by all planes in planar order (RRR GGG BBB). + if np is not None: + arr = np.asarray(merged_rgb) + merged_block = b"\x00\x00" + b"".join( + arr[..., i].tobytes() for i in range(3)) + else: + merged_block = b"\x00\x00" + b"".join( + merged_rgb.getchannel(c).tobytes() for c in "RGB") # assemble file fh = open(out_path, "wb") @@ -534,8 +544,7 @@ def build_psd(layers, width: int, height: int, out_path: str, workers: int, lam = layer_info + struct.pack(">I", 0) # global layer mask info fh.write(struct.pack(">I", len(lam)) + lam) - # merged image data (RGB, RLE) - merged_block = b"".join(p for _, p in merged_channels) + # merged image data (RGB, RAW) fh.write(merged_block) fh.close()