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