Difference between revisions of "LazPaint LZP Format"
(→Compression: layer compression different) |
(→Blend operations: more blend) |
||
Line 124: | Line 124: | ||
(with gamma correction unless it is specified in the stack flags) | (with gamma correction unless it is specified in the stack flags) | ||
− | 2 boLighten max(Over, Under) | + | 2 boLighten Mix := max(Over, Under) |
− | 3 boScreen 255 - ((255 - Under) * (255 - Over) shr 8) | + | 3 boScreen Mix := 255 - ((255 - Under) * (255 - Over) '''shr''' 8) |
− | 4 boAdditive | + | 4 boAdditive Mix := GammaCompression(GammaExpansion(Under)+GammaExpansin(Over)) |
− | 5 boLinearAdd | + | 5 boLinearAdd Mix := Under + Over |
− | 6 boColorDodge | + | 6 boColorDodge Mix := '''if''' Over = 255 '''then''' 255 '''else''' Min(255, (Under '''shl''' 8) '''div''' (255 - Over)) |
− | 7 boDivide | + | 7 boDivide Mix := '''if''' Over = 0 '''then''' 255 '''else''' Min(255, (Under '''shl''' 8) '''div''' Over) |
− | 8 boNiceGlow | + | 8 boNiceGlow Mix := '''if''' Under = 255 '''then''' 255 '''else''' Min(255, Over*Over '''div''' (255 - Under)) |
− | 9 boSoftLight | + | 9 boSoftLight Mix := ((255 - Under)*Over shr 7 + Under)*Under div 255 |
− | 10 boHardLight | + | 10 boHardLight Mix := '''if''' Over <= 128 '''then''' Under*Over '''shr''' 7 '''else''' 255 - ((255 - Under)*(255 - Over) '''shr''' 7) |
− | + | ||
− | 11 boGlow | + | 11 boGlow Mix := '''if''' Under = 255 '''then''' 255 '''else''' Min(255, Over*Over '''div''' (255 - Under)) |
− | 12 boReflect | + | 12 boReflect Mix := '''if''' Over = 255 '''then''' 255 '''else''' Min(255, Under*Under '''div''' (255 - Over)) |
− | 13 boOverlay | + | 13 boOverlay Mix := '''if''' Under <= 128 '''then''' Under*Over '''shr''' 7 '''else''' 255 - ((255 - Under)*(255 - Over) '''shr''' 7) |
− | 14 boDarkOverlay | + | 14 boDarkOverlay Mix := '''if''' GammaExpansion(Under) <= 32768 '''then''' Under*Over '''shr''' 7 '''else''' GammaCompression(65535 - ((65535 - GammaExpansion(Under))*(65535 - GammaExpansion(Over)) '''shr''' 15) |
15 boDarken | 15 boDarken | ||
16 boMultiply | 16 boMultiply |
Revision as of 14:54, 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 flattened 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.
The compression of the layers is defined in the layer structure.
Thumbnail
Its presence is recommended however optional. Its presence is specified 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.
Flat image
The file always include a flattened image to make it easier for image viewers. It is in the LZP single image format.
If there is no layer structure, the caption of this image is the name of the unique layer. If there is a layer structure, then the caption of this image is discarded.
Layer structure
Offset Size Content ------ ---- ------------------------------------------------------- 0 20 Contains the string 'TBGRALayeredBitmap' followed by the bytes 1A 00 20 4 Size S of the additional header (must be at least 12) 24 4 Number of layers N (should be identical to the number in the file header) 28 4 Selected layer index. Equals to -1 if no layer is selected, otherwise positive from 0 to N-1 32 4 Stack flags
The following flags are defined: - $01: the layers are blended without gamma correction - $02: the layers are compressed with RLE compression (otherwise they are compressed with ZStream compression)
The total header size of the layer structure is equal to 20 + S.
Then for each layer there is a layer entry.
Layer entry
Header of the layer entry:
Offset Size Content ------ ---- ------------------------------------------------------- 0 4 Size S1 of the optional fields that follows 4 4 Layer flags (lowest bit means that it is visible) 8 4 Layer blend operation 12 4 Layer horizontal offset in pixels 16 4 Layer vertical offset in pixels 20 4 Layer ID (if used, each layer must have a different ID in a given file) 24 4 Layer opacity from 0 (transparent) to 65535 (opaque) 28 4 Size S2 of image data 4+S1 S2 Image data 4+S1+S2 Next entry
All fields are optional so in theory, S1 can be set to zero and the image data can directly follow. However it is recommended to write the whole header.
The default values are: visible, blend operation boTransparent, offset (0,0), opaque.
Blend operations
Value Name Description ----- ----------------- ---------------------------------------------------- 0 boLinearBlend Blend over the previous layers without gamma correction 1 boTransparent Blend over the previous layers (with gamma correction unless it is specified in the stack flags) 2 boLighten Mix := max(Over, Under) 3 boScreen Mix := 255 - ((255 - Under) * (255 - Over) shr 8) 4 boAdditive Mix := GammaCompression(GammaExpansion(Under)+GammaExpansin(Over)) 5 boLinearAdd Mix := Under + Over 6 boColorDodge Mix := if Over = 255 then 255 else Min(255, (Under shl 8) div (255 - Over)) 7 boDivide Mix := if Over = 0 then 255 else Min(255, (Under shl 8) div Over) 8 boNiceGlow Mix := if Under = 255 then 255 else Min(255, Over*Over div (255 - Under)) 9 boSoftLight Mix := ((255 - Under)*Over shr 7 + Under)*Under div 255 10 boHardLight Mix := if Over <= 128 then Under*Over shr 7 else 255 - ((255 - Under)*(255 - Over) shr 7)
11 boGlow Mix := if Under = 255 then 255 else Min(255, Over*Over div (255 - Under)) 12 boReflect Mix := if Over = 255 then 255 else Min(255, Under*Under div (255 - Over)) 13 boOverlay Mix := if Under <= 128 then Under*Over shr 7 else 255 - ((255 - Under)*(255 - Over) shr 7) 14 boDarkOverlay Mix := if GammaExpansion(Under) <= 32768 then Under*Over shr 7 else GammaCompression(65535 - ((65535 - GammaExpansion(Under))*(65535 - GammaExpansion(Over)) shr 15) 15 boDarken 16 boMultiply 17 boColorBurn 18 boDifference 19 boLinearDifference 20 boExclusion 21 boLinearExclusion 22 boSubtract 23 boLinearSubtract 24 boSubtractInverse 25 boLinearSubtractInverse 26 boNegation 27 boLinearNegation 28 boXor