diff --git a/imageconvert/make_png_convert b/imageconvert/make_png_convert new file mode 100644 index 0000000..6a2f3bd --- /dev/null +++ b/imageconvert/make_png_convert @@ -0,0 +1,41 @@ +# +# Define PNG_ROOT to point to the location of the PNGdec library +# +PNG_ROOT = /Users/laurencebank/Documents/Arduino/libraries/PNGdec/src + +all: pngconvert +CFLAGS = -D__LINUX__ -I $(PNG_ROOT) -Wall -O2 + +pngconvert: png_main.o PNGdec.o adler32.o crc32.o infback.o inffast.o inflate.o inftrees.o zutil.o + $(CC) png_main.o PNGdec.o adler32.o crc32.o infback.o inffast.o inflate.o inftrees.o zutil.o -o pngconvert + strip $@ + +png_main.o: png_main.cpp + $(CXX) $(CFLAGS) -c png_main.cpp + +PNGdec.o: $(PNG_ROOT)/PNGdec.cpp $(PNG_ROOT)/png.inl $(PNG_ROOT)/PNGdec.h + $(CXX) $(CFLAGS) -c $(PNG_ROOT)/PNGdec.cpp + +adler32.o: $(PNG_ROOT)/adler32.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/adler32.c + +crc32.o: $(PNG_ROOT)/crc32.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/crc32.c + +infback.o: $(PNG_ROOT)/infback.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/infback.c + +inffast.o: $(PNG_ROOT)/inffast.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/inffast.c + +inflate.o: $(PNG_ROOT)/inflate.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/inflate.c + +inftrees.o: $(PNG_ROOT)/inftrees.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/inftrees.c + +zutil.o: $(PNG_ROOT)/zutil.c + $(CC) $(CFLAGS) -c $(PNG_ROOT)/zutil.c + +clean: + rm -rf *.o pngconvert diff --git a/imageconvert/png_main.cpp b/imageconvert/png_main.cpp new file mode 100644 index 0000000..c0e965f --- /dev/null +++ b/imageconvert/png_main.cpp @@ -0,0 +1,216 @@ +// +// PNG to Group5 Image Compressor tool +// Written by Larry Bank +// Copyright (c) 2025 BitBank Software, Inc. +// +#include +#define MAX_IMAGE_FLIPS 256 +#include "../src/Group5.h" +#include "../src/g5enc.inl" +#include "PNGdec.h" + +PNG png; // static instance of class + +// +// Create the comments and const array boilerplate for the hex data bytes +// +void StartHexFile(FILE *f, int iLen, int w, int h, const char *fname) +{ + int i; + char szTemp[256]; + fprintf(f, "//\n// Created with imageconvert, written by Larry Bank\n"); + fprintf(f, "// %d x %d x 1-bit per pixel\n", w, h); + fprintf(f, "// compressed image data size = %d bytes\n//\n", iLen); + strcpy(szTemp, fname); + i = strlen(szTemp); + if (szTemp[i-2] == '.') szTemp[i-2] = 0; // get the leaf name for the data + fprintf(f, "const uint8_t %s[] = {\n", szTemp); +} /* StartHexFile() */ +// +// Add N bytes of hex data to the output +// The data will be arranged in rows of 16 bytes each +// +void AddHexBytes(FILE *f, void *pData, int iLen, int bLast) +{ + static int iCount = 0; // number of bytes processed so far + int i; + uint8_t *s = (uint8_t *)pData; + for (i=0; i>4) * 4]; + g = (pPal[0] + pPal[1]*2 + pPal[2])/4; + } + break; + } // switch on bpp + if (g >= 128) u8 |= 1; // white + count--; + if (count == 0) { // byte is full, move on + *d++ = u8; + u8 = 0; + count = 8; + } + } // for x + } // for y +} /* ConvertTo1Bpp() */ + +int main(int argc, const char * argv[]) { + int w, h, y, i, rc, bpp; + uint8_t *s, *pOut, *pData; + int iPitch, iOutSize, iDataSize; + FILE *ihandle; + uint8_t *pPalette; + G5ENCIMAGE g5enc; + BB_BITMAP bbbm; + int bHFile; // flag indicating if the output will be a .H file of hex data + + printf("PNG to Group5 image conversion tool\n"); + if (argc != 3) { + printf("Usage: ./pngconvert \n"); + return -1; + } + pOut = (uint8_t *)argv[2] + strlen(argv[2]) - 1; + bHFile = (pOut[0] == 'H' || pOut[0] == 'h'); // output an H file? + ihandle = fopen(argv[1],"rb"); // open input file + if (ihandle == NULL) + { + fprintf(stderr, "Unable to open file: %s\n", argv[1]); + return -1; // bad filename passed + } + fseek(ihandle, 0L, SEEK_END); // get the file size + iDataSize = (int)ftell(ihandle); + fseek(ihandle, 0, SEEK_SET); + pData = (uint8_t *)malloc(iDataSize); + fread(pData, 1, iDataSize, ihandle); + fclose(ihandle); + + rc = png.openRAM(pData, iDataSize, NULL); + if (rc == PNG_SUCCESS) { + w = png.getWidth(); + h = png.getHeight(); + printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", w, h, png.getBpp(), png.getPixelType()); + png.setBuffer((uint8_t *)malloc(png.getBufferSize())); + rc = png.decode(NULL, 0); //PNG_CHECK_CRC); + png.close(); + if (rc != PNG_SUCCESS) { + printf("Error decoding PNG file = %d\n", rc); + free(png.getBuffer()); + return -1; + } + i = 1; + pPalette = NULL; + switch (png.getPixelType()) { + case PNG_PIXEL_INDEXED: + case PNG_PIXEL_GRAYSCALE: + if (png.getPixelType() == PNG_PIXEL_INDEXED) { + pPalette = png.getPalette(); + } + i = 1; + bpp = png.getBpp(); + break; + case PNG_PIXEL_TRUECOLOR: + i = 3; + bpp = 24; + break; + case PNG_PIXEL_TRUECOLOR_ALPHA: + i = 4; + bpp = 32; + break; + } // switch + if (bpp != 1) { // need to convert it to 1-bpp + printf("Converting from %d-bpp to 1-bpp\n", bpp); + ConvertTo1Bpp(png.getBuffer(), w, h, bpp, pPalette); + } + iPitch = (w+7) >> 3; + pOut = (uint8_t *)malloc(iPitch * h); + s = png.getBuffer(); + rc = g5_encode_init(&g5enc, w, h, pOut, iPitch * h); + for (y=0; y