Sign in Join
Wiki copytemporary

LazPaint LZP Format Single Image: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11This description applies for both the flat image and for the images in the layer structure of [[LazPaint LZP Format|LZP file format]].
22
33There are two possible compressions. Both are lossless i.e. there is no loss of quality.
44
55If a file is saved in this format without any header, it uses ZStream compression. But in general LazPaint uses RLE compression here.
66
77#### ZStream
88
99The image has a defined width and height. There is a rectangular area for its content. Pixels that are outside of this area are transparent (all channels equal to zero).
1010
1111The content is compressed in any number of chunks. The uncompressed data must then be concatenated regardless of where scanlines start or end.
1212
1313The header of the ZStream image is as follows:
1414
1515`Offset  Size  Content`\
1616`------  ----  ----------------------------`\
1717`0       4     Width`\
1818`4       4     Height`\
1919`8       4     Length of the caption (N)`\
2020`12      N     Caption (UTF8 encoded)`\
2121`12+N    4     Left bound of the content`\
2222`16+N    4     Top bound of the content`\
2323`20+N    4     Right bound of the content`\
2424`24+N    4     Bottom bound of the content`\
2525`28+N    4     Line order (0: top to bottom, 1: bottom to top)`\
2626`32+N    4     Number of chunks`
2727
2828The 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.
2929
3030The chunks follow directly the header. Here is the structure for one chunk:
3131
3232`Offset  Size  Content`\
3333`------  ----  ----------------------------`\
3434`0       4     Size of the compressed data in the chunk (M)`\
3535`4       M     Compressed data using ZStream (without ZStream header)`
3636
3737#### RLE
3838
3939The header of the RLE image is as follows:
4040
4141`Offset  Size  Content`\
4242`------  ----  ----------------------------`\
4343`0       4     Width`\
4444`4       4     Height`\
4545`8       4     Length of the caption (N)`\
4646`12      N     Caption (UTF8 encoded)`\
4747`12+N    1     Plane flags`
4848
4949The following plane flags are defined:
5050
5151\- \$01: the green channel is a copy of the red channel
5252
5353\- \$02: the blue channel is a copy of the red channel
5454
5555\- \$04: the blue channel is a copy of the green channel
5656
5757\- \$08: there is no alpha channel (the image is opaque)
5858
5959\- \$10: there is a palette and colors are expressed as indices in this palette
6060
6161There is then a variable number of RLE streams. The pixels are scanned from top to bottom and from left to right.
6262
6363##### Full RLE structure for empty images
6464
6565If the image is completely transparent, there are no stream for color channels.
6666
6767`Offset  Size  Content`\
6868`------  ----  -------------------------`\
6969`0       13+N  Header`\
7070`13+N    ?     Alpha channel stream`
7171
7272The uncompressed stream for the alpha channel contains one byte for each pixel of the canvas. 0 means the pixel is transparent and 255 means opaque. Because the image is empty, it contains only zeros.
7373
7474##### Full RLE structure for non paletted images
7575
7676`Offset  Size  Content`\
7777`------  ----  -------------------------`\
7878`0       13+N  Header`\
7979`13+N    ?     Alpha channel stream (optional)`\
8080`?       ?     Red channel stream`\
8181`?       ?     Green channel stream (optional)`\
8282`?       ?     Blue channel stream (optional)`
8383
8484Alpha channel is not present if \$08 flag is used. Otherwise the uncompressed stream contains one byte for each pixel of the canvas. 0 means the pixel is transparent and 255 means opaque.
8585
8686The uncompressed stream for the red channel contains one byte for each **non-transparent** pixel.
8787
8888Green channel is not present if \$01 flag is used. Otherwise the uncompressed stream contains one byte for each **non-transparent** pixel.
8989
9090Blue channel is not present if \$02 or \$04 flag is used. Otherwise the uncompressed stream contains one byte for each **non-transparent** pixel.
9191
9292##### Full RLE structure for paletted images
9393
9494`Offset  Size  Content`\
9595`------  ----  -------------------------`\
9696`0       13+N  Header`\
9797`13+N    ?     Alpha channel stream (optional)`\
9898`?       ?     Red channel palette stream`\
9999`?       ?     Green channel palette stream (optional)`\
100100`?       ?     Blue channel palette stream (optional)`\
101101`?       ?     Indexed color stream`
102102
103103Alpha channel is not present if \$08 flag is used. Otherwise the uncompressed stream contains one byte for each pixel of the canvas. 0 means the pixel is transparent and 255 means opaque.
104104
105105Each channel palette stream contains a maximum of 256 uncompressed bytes. The streams may be shorter and in that case, the rest is padded with zeros. The position in the uncompressed stream is the color index.
106106
107107The uncompressed stream for the red channel contains one byte for each entry of the palette. It is padded with zeros to make 256 bytes.
108108
109109Green channel palette is not present if \$01 flag is used. Otherwise the stream contains the green values for the palette.
110110
111111Blue channel palette is not present if \$02 or \$04 flag is used. Otherwise the stream contains the blue values for the palette.
112112
113113The uncompressed indexed color stream contains one byte for each **non-transparent** pixel, that is the index into the palette.
114114
115115##### RLE stream
116116
117117The structure of one RLE stream is as follows:
118118
119119`Offset  Size  Content`\
120120`------  ----  ----------------------------`\
121121`0       4     Size of the compressed data (P)`\
122122`4       P     Compressed data`
123123
124124The data is a series of unpacking instructions. Each element of the instruction is a one byte value.
125125
126126Special instructions:
127127
128128`Sequence                    Meaning`\
129129`--------------------------  ---------------------------------------------------------------`\
130130`$C1                         Reserved (the reader must stop and say the format is not supported)`\
131131`$C2                         Reserved (the reader must stop and say the format is not supported)`\
132132`$E0                         Ends of stream`\
133133`$E1                         Reserved (the reader must stop and say the format is not supported)`\
134134`$FF                         The reader must ignore and continue to read`
135135
136136Big repetitions instructions:
137137
138138`Sequence                    Meaning`\
139139`--------------------------  ---------------------------------------------------------------`\
140140`$00 `*`Hi`*` `*`Lo`*` `*`Val`*`               Repeats (`*`Hi`*`*256 + `*`Lo`*`) times the value `*`Val`*\
141141`$80 `*`Val`*`                     Repeats the value `*`Val`*` the same number of times that in the previous $00 instruction`\
142142`$40 `*`Count`*` `*`Val`*`               Repeats (`*`Count`*`+64) times the value `*`Val`*\
143143`$C0 `*`Val`*`                     Repeats the value `*`Val`*` the same number of times that in the previous $40 instruction`
144144
145145Small repetitions:
146146
147147`Sequence                    Meaning`\
148148`--------------------------  ---------------------------------------------------------------`\
149149`$01..$3f `*`Val`*`                Repeats `*`Val`*`, the number of times being the value of the instruction ($01..$3f)`\
150150`$40+n (`*`n`*` = 1..31)           Uncompress `*`n`*` group of packed repetition (see below)`\
151151`$60+`*`n`*` (`*`n`*` = 0..15)           Repeats (`*`n`*`+1) times the value 0`\
152152`$70+`*`n`*` (`*`n`*` = 0..15)           Repeats (`*`n`*`+1) times the value 255`
153153
154154Dump:
155155
156156`Sequence                    Meaning`\
157157`--------------------------  ---------------------------------------------------------------`\
158158`$81 `*`Count`*`                   The next (`*`Count`*`+64) bytes are copied as they are`\
159159`$80+`*`n`*` (`*`n`*` = 2..63)           The next `*`n`*` bytes are copied as they are`\
160160`$C0+`*`n`*` `*`Val`*` (`*`n`*` = 3..31)       The next `*`(n-1)/2`*` bytes must be unpacked to yield `*`n`*` uncompressed bytes (see below)`\
161161`                            An initial value `*`Val`*` is provided and is put as it is in the uncompressed stream.`\
162162`$E0+`*`n`*` (`*`n`*` = 2..30)           The next `*`n/2`*` bytes must be unpacked to yield `*`n`*` uncompressed bytes (see below)`\
163163`                            The last unpacked value with instruction $C0 and $E0 is used as an implicit initial value.`\
164164`                            This initial value is however not put in the uncompressed stream. Its default value is $80`\
165165`                            in the case there is no previous unpacking instruction.`
166166
167167##### Simple instructions examples
168168
169169`07 FF 06 FE`
170170
171171repeats 7 times the value \$FF then 6 times the value \$FE.
172172
173173`63 73`
174174
175175repeat 4 times the value \$00 then 4 times the value \$FF.
176176
177177`00 01 00 23 E0`
178178
179179Stream containing \$100 times the value \$23. The \$E0 instruction indicates the end of the stream.
180180
181181`00 01 00 C0 80 FF 80 C0 80 FF`
182182
183183Stream containing:
184184
185185`- $100 times the value $C0`\
186186`- $100 times the value $FF`\
187187`- $100 times the value $C0`\
188188`- $100 times the value $FF`\
189189`- the end of the stream instruction is missing`
190190
191191`40 03 FF C0 00`
192192
193193repeats 67 times the value \$FF, then 67 times the value \$00.
194194
195195`83 01 02 03`
196196
197197writes 01 02 03 into the output stream (a total of 3 bytes).
198198
199199`81 03 01 02 03 04 ... 40 41 42 43`
200200
201201writes 01 02 03 04 ... 40 41 42 43 into the output stream (a total of 67 bytes).
202202
203203##### Packed repetitions
204204
205205The instructions \$41..\$5F (= \$40 + *n*) represent a group of *n* packed repetition. So the structure of one instruction is:
206206
207207`Instruction $40+`*`n`*` `\
208208`Packed repetition number 1`\
209209`Packed repetition number 2`\
210210`...`\
211211`Packed repetition number `*`n`*
212212
213213One entry of packed repetition:
214214
215215`Offset  Size  Content`\
216216`-----   ----  -----------------`\
217217`0       1     Packed number P of repetitions to apply`\
218218`1       1     First byte to repeat N1 times`\
219219`2       1     2nd byte to repeat N2 times`\
220220`3       1     3rd byte to repeat N3 times`\
221221`4       1     4th byte to repeat N4 times`\
222-\
222+
223223`P = N1-1 + ((N2-1) `*`shl`*` 2) + ((N3-1) `*`shl`*` 4) + ((N4-1) `*`shl`*` 6)`
224224
225225Example:
226226
227227`42 FF 01 02 03 04 55 01 02 03 04`\
228-\
228+
229229`is unpacked as`\
230-\
230+
231231`01 01 01 01 02 02 02 02 03 03 03 03 04 04 04 04 01 01 02 02 03 03 04 04`
232232
233233##### Packed dumps
234234
235235In a packed dumps, it is the values themselves that are packed. To do that, an initial value is defined. By default it is \$80. Then each subsequent value is computed by adding an offset from -7 to +7. This offset is stored as a number between 1 and 15 (by adding 8 to it).
236236
237237For example:
238238
239239`20 22 25`\
240-\
240+
241241`can be packed as`\
242-\
242+
243243`initial value $20, then offset +2, then offset +3`
244244
245245So it would be written in the compressed stream as:
246246
247247`C3 20 AB`
248248
249249Where \$A = 10 = 2 + 8 is the first offset and \$B = 11 = 3 + 8 is the second offset.
250250
251251Another example:
252252
253253`00 01 02 03 04 05 ... 0E 0F (a total of 16 bytes)`\
254-\
254+
255255`can be packed as`\
256-\
256+
257257`D0 00 99 99 99 99 99 99 99 90 (a total of 10 bytes)`
258258
259259Note that the initial value may be omitted by using the instructions \$E2..\$FE.
260260
261261---
262262*From the Free Pascal wiki, page "LazPaint LZP Format Single Image", as it stood on 2020-12-04 after a change by Circular, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
263263Category: LazPaint

Back to history