Fix merged image data: single compression field + RAW for compatibility
Per Adobe PSD spec, the Image Data Section has ONE 2-byte compression field followed by all planes in planar order (RRR GGG BBB). The previous code wrote a compression marker per channel (4 extra bytes) and used RLE, which third-party viewers parse incorrectly (stretching) and Photoshop rejected. Now writes RAW data with a single compression marker, verified by pytoshop (decompresses to 3x4882x9764).
This commit is contained in:
1 parent
a5757d1f07
commit
b76a26c11c
1 file changed
+12
-3
+12
-3
@@ -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()
|
||||
|
||||
|
||||
Reference in new issue
Block a user