Commit Graph
7 Commits
Author SHA1 Message Date
AskaEth edef8799ce Fix blending ranges: zero composite range made PS skip layer blending
PS reads layer blending ranges to decide if a layer participates in
compositing. psd_tools wrote all-zero ranges (composite 0..0), which tells
Photoshop the layer has an empty blend range -> the canvas renders empty
even though layer pixels are correct (Ctrl+C/V shows content, export PNG is
transparent, save-as by PS keeps the bad ranges). Now writes full-range
(0..65535) composite + channel ranges like PS-generated files, verified
against the reference PSD.
2026-08-27 10:02:17 +08:00
AskaEth 8af857d45a Fix luni block: missing 4-byte character count field
The unicode layer name block must be [char_count(4B)][utf-16-be chars].
We wrote raw utf-16 without the count, so Photoshop read the first
characters as the length, shifted the entire extra-data parse, and every
layer's pixels came out empty (all layers transparent). Fixed: name now
reads back correctly and 167/167 layers match the rendered originals
(mean diff 0.000).
2026-08-27 09:25:18 +08:00
AskaEth 00f2cbe71a Write standard tagged blocks (lnsr/lyid/clbl/infx/knko/lspf/lclr/fxrp) per layer
Photoshop reads a layer's tagged blocks until it sees a non-8BIM
signature. With only 'luni' the next bytes are the channel data, which PS
mis-parses and the layer pixels come out empty. PS writes the standard
block set, so we now mirror it (verified: blocks list now matches the
reference PSD).
2026-08-27 09:06:03 +08:00
AskaEth e07ef4acaa Set layer flags bit3 (Photoshop 5.0+) so PS reads tagged blocks correctly
PS-generated PSDs always set flags bit 3 (0x08) to signal Photoshop 5.0+
format where the layer extra data contains tagged blocks. Our layers had
flags=0x00, so Photoshop treated them as pre-5.0 records and failed to
read the extra data / layer pixels, showing every layer as transparent
(only ape_2 happened to render). Verified against the reference PSD.
2026-08-27 08:59:35 +08:00
AskaEth b76a26c11c 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).
2026-08-27 08:37:59 +08:00
AskaEth a5757d1f07 Fix PSD structure: add missing LayerInfo length field and correct channel order
- Layer info section was missing its 4-byte length field, causing all
  subsequent offsets to shift and Photoshop to fail with 'unexpected end
  of file'
- Layer channel data was ordered [R,G,B,A] with ids [-1,0,1,2], shifting
  every channel by one (alpha held red, red held green, ...) - fixed to
  [A,R,G,B] so id -1 is the alpha mask
- Verified: psd_tools opens the PSD, per-layer pixels match the rendered
  originals with 0.000 mean difference
2026-08-27 08:27:05 +08:00
AskaEth 60624f01c2 Add ppl<->psd conversion tools (ppl2psd, psd2ppl) 2026-08-27 08:16:44 +08:00