]> git.draconx.ca Git - liblbx.git/blobdiff - src/png.c
lbximg: Convert to new decoding API.
[liblbx.git] / src / png.c
index c52db03e599ef7f7e48d5982272c8ff5eadb8229..cc885f7a6a8fb55b3f2219090b1d52712fde3bba 100644 (file)
--- a/src/png.c
+++ b/src/png.c
@@ -1,7 +1,7 @@
 /*
  * 2ooM: The Master of Orion II Reverse Engineering Project
  * PNG output routines for lbximg extration.
- * Copyright © 2013 Nick Bowler
+ * Copyright © 2013-2014 Nick Bowler
  *
  * 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
@@ -103,7 +103,7 @@ static void fill_png_palette(png_color *out, const struct lbx_colour *in)
 
 static void
 write_rgba_frame(png_structp png, png_infop info,
-                 unsigned char **framedata, unsigned char **mask,
+                 unsigned char *pixels, unsigned char *mask,
                  struct lbx_colour *lbx_palette)
 {
        png_uint_32 width = png_get_image_width(png, info);
@@ -133,10 +133,15 @@ write_rgba_frame(png_structp png, png_infop info,
        fill_png_palette(png_palette, lbx_palette);
        for (png_uint_32 y = 0; y < height; y++) {
                for (png_uint_32 x = 0; x < width; x++) {
-                       row[x][0] = png_palette[framedata[y][x]].red;
-                       row[x][1] = png_palette[framedata[y][x]].green;
-                       row[x][2] = png_palette[framedata[y][x]].blue;
-                       row[x][3] = mask[y][x] ? -1 : 0;
+                       unsigned long offset = (unsigned long) y * width + x;
+                       png_color *c = &png_palette[pixels[offset]];
+                       bool vis;
+
+                       vis = mask[offset/CHAR_BIT] & (1u << offset%CHAR_BIT);
+                       row[x][0] = c->red;
+                       row[x][1] = c->green;
+                       row[x][2] = c->blue;
+                       row[x][3] = -vis;
                }
                png_write_row(png, (void *)row);
        }
@@ -147,7 +152,7 @@ write_rgba_frame(png_structp png, png_infop info,
 
 static void
 write_masked_index_frame(png_structp png, png_infop info,
-                         unsigned char **framedata, unsigned char **mask)
+                         unsigned char *pixels, unsigned char *mask)
 {
        png_uint_32 width = png_get_image_width(png, info);
        png_uint_32 height = png_get_image_height(png, info);
@@ -174,8 +179,12 @@ write_masked_index_frame(png_structp png, png_infop info,
        png_write_info(png, info);
        for (png_uint_32 y = 0; y < height; y++) {
                for (png_uint_32 x = 0; x < width; x++) {
-                       row[x][0] = framedata[y][x];
-                       row[x][1] = mask[y][x] ? -1 : 0;
+                       unsigned long offset = (unsigned long) y * width + x;
+                       bool vis;
+
+                       vis = mask[offset/CHAR_BIT] & (1u << offset%CHAR_BIT);
+                       row[x][0] = pixels[offset];
+                       row[x][1] = -vis;
                }
                png_write_row(png, (void *)row);
        }
@@ -185,28 +194,35 @@ write_masked_index_frame(png_structp png, png_infop info,
 }
 
 static void
-write_palette_frame(png_structp png, png_infop info,
-                    unsigned char **framedata, struct lbx_colour *lbx_palette)
+write_index_frame(png_structp png, png_infop info, unsigned char *pixels)
 {
-       png_color png_palette[256];
+       png_uint_32 width = png_get_image_width(png, info);
+       png_uint_32 height = png_get_image_height(png, info);
 
-       fill_png_palette(png_palette, lbx_palette);
-       png_set_PLTE(png, info, png_palette, 256);
-       png_set_rows(png, info, framedata);
-       png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
+       png_write_info(png, info);
+       for (png_uint_32 y = 0; y < height; y++) {
+               unsigned long offset = (unsigned long) y * width;
+
+               png_write_row(png, (void *)(pixels+offset));
+       }
+       png_write_end(png, NULL);
 }
 
 static void
-write_index_frame(png_structp png, png_infop info, unsigned char **framedata)
+write_palette_frame(png_structp png, png_infop info,
+                    unsigned char *pixels, struct lbx_colour *lbx_palette)
 {
-       png_set_rows(png, info, framedata);
-       png_write_png(png, info, PNG_TRANSFORM_IDENTITY, NULL);
+       png_color png_palette[256];
+       fill_png_palette(png_palette, lbx_palette);
+       png_set_PLTE(png, info, png_palette, 256);
+
+       write_index_frame(png, info, pixels);
 }
 
 int img_output_png(FILE *f, const char *filename,
                    unsigned width, unsigned height,
-                   unsigned char **framedata, unsigned char **mask,
-                  struct lbx_colour *palette)
+                   unsigned char *pixels, unsigned char *mask,
+                   struct lbx_colour *palette)
 {
        bool masked = img_is_masked(mask, width, height);
        struct file_info file = { filename, f };
@@ -246,28 +262,28 @@ int img_output_png(FILE *f, const char *filename,
                             PNG_COMPRESSION_TYPE_DEFAULT,
                             PNG_FILTER_TYPE_DEFAULT);
 
-               write_rgba_frame(png, info, framedata, mask, palette);
+               write_rgba_frame(png, info, pixels, mask, palette);
        } else if (palette) {
                png_set_IHDR(png, info, width, height, 8,
                             PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
                             PNG_COMPRESSION_TYPE_DEFAULT,
                             PNG_FILTER_TYPE_DEFAULT);
 
-               write_palette_frame(png, info, framedata, palette);
+               write_palette_frame(png, info, pixels, palette);
        } else if (masked) {
                png_set_IHDR(png, info, width, height, 8,
                             PNG_COLOR_TYPE_GRAY_ALPHA, PNG_INTERLACE_NONE,
                             PNG_COMPRESSION_TYPE_DEFAULT,
                             PNG_FILTER_TYPE_DEFAULT);
 
-               write_masked_index_frame(png, info, framedata, mask);
+               write_masked_index_frame(png, info, pixels, mask);
        } else {
                png_set_IHDR(png, info, width, height, 8,
                             PNG_COLOR_TYPE_GRAY, PNG_INTERLACE_NONE,
                             PNG_COMPRESSION_TYPE_DEFAULT,
                             PNG_FILTER_TYPE_DEFAULT);
 
-               write_index_frame(png, info, framedata);
+               write_index_frame(png, info, pixels);
        }
 
        png_destroy_write_struct(&png, &info);