Photonsters / VoxelsOps

this library will process three-dimensional matrix of binary data with boolean operations and some helper filters
GNU General Public License v3.0
12 stars 1 forks source link

Encode layer images to photon file #3

Open NardJ opened 6 years ago

NardJ commented 6 years ago

Some info on how to encode layer images back to a photon file. A photon file is constructed as follows:

VoxelsOps do not effect the Header and Preview blocks. So only the meta block and data block for each image have to be reconstructed.

The start address of the first metablock is stored in the Header in 4 bytes from byte 64. The number of layers (and thus metablocks and data blocks) is stored in the Header in 4 bytes from byte 68.

Each Meta block has the following struct:

- Layer height (mm),  4 bytes containing Float,  "Height at which this layer should be printed."
- Exposure time (s),   4 bytes containing Float, "Exposure time for this layer."
- Off time (s),              4 bytes containing Float, "Off time for this layer."
- Datablock Address,  4 bytes containing Int, "Address where the raw image can be found."
- Data Length,            4 bytes containing Int,  "Size (in bytes) of the raw image."
- Some padding,         16 bytes

For each metablock you should adjust the datablock address and data length after RLE encoding the layer image. The other data you can copy from the source file.

Each Data block is just a block of RLE encoded bytes without decoration or other info. Some python code I used to encode the image to RLE data:

# Count number of pixels with same color up until 0x7D/125 repetitions
        rleData = bytearray()
        color = 0
        black = 0
        white = 1
        nrOfColor = 0
        prevColor=None
        for y in range(height):
            for x in range(width):
                # print (imgsurf.get_at((x, y)))
                (r, g, b, a) = imgsurf.get_at((x, y))
                if ((r + g + b) // 3) < 128:
                    color = black
                else:
                    color = white
                if prevColor == None: prevColor = color
                isLastPixel = (x == (width - 1) and y == (height - 1))
                if color == prevColor and nrOfColor < 0x7D and not isLastPixel:
                    nrOfColor = nrOfColor + 1
                else:
                    #print (color,nrOfColor,nrOfColor<<1)
                    encValue = (prevColor << 7) | nrOfColor # push color (B/W) to highest bit and repetitions to lowest 7 bits.
                    rleData.append(encValue)
                    prevColor = color
                    nrOfColor = 1
        return bytes(rleData)