Reading and writing a Photoshop TIFF
This blog post draws on my experience adding reading and writing support for our app, and is intended to clarify the ambiguities in the official standard.
Adobe Photoshop provides two ways to save layers: its proprietary PSD/PSB format, widely supported in imaging applications, and inside TIFF containers. The latter is not well supported; as detailed in an email to the OpenColorIO mailing list, the PSD standard is too vague and imprecise to be an useful reference in writing support for these files. Indeed, as of the writing of this post, only ImageMagick (commit, commit) provides any sort of support for this variant.
As of today, the official documentation on Photoshop TIFFs is:
- page 11 of the “Adobe Photoshop® TIFF Technical Notes” available on the Adobe Open Standards page
- section “Photoshop-specific TIFF Tags” in the “Adobe Photoshop File Formats Specification” of November 2019, available here.
In short, Photoshop layers are stored in tag or field
37724, identified as
TIFFTAG_IMAGESOURCEDATA in the latest libtiff. The type of this tag shall be
TIFF_UNDEFINED in libtiff. The data blob shall be an array of
uint8_t, and shall be headed by a magic signature that is one of the following null terminated ASCII strings:
- for standard Photoshop files,
Adobe Photoshop Document Data Block.
- for Large Document Format (8BPB/PSB) files,
Adobe Photoshop Document Data V0002(the last five characters differ).
After the magic signature, the remainder of the blob is comprised of a series of Additional Layer Information blocks:
- block type (4 bytes)
- length of the block (4 bytes, variable, padded to a 4-byte offset)
- data of the block (length as above)
The Technical Notes say that these are the available block types:
LMsk(global mask info block)
Patt(pattern definition block)
There is a second useful tag,
34377, also known as
TIFFTAG_PHOTOSHOP. The type of this tag shall be
TIFF_BYTE). This is the TIFF equivalent of Photoshop’s image resource section; its contents must not be prepended by the length field, as it is already provided for by the TIFF container.
Supporting Photoshop TIFFs
Warning: The author has not seen a TIFF PSB (Photoshop Large Document Format) in the wild. A prospective developer should read the Standard and apply the PSB remarks accordingly in each paragraph.
The Photoshop standard says of its native file format:
All data is stored in big endian byte order. On the Windows platform, you must byte swap short and long integers when reading or writing.
The situation is more complex in Photoshop TIFF files.
data must be stored in big endian order. On the other hand,
TIFFTAG_IMAGESOURCEDATA data must be stored in the endianness of its container. In practice, this means that existing PSD I/O routines can be reused, provided the developer byte-swaps integer and block type reading routines when interacting with a little-endian data source.
As an example, suppose a little-endian TIFF file, whose
data blob starts at address
000371e8. Its format is PSD, and the first block is a
Layr block of size 11463. Thus, the first 48 bytes of the data blob shall match the following:
$ xxd -s +225768 -l 48 1.tif 000371e8: 4164 6f62 6520 5068 6f74 6f73 686f 7020 Adobe Photoshop 000371f8: 446f 6375 6d65 6e74 2044 6174 6120 426c Document Data Bl 00037208: 6f63 6b00 4d49 4238 7279 614c c72c 0000 ock.MIB8ryaL.,..
- the null terminated magic signature
Adobe Photoshop Document Data block
MIB8magic block signature, signaling both little endian and the start of a new info block
ryaLblock type, which is
Layrin big endian and thus means a layer info block
00002cc7in big endian, and thus 11463.
A valid Photoshop TIFF file must have a layer info block as a minimum. Its contents are described in Layer info. The type of this block shall be
Layr, or one of the following (see Layer and mask information section):
Lr16interchangeably, for 8-bit and 16-bit depth;
Lr32for 32-bit layers.
Irrespective of the compression type, the raw channel image data in Photoshop TIFF files must be in big endian order. Prospective applications shall byteswap the channel values prior to compression and after decompression, where applicable.
Lyid block is optional; if it is present, its value should be the position of the layer in a depth-first, left-right traversal of the layer tree.
Additional info blocks
LMsk info block is described in Global layer mask info. It is optional; however, if it is present, its length shall not be 0. The overlay color space ID shall be one of the values described in Color space IDs, and the color components shall be the corresponding Pure color value. The opacity value shall be 50 and the kind 128.
Patt block is optional; if it is present, the image data in the virtual memory array list
must be in big endian order. Prospective applications shall byteswap the channel values prior to compression and after decompression, where applicable.
Adobe Photoshop, as of CC 2021, also outputs additional blocks. All of them are optional:
Unlike its native and more widespread sibling, Photoshop TIFFs are a relatively obscure way yet portable way of exporting Photoshop layers. These are stored in the byte order of its container, except for the channel data in both layer and pattern blocks, which are stored in big endian order. A prospective developer should, given an existing suite of I/O primitives for the PSD format, be able to add support for TIFF containers with relative ease by: byteswapping all integers and block types; and ensuring channel data is always compressed and/or stored in big endian.