/*
* 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
FILE *f;
};
-static int is_masked(unsigned char **mask, unsigned width, unsigned height)
-{
- for (unsigned y = 0; y < height; y++) {
- for (unsigned x = 0; x < width; x++) {
- if (mask[y][x] == 0)
- return 1;
- }
- }
-
- return 0;
-}
-
static void fatal(png_structp png, int err, const char *fmt, ...)
{
va_list ap;
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);
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);
}
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);
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);
}
}
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 = is_masked(mask, width, height);
+ bool masked = img_is_masked(mask, width, height);
struct file_info file = { filename, f };
png_structp png;
png_infop info;
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);