-
Notifications
You must be signed in to change notification settings - Fork 12
API
The PNG class exposes a few simple methods detailed below. The more challenging part of using it is when you're using a new type of file system and need to write your own callback functions. Those are documented below the API section.
This is the entire class definition for PNG:
class PNG {
public:
int open(uint8_t *pOutput, int iBufferSize);
int open(char *szFilename, PNG_OPEN_CALLBACK *pfnOpen, PNG_CLOSE_CALLBACK *pfnClose, PNG_READ_CALLBACK *pfnRead, PNG_WRITE_CALLBACK *pfnWrite, PNG_SEEK_CALLBACK *pfnSeek);
int encodeBegin(int iWidth, int iHeight, uint8_t iPixelType, uint8_t iBpp, uint8_t *pPalette, uint8_t iCompLevel);
int addLine(uint8_t *pPixels);
int addRGB565Line(uint16_t *pPixels, void *pTempLine);
int setTransparentColor(uint32_t u32Color);
int setAlphaPalette(uint8_t *pAlphaValues);
int close();
int getLastError();
private:
PNGIMAGE _png;
};The class is basically a C++ wrapper of C code which does all of the actual work. The PNGIMAGE structure is kept private, but is passed as a pointer to the 'worker' functions. This makes it easy to lift out the C code if you want to use it in a pure C project. Here are details of each method:
int open()
There are two versions of the open method - one for PNG creation to a memory buffer and another for images written to a file. All return 0 (PNG_SUCCESS) for success, non-0 for failure (see error codes). The success or failure depends on the file successfully opening or the buffer being non-NULL. Once this function returns successfully, you can set the encoding parameters with encodeBegin() and then add the image data with addLine(). If you're writing the output to memory, make sure the output buffer is large enough to hold the compressed data.
int close()
After adding all of the lines to create your PNG image, this will finalize the file by calculating the IDAT chunk CRC and write the IEND chunk. Finally it will close the file and return the total size written. The file access callback functions must be able to seek, overwrite and read data that was previously written for it to work correct.
int encodeBegin(int iWidth, int iHeight, uint8_t iPixelType, uint8_t iBpp, uint8_t *pPalette, uint8_t iCompLevel)
This method tells the encoder the specifics of the image you want to create. The pixel type can be one of the constants defined by the PNG spec and enumerated in PNGenc.h (e.g. PNG_PIXEL_INDEXED). iCompLevel is the zlib effort value - how hard it should try to compress the data. This value can be between 1 (least) to 9 (most). The amount of time needed for 9 is much more than 3, but the additional compression it achieves does not scale by the same amount. Consider this when choosing the value. For indexed (palette) images, a palette of RGB triplets must be provided and needs to be the full length even if only a few colors are used. For example, if the bit depth is 8 and only 2 colors are defined in the palette, it still needs to be 768 (256 x 3) bytes long. If any of the parameters are invalid an error will be returned. When PNG_SUCCESS is returned, you can begin calling addLine() with the image data. The following are valid pixel types:
PNG_PIXEL_GRAYSCALE - 8-bpp grayscale
PNG_PIXEL_TRUECOLOR - 24-bpp (8x3) RGB triplets
PNG_PIXEL_INDEXED - 1 to 8-bpp palette color (BGR color triplets -> 0=B, 1=G, 2=R)
PNG_PIXEL_GRAY_ALPHA - 16-bpp (8-bit gray + 8-bit alpha)
PNG_PIXEL_TRUECOLOR_ALPHA - 32-bpp (RGB8888)
int addRGB565Line(uint16_t *pPixels, void *pTempLine)
The PNG file format doesn't directly support RGB565 pixels. This is a convenient function which allows you to feed the compressor RGB565 pixels and they will get automatically converted into either PNG_PIXEL_GRAYSCALE or PNG_PIXEL_TRUECOLOR depending on the pixel type you pass in to encodeBegin(). The pTempLine is a pointer to a buffer you provide which has enough room to hold a single line of convert pixels.
int setAlphaPalette(uint8_t *pAlphaValues)
For indexed images, PNG allows setting a per-color alpha value (0-255). Like the color palette, you must provide valid memory for the full list of color entries even if you only set a few values.
int setTransparentColor(uint32_t u32Color)
PNG allows setting of a single transparent color for grayscale and truecolor images.
int getLastError()
Returns the last error or 0 (PNG_SUCCESS) if there was none. See PNGdec.h for a list of error codes
There are 5 callback functions defined by PNGenc. If you're encoding a PNG to memory, then you don't need to provide any callback functions. The callback functions need to be implemented if you're writing the output to a file. They implement the standard functions of open, close, read, write, and seek:
typedef void * (PNG_OPEN_CALLBACK)(char *szFilename);
typedef void (PNG_CLOSE_CALLBACK)(PNGFILE *pFile);
typedef int32_t (PNG_READ_CALLBACK)(PNGFILE *pFile, uint8_t *pBuf, int32_t iLen);
typedef int32_t (PNG_WRITE_CALLBACK)(PNGFILE *pFile, uint8_t *pBuf, int32_t iLen);
typedef int32_t (PNG_SEEK_CALLBACK)(PNGFILE *pFile, int32_t iPosition);The challenge with the file system callbacks is that file access on Arduino is usually not associated with a simple file handle, but with a C++ class. In order to manage this in a generic way that will work for all possible systems, the PNGdec class holds onto a void * pointer which you would like use to hold a class pointer. Let's look at the PNG_CLOSE_CALLBACK function I wrote for the Arduino SD library to understand how this is done:
void PNGCloseFile(PNGFILE *pFile)
{
File *f = static_cast<File *>(pFile->fHandle);
if (f != NULL)
f->close();
}The trick to making it all work is just to use static_cast to convert the void * into whatever class you need to access files.
See any of the example sketches for how to implement the other callback functions.