Difference between revisions of "LazPaint LZP Format"

From Lazarus wiki
Jump to navigationJump to search
(→‎File header: formatting)
(→‎Global structure: formatting)
Line 9: Line 9:
 
The file is composed of:
 
The file is composed of:
  
- file header
+
Offset  Content
 
+
------  --------------------
- thumbnail (optional)
+
0      File header
 
+
?      Thumbnail (optional)
- flat image
+
?      Flat image
 
+
?      Layer structure (optional)
- layer structure (optional)
 
 
 
  
 
Note: some old formats do not have a header and start directly with the flat image. Image readers may discard those files. However for your information, in this case, images are always stored with ZStream compression and the size of the image is deduced from the size of the flat image.
 
Note: some old formats do not have a header and start directly with the flat image. Image readers may discard those files. However for your information, in this case, images are always stored with ZStream compression and the size of the image is deduced from the size of the flat image.

Revision as of 02:22, 17 March 2015

LZP File format specification

The default encoding for numbers is little endian. So the hexadecimal number $12345678 would be stored as the sequence of bytes 78 56 34 12.

Pascal convention is used in this document for hexadecimal numbers, so for example $10 means 16.

Global structure

The file is composed of:

Offset  Content
------  --------------------
0       File header
?       Thumbnail (optional)
?       Flat image
?       Layer structure (optional)

Note: some old formats do not have a header and start directly with the flat image. Image readers may discard those files. However for your information, in this case, images are always stored with ZStream compression and the size of the image is deduced from the size of the flat image.

File header

Offset  Size  Name                Content
------  ----  ------------------  ------------------------
0       8     magic               Always contains the string 'LazPaint'
8       4     zero1               Contains the number 0
12      4     headerSize          Size of this header

16      4     width               Width of the image canvas
20      4     height              Height of the image canvas
24      4     nbLayers            Number of layers
28      4     previewOffset       Offset (from the beginning of the file) of the flattened image

32      4     zero2               Contains the number 0
36      4     compressionMode     Contains flags indicating the compression and the presence of a thumbnail
40      4     reserved1           Reserved for future use. Set to 0.
44      4     layersOffset        Offset (from the beginning of the file) of the layer structure

headerSize contains the size of this header. An image reader must read this to know which fields are available. It must be greater or equal to 48.

width and height are the dimension of the canvas. There is no real limitation for these numbers however it is recommended to keep it under or equal to 8192.

nbLayers is the number of layers. The minimum is 1. There is no real limitation however it is recommended to keep it under or equal to 99.

layersOffset can be 0, in which case the image is flat and that there is no layer description.

Compression

compressionMode contains flags indicating the compression and the presence of a thumbnail.

The low order byte indicates the compression of the image. It is the value (compressionMode and $ff):

- $01 indicates ZStream compression

- $02 indicates RLE compression

The following flags can be defined:

- $100 indicates that there is thumbnail in PNG format; check with (compressionMode and $100) <> 0

If there is a thumbnail, it is directly after the header. The reader should read headerSize to have the correct location.

Thumbnail

Its presence is optional and determined by the flag $100 of compressionMode.

Currently, it is a PNG file embedded directly after the header. It is provided as a way to facilitate quick preview.

PNG format is widespread so it is easy to implement a browser that would display the thumbnail. To do so, check that the header contains magic and that the flag for the thumbnail is set in compressionMode. Then jump to the end of the header using headerSize. Then read the PNG file.

There is no real limitation but the recommended size for the thumbnail is 128 along the largest dimension. The other dimension may be smaller if the image is not a square. Of course if the image is smaller than 128 then the thumbnail will be smaller than 128.

Images

This applies for both the flat image and for the images in the layer structure.

There are two possible compressions. Both are lossless i.e. there is no loss of quality.

ZStream

The image has a defined width and height. There is a rectangular area for its content. Pixels that are outside of this area are transparent.

The content is compressed in any number of chunks. The uncompressed data must then be concatenated regardless of where scanlines start or end.

The header of the ZStream image is as follows:

Offset  Size  Content
------  ----  ----------------------------
0       4     Width
4       4     Height
8       4     Length of the caption (N)
12      N     Caption (UTF8 encoded)
12+N    4     Left bound of the content
16+N    4     Top bound of the content
20+N    4     Right bound of the content
24+N    4     Bottom bound of the content
28+N    4     Line order (0: top to bottom, 1: bottom to top)
32+N    4     Number of chunks

The content contains the lines in the rectangular area, following the specified line order. Each line contains all pixels in BGRA 32-bit format, i.e. 1 byte for each channel and the order of the channels being blue, green, red, alpha.

The chunks follow directly the header. Here is the structure for one chunk:

Offset  Size  Content
------  ----  ----------------------------
0       4     Size of the compressed data in the chunk (M)
4       M     Compressed data using ZStream (without ZStream header)

RLE

The header of the RLE image is as follows:

Offset  Size  Content
------  ----  ----------------------------
0       4     Width
4       4     Height
8       4     Length of the caption (N)
12      N     Caption (UTF8 encoded)
12+N    1     Plane flags

The following plane flags are defined:

- $01: the green channel is a copy of the red channel

- $02: the blue channel is a copy of the red channel

- $04: the blue channel is a copy of the green channel

- $08: there is no alpha channel (the image is opaque)

- $16: there is an RGB palette

There is then a variable number of RLE streams.

RLE stream

The structure of one RLE stream is as follows:

Offset  Size  Content
------  ----  ----------------------------
0       4     Size of the compressed data (P)
4       P     Compressed data

The data is a series of unpacking instructions. Each element of the instruction is a one byte value.

Special instructions:

Sequence                    Meaning
--------------------------  ---------------------------------------------------------------
$C1                         Reserved (the reader must stop and say the format is not supported)
$C2                         Reserved (the reader must stop and say the format is not supported)
$E0                         Ends of stream
$E1                         Reserved (the reader must stop and say the format is not supported)
$FF                         The reader must ignore and continue to read

Big repetitions instructions:

Sequence                    Meaning
--------------------------  ---------------------------------------------------------------
$00 Hi Lo Val               Repeats (Hi*256 + Lo) times the value Val
$80 Val                     Repeats the value Val the same number of times that in the previous $00 instruction
$40 Count Val               Repeats (Count+64) times the value Val
$C0 Val                     Repeats the value Val the same number of times that in the previous $40 instruction

Small repetitions:

Sequence                    Meaning
--------------------------  ---------------------------------------------------------------
$01..$3f Val                Repeats Val, the number of times being the value of the instruction ($01..$3f)
$40+n (n = 1..31)           Uncompress n group of packed repetition (see below)
$60+n (n = 1..16)           Repeats (n+1) times the value 0
$70+n (n = 1..16)           Repeats (n+1) times the value 255

Dump:

Sequence                    Meaning
--------------------------  ---------------------------------------------------------------
$81 Count                   The next (Count+64) bytes are copied as they are
$80+n (n = 2..63)           The next n bytes are copied as they are
$C0+n Val (n = 3..15)   The next (n-1)/2 bytes must be unpacked to yield n uncompressed bytes (see below)