summaryrefslogtreecommitdiff
path: root/png8.c
diff options
context:
space:
mode:
Diffstat (limited to 'png8.c')
-rwxr-xr-xpng8.c263
1 files changed, 263 insertions, 0 deletions
diff --git a/png8.c b/png8.c
new file mode 100755
index 0000000..6022562
--- /dev/null
+++ b/png8.c
@@ -0,0 +1,263 @@
+/*
+
+ png8 - Simple PNG sprite strip converter for assembly targets
+
+ Copyright (C) 2016 Ian Cowburn <ianc@noddybox.co.uk>
+
+ 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 <http://www.gnu.org/licenses/>.
+
+ -------------------------------------------------------------------------
+
+ Main
+
+*/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <time.h>
+#include <setjmp.h>
+
+#include <png.h>
+
+/* ---------------------------------------- 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 <options> <file> -- convert a file\n"
+"usage: png8 -h -- get help on <options>\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 <switches> <PNG file>\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 <text> - Use <text> 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
+*/