/* png8 - Simple PNG sprite strip converter for assembly targets Copyright (C) 2016 Ian Cowburn This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------- Main */ #include #include #include #include #include #include #include /* ---------------------------------------- MACROS */ #ifndef TRUE #define TRUE (1) #endif #ifndef FALSE #define FALSE (0) #endif #define IS_BLACK(ul) (((ul) && 0x00FFFFFFul) == 0) #define IS_TRANS(ul) (((ul) && 0xFF000000ul) == 0) /* ---------------------------------------- VERSION INFO */ static const char *png8_usage = "Version 1.0 development\n" "\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License (Version 3) for more details.\n" "\n" "usage: png8 -- convert a file\n" "usage: png8 -h -- get help on \n"; /* ---------------------------------------- TYPES */ typedef enum { OUTPUT_Undefined, OUTPUT_Mono, OUTPUT_4Col } output_type_t; typedef unsigned long ulong; /* ---------------------------------------- HELP & USAGE */ static void Usage(void) { fprintf(stderr,"%s\n", png8_usage); exit(EXIT_FAILURE); } static void Help(void) { static const char *help = "Usage:\n" " png8 \n" "\nGeneral switches:\n" "-h - This help text.\n" "\nOne of these switches must be provided:\n" "-1 - Produce a monochrome sprite data set (e.g. Spectrum).\n" "-4 - Produce a 4-colour sprite data set (e.g. Commodore 64).\n" "\nOptional switches:\n" "-s - Treat black the same as a transparent pixel.\n" "-p - Use in place of 'byte' for output.\n" "-i - For monochrome data, produce pre-shifted values.\n" ""; fprintf(stderr,"%s\n", help); exit(EXIT_SUCCESS); } /* ---------------------------------------- UTIL */ static void Exit(const char *fmt, ...) { va_list va; va_start(va, fmt); vfprintf(stderr, fmt, va); va_end(va); exit(EXIT_FAILURE); } static void *Malloc(size_t size) { void *p = malloc(size); if (!p) { Exit("memory allocation failed\n"); } return p; } static ulong RGBA(png_byte r, png_byte g, png_byte b, png_byte a) { return ((ulong)r << 16ul) | ((ulong)g << 8ul) | ((ulong)b) | ((ulong)a << 24ul); } /* ---------------------------------------- MAIN */ int main(int argc, char *argv[]) { png_structp png; png_infop png_info; int num_passes; png_bytep *data; int width, height; png_byte colour_type, colour_depth; const char *opcode = "byte"; output_type_t output = OUTPUT_Undefined; int pre_shift = FALSE; int f; FILE *fp; char header[8]; f = 1; while(argv[f] && argv[f][0] == '-') { switch(argv[f][1]) { case 'h': Help(); break; case '1': output = OUTPUT_Mono; break; case '4': output = OUTPUT_4Col; break; default: Usage(); break; } f++; } if (output == OUTPUT_Undefined || !argv[f]) { Usage(); } if (!(fp = fopen(argv[f], "rb"))) { Exit("Failed to open %s\n", argv[f]); } fread(header, 1, sizeof header, fp); if (png_sig_cmp(header, 0, sizeof header)) { Exit("%s not recognised as a PNG file\n", argv[f]); } if (!(png = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))) { Exit("png_create_read_struct failed\n"); } if (!(png_info = png_create_info_struct(png))) { Exit("png_create_info_struct failed\n"); } if (setjmp(png_jmpbuf(png))) { Exit("png_init_io failed\n"); } png_init_io(png, fp); png_set_sig_bytes(png, sizeof header); png_read_info(png, png_info); width = png_get_image_width(png, png_info); height = png_get_image_height(png, png_info); colour_type = png_get_color_type(png, png_info); colour_depth = png_get_bit_depth(png, png_info); num_passes = png_set_interlace_handling(png); if (colour_type != PNG_COLOR_TYPE_RGBA) { Exit("PNG must be an RGB image with an alpha channel.\n"); } png_read_update_info(png, png_info); data = Malloc((sizeof *data) * height); for(f = 0; f < height; f++) { data[f] = Malloc(png_get_rowbytes(png, png_info)); } if (setjmp(png_jmpbuf(png))) { Exit("png_read_image failed\n"); } png_read_image(png, data); fclose(fp); for(f = 0; f < height; f++) { free(data[f]); } free(data); return EXIT_SUCCESS; } /* vim: ai sw=4 ts=8 expandtab */