Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F126571
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/util/loadpng/loadpng.c b/util/loadpng/loadpng.c
new file mode 100644
index 00000000..3e5d9612
--- /dev/null
+++ b/util/loadpng/loadpng.c
@@ -0,0 +1,404 @@
+#ifdef USE_ALLEGRO
+
+/* loadpng, Allegro wrapper routines for libpng
+ * by Peter Wang (tjaden@users.sf.net).
+ *
+ * This file is hereby placed in the public domain.
+ */
+
+
+#include <png.h>
+#include <allegro.h>
+#include <allegro/internal/aintern.h>
+#include "loadpng.h"
+
+/* We need internals _color_load_depth and _fixup_loaded_bitmap. The
+ * first can be replaced by the new get_color_depth() function which
+ * is in Allegro 4.1 branch. But it's not worth it to break 4.0
+ * compatibility.
+ */
+
+
+
+double _png_screen_gamma = -1.0;
+int _png_compression_level = Z_BEST_COMPRESSION;
+
+
+
+/* get_gamma:
+ * Get screen gamma value one of three ways.
+ */
+static double get_gamma(void)
+{
+ if (_png_screen_gamma == -1.0) {
+ /* Use the environment variable if available.
+ * 2.2 is a good guess for PC monitors.
+ * 1.1 is good for my laptop.
+ */
+ AL_CONST char *gamma_str = getenv("SCREEN_GAMMA");
+ return (gamma_str) ? atof(gamma_str) : 2.2;
+ }
+
+ return _png_screen_gamma;
+}
+
+
+
+/* read_data:
+ * Custom read function to use Allegro packfile routines,
+ * rather than C streams (so we can read from datafiles!)
+ */
+static void read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
+{
+ PACKFILE *f = (PACKFILE *)png_get_io_ptr(png_ptr);
+ if ((png_uint_32)pack_fread(data, length, f) != length)
+ png_error(png_ptr, "read error (loadpng calling pack_fread)");
+}
+
+
+
+/* check_if_png:
+ * Check if input file is really PNG format.
+ */
+#define PNG_BYTES_TO_CHECK 4
+
+static int check_if_png(PACKFILE *fp)
+{
+ unsigned char buf[PNG_BYTES_TO_CHECK];
+
+ ASSERT(fp);
+
+ if (pack_fread(buf, PNG_BYTES_TO_CHECK, fp) != PNG_BYTES_TO_CHECK)
+ return 0;
+
+ return (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0);
+}
+
+
+
+/* really_load_png:
+ * Worker routine, used by load_png and load_memory_png.
+ */
+static BITMAP *really_load_png(png_structp png_ptr, png_infop info_ptr, RGB *pal)
+{
+ BITMAP *bmp;
+ PALETTE tmppal;
+ png_uint_32 width, height, rowbytes;
+ int bit_depth, color_type, interlace_type;
+ double image_gamma, screen_gamma;
+ int intent;
+ int bpp, dest_bpp;
+ int tRNS_to_alpha = FALSE;
+ int number_passes, pass;
+
+ ASSERT(png_ptr && info_ptr && rgb);
+
+ /* The call to png_read_info() gives us all of the information from the
+ * PNG file before the first IDAT (image data chunk).
+ */
+ png_read_info(png_ptr, info_ptr);
+
+ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+ &interlace_type, NULL, NULL);
+
+ /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
+ * byte into separate bytes (useful for paletted and grayscale images).
+ */
+ png_set_packing(png_ptr);
+
+ /* Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
+ if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8))
+ png_set_expand(png_ptr);
+
+ /* Adds a full alpha channel if there is transparency information
+ * in a tRNS chunk. */
+ if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
+ png_set_tRNS_to_alpha(png_ptr);
+ tRNS_to_alpha = TRUE;
+ }
+
+ /* Convert 16-bits per colour component to 8-bits per colour component. */
+ if (bit_depth == 16)
+ png_set_strip_16(png_ptr);
+
+ /* Convert grayscale to RGB triplets */
+ if ((color_type == PNG_COLOR_TYPE_GRAY) ||
+ (color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_set_gray_to_rgb(png_ptr);
+
+ /* Optionally, tell libpng to handle the gamma correction for us. */
+ if (_png_screen_gamma != 0.0) {
+ screen_gamma = get_gamma();
+
+ if (png_get_sRGB(png_ptr, info_ptr, &intent))
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+ else {
+ if (png_get_gAMA(png_ptr, info_ptr, &image_gamma))
+ png_set_gamma(png_ptr, screen_gamma, image_gamma);
+ else
+ png_set_gamma(png_ptr, screen_gamma, 0.45455);
+ }
+ }
+
+ /* Turn on interlace handling. */
+ number_passes = png_set_interlace_handling(png_ptr);
+
+ /* Call to gamma correct and add the background to the palette
+ * and update info structure.
+ */
+ png_read_update_info(png_ptr, info_ptr);
+
+ /* Even if the user doesn't supply space for a palette, we want
+ * one for the load process.
+ */
+ if (!pal)
+ pal = tmppal;
+
+ /* Palettes. */
+ if (color_type & PNG_COLOR_MASK_PALETTE) {
+ int num_palette, i;
+ png_colorp palette;
+
+ if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)) {
+ /* We don't actually dither, we just copy the palette. */
+ for (i = 0; ((i < num_palette) && (i < 256)); i++) {
+ pal[i].r = palette[i].red >> 2; /* 256 -> 64 */
+ pal[i].g = palette[i].green >> 2;
+ pal[i].b = palette[i].blue >> 2;
+ }
+
+ for (; i < 256; i++)
+ pal[i].r = pal[i].g = pal[i].b = 0;
+ }
+ }
+ else {
+ generate_332_palette(pal);
+ }
+
+ rowbytes = png_get_rowbytes(png_ptr, info_ptr);
+
+ /* Allocate the memory to hold the image using the fields of info_ptr. */
+ bpp = rowbytes * 8 / width;
+
+ /* Allegro cannot handle less than 8 bpp. */
+ if (bpp < 8)
+ bpp = 8;
+
+ dest_bpp = _color_load_depth(bpp, (bpp == 32));
+ bmp = create_bitmap_ex(bpp, width, height);
+
+ /* Maybe flip RGB to BGR. */
+ if ((bpp == 24) || (bpp == 32)) {
+ int c = makecol_depth(bpp, 0, 0, 255);
+ unsigned char *pc = (unsigned char *)&c;
+ if (pc[0] == 255)
+ png_set_bgr(png_ptr);
+#ifdef ALLEGRO_BIG_ENDIAN
+ png_set_swap_alpha(png_ptr);
+#endif
+ }
+
+ /* Read the image, one line at a line (easier to debug!) */
+ for (pass = 0; pass < number_passes; pass++) {
+ png_uint_32 y;
+ for (y = 0; y < height; y++)
+ png_read_row(png_ptr, bmp->line[y], NULL);
+ }
+
+ /* Let Allegro convert the image into the desired colour depth. */
+ if (dest_bpp != bpp)
+ bmp = _fixup_loaded_bitmap(bmp, pal, dest_bpp);
+
+ /* Read rest of file, and get additional chunks in info_ptr. */
+ png_read_end(png_ptr, info_ptr);
+
+ return bmp;
+}
+
+
+
+/* load_png:
+ * Load a PNG file from disk, doing colour coversion if required.
+ */
+BITMAP *load_png(AL_CONST char *filename, RGB *pal)
+{
+ PACKFILE *fp;
+ BITMAP *bmp;
+
+ ASSERT(filename);
+
+ fp = pack_fopen(filename, "r");
+ if (!fp)
+ return NULL;
+
+ bmp = load_png_pf(fp, pal);
+
+ pack_fclose(fp);
+
+ return bmp;
+}
+
+
+
+/* load_png_pf:
+ * Load a PNG file from disk, doing colour coversion if required.
+ */
+BITMAP *load_png_pf(PACKFILE *fp, RGB *pal)
+{
+ BITMAP *bmp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+
+ ASSERT(fp);
+
+ if (!check_if_png(fp)) {
+ return NULL;
+ }
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also supply the
+ * the compiler header file version, so that we know if the application
+ * was compiled with a compatible version of the library.
+ */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ (void *)NULL, NULL, NULL);
+ if (!png_ptr) {
+ return NULL;
+ }
+
+ /* Allocate/initialize the memory for image information. */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ return NULL;
+ }
+
+ /* Set error handling if you are using the setjmp/longjmp method (this is
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier.
+ */
+ if (setjmp(png_ptr->jmpbuf)) {
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ /* If we get here, we had a problem reading the file */
+ return NULL;
+ }
+
+ /* Use Allegro packfile routines. */
+ png_set_read_fn(png_ptr, fp, (png_rw_ptr)read_data);
+
+ /* We have already read some of the signature. */
+ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
+
+ /* Really load the image now. */
+ bmp = really_load_png(png_ptr, info_ptr, pal);
+
+ /* Clean up after the read, and free any memory allocated. */
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ return bmp;
+}
+
+
+
+/* read_data_memory:
+ * Custom reader function to read a PNG file from a memory buffer.
+ */
+
+typedef struct {
+ AL_CONST unsigned char *buffer;
+ png_uint_32 bufsize;
+ png_uint_32 current_pos;
+} MEMORY_READER_STATE;
+
+static void read_data_memory(png_structp png_ptr, png_bytep data, png_uint_32 length)
+{
+ MEMORY_READER_STATE *f = (MEMORY_READER_STATE *)png_get_io_ptr(png_ptr);
+
+ if (length > (f->bufsize - f->current_pos))
+ png_error(png_ptr, "read error in read_data_memory (loadpng)");
+
+ memcpy(data, f->buffer + f->current_pos, length);
+ f->current_pos += length;
+}
+
+
+
+/* check_if_png_memory:
+ * Check if input buffer is really PNG format.
+ */
+static int check_if_png_memory(AL_CONST void *buffer)
+{
+ unsigned char *buf = (unsigned char *)buffer;
+ return (png_sig_cmp(buf, (png_size_t)0, PNG_BYTES_TO_CHECK) == 0);
+}
+
+
+
+/* load_memory_png:
+ * Load a PNG file from memory, doing colour coversion if required.
+ */
+BITMAP *load_memory_png(AL_CONST void *buffer, int bufsize, RGB *pal)
+{
+ MEMORY_READER_STATE memory_reader_state;
+ BITMAP *bmp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+
+ if (!buffer || (bufsize <= 0))
+ return NULL;
+
+ if (!check_if_png_memory(buffer))
+ return NULL;
+
+ /* Create and initialize the png_struct with the desired error handler
+ * functions. If you want to use the default stderr and longjump method,
+ * you can supply NULL for the last three parameters. We also supply the
+ * the compiler header file version, so that we know if the application
+ * was compiled with a compatible version of the library.
+ */
+ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
+ (void *)NULL, NULL, NULL);
+ if (!png_ptr)
+ return NULL;
+
+ /* Allocate/initialize the memory for image information. */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr) {
+ png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
+ return NULL;
+ }
+
+ /* Set error handling if you are using the setjmp/longjmp method (this is
+ * the normal method of doing things with libpng). REQUIRED unless you
+ * set up your own error handlers in the png_create_read_struct() earlier.
+ */
+ if (setjmp(png_ptr->jmpbuf)) {
+ /* Free all of the memory associated with the png_ptr and info_ptr */
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+ /* If we get here, we had a problem reading the file */
+ return NULL;
+ }
+
+ /* Set up the reader state. */
+ memory_reader_state.buffer = (unsigned char *)buffer;
+ memory_reader_state.bufsize = bufsize;
+ memory_reader_state.current_pos = PNG_BYTES_TO_CHECK;
+
+ /* Tell libpng to use our custom reader. */
+ png_set_read_fn(png_ptr, &memory_reader_state, (png_rw_ptr)read_data_memory);
+
+ /* We have already read some of the signature. */
+ png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK);
+
+ /* Really load the image now. */
+ bmp = really_load_png(png_ptr, info_ptr, pal);
+
+ /* Clean up after the read, and free any memory allocated. */
+ png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
+
+ return bmp;
+}
+
+#endif
diff --git a/util/loadpng/loadpng.h b/util/loadpng/loadpng.h
new file mode 100644
index 00000000..c666b4ab
--- /dev/null
+++ b/util/loadpng/loadpng.h
@@ -0,0 +1,79 @@
+#ifdef USE_ALLEGRO
+
+/* loadpng.h */
+/* This file is hereby placed in the public domain. */
+#ifndef _included_loadpng_h_
+#define _included_loadpng_h_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+/* Overkill :-) */
+#define LOADPNG_VERSION 1
+#define LOADPNG_SUBVERSION 5
+#define LOADPNG_VERSIONSTR "1.5"
+
+
+/* _png_screen_gamma is slightly overloaded (sorry):
+ *
+ * A value of 0.0 means: Don't do any gamma correction in load_png()
+ * and load_memory_png(). This meaning was introduced in v1.4.
+ *
+ * A value of -1.0 means: Use the value from the environment variable
+ * SCREEN_GAMMA (if available), otherwise fallback to a value of 2.2
+ * (a good guess for PC monitors, and the value for sRGB colourspace).
+ * This is the default.
+ *
+ * Otherwise, the value of _png_screen_gamma is taken as-is.
+ */
+extern double _png_screen_gamma;
+
+
+/* Choose zlib compression level for saving file.
+ * Default is Z_BEST_COMPRESSION.
+ */
+extern int _png_compression_level;
+
+
+/* Load a PNG from disk. */
+extern BITMAP *load_png(AL_CONST char *filename, RGB *pal);
+
+/* Load a PNG from some place. */
+extern BITMAP *load_png_pf(PACKFILE *fp, RGB *pal);
+
+/* Load a PNG from memory. */
+extern BITMAP *load_memory_png(AL_CONST void *buffer, int buffer_size, RGB *pal);
+
+/* Save a bitmap to disk in PNG format. */
+extern int save_png(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal);
+
+/* Adds `PNG' to Allegro's internal file type table.
+ * You can then just use load_bitmap and save_bitmap as usual.
+ */
+extern void register_png_file_type(void);
+
+/* Register an datafile type ID with Allegro, so that when an object
+ * with that type ID is encountered while loading a datafile, that
+ * object will be loaded as a PNG file.
+ */
+extern void register_png_datafile_object(int id);
+
+/* This is supposed to resemble jpgalleg_init in JPGalleg 2.0, just in
+ * case you are lazier than lazy. It contains these 3 lines of code:
+ * register_png_datafile_object(DAT_ID('P','N','G',' '));
+ * register_png_file_type();
+ * return 0;
+ */
+extern int loadpng_init(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _included_loadpng_h */
+
+#endif
diff --git a/util/loadpng/regpng.c b/util/loadpng/regpng.c
new file mode 100644
index 00000000..ecf7e40f
--- /dev/null
+++ b/util/loadpng/regpng.c
@@ -0,0 +1,72 @@
+#ifdef USE_ALLEGRO
+
+/* loadpng, Allegro wrapper routines for libpng
+ * by Peter Wang (tjaden@users.sf.net).
+ *
+ * This file is hereby placed in the public domain.
+ */
+
+
+#include <allegro.h>
+#include "loadpng.h"
+
+
+
+/* register_png_file_type:
+ */
+void register_png_file_type(void)
+{
+ register_bitmap_file_type("png", load_png, save_png);
+}
+
+
+
+/* register_png_datafile_object:
+ */
+
+static void *load_datafile_png(PACKFILE *f, long size)
+{
+ BITMAP *bmp;
+ void *buffer;
+
+ buffer = malloc(size);
+ if (!buffer)
+ return NULL;
+
+ if (pack_fread(buffer, size, f) != size) {
+ free(buffer);
+ return NULL;
+ }
+
+ bmp = load_memory_png(buffer, size, NULL);
+
+ free(buffer);
+
+ return bmp;
+}
+
+static void destroy_datafile_png(void *data)
+{
+ if (data) {
+ destroy_bitmap((BITMAP *)data);
+ }
+}
+
+void register_png_datafile_object(int id)
+{
+ register_datafile_object(id, load_datafile_png, destroy_datafile_png);
+}
+
+
+
+/* loadpng_init:
+ * This is supposed to resemble jpgalleg_init in JPGalleg 2.0.
+ */
+int loadpng_init(void)
+{
+ register_png_datafile_object(DAT_ID('P','N','G',' '));
+ register_png_file_type();
+ return 0;
+}
+
+#endif
diff --git a/util/loadpng/savepng.c b/util/loadpng/savepng.c
new file mode 100644
index 00000000..2138fdfa
--- /dev/null
+++ b/util/loadpng/savepng.c
@@ -0,0 +1,310 @@
+#ifdef USE_ALLEGRO
+
+/* loadpng, Allegro wrapper routines for libpng
+ * by Peter Wang (tjaden@users.sf.net).
+ *
+ * This file is hereby placed in the public domain.
+ */
+
+
+#include <png.h>
+#include <allegro.h>
+#include "loadpng.h"
+
+
+
+/* write_data:
+ * Custom write function to use Allegro packfile routines,
+ * rather than C streams.
+ */
+static void write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
+{
+ PACKFILE *f = (PACKFILE *)png_get_io_ptr(png_ptr);
+ if ((png_uint_32)pack_fwrite(data, length, f) != length)
+ png_error(png_ptr, "write error (loadpng calling pack_fwrite)");
+}
+
+/* Don't think Allegro has any problem with buffering
+ * (rather, Allegro provides no way to flush packfiles).
+ */
+static void flush_data(png_structp png_ptr) { (void)png_ptr; }
+
+
+
+/* save_indexed:
+ * Core save routine for 8 bpp images.
+ * */
+static int save_indexed(png_structp png_ptr, BITMAP *bmp)
+{
+ ASSERT(bitmap_color_depth(bmp) == 8);
+
+ if (is_memory_bitmap(bmp)) { /* fast path */
+ int y;
+
+ for (y=0; y<bmp->h; y++) {
+ png_write_row(png_ptr, bmp->line[y]);
+ }
+
+ return 1;
+ }
+ else { /* generic case */
+ unsigned char *rowdata;
+ int x, y;
+
+ rowdata = (unsigned char *)malloc(bmp->w * 3);
+ if (!rowdata)
+ return 0;
+
+ for (y=0; y<bmp->h; y++) {
+ unsigned char *p = rowdata;
+
+ for (x=0; x<bmp->w; x++) {
+ *p++ = getpixel(bmp, x, y);
+ }
+
+ png_write_row(png_ptr, rowdata);
+ }
+
+ free(rowdata);
+
+ return 1;
+ }
+}
+
+
+
+/* save_rgb:
+ * Core save routine for 15/16/24 bpp images (original by Martijn Versteegh).
+ */
+static int save_rgb(png_structp png_ptr, BITMAP *bmp)
+{
+ AL_CONST int depth = bitmap_color_depth(bmp);
+ unsigned char *rowdata;
+ int y, x;
+
+ ASSERT(depth == 15 || depth == 16 || depth == 24);
+
+ rowdata = (unsigned char *)malloc(bmp->w * 3);
+ if (!rowdata)
+ return 0;
+
+ for (y=0; y<bmp->h; y++) {
+ unsigned char *p = rowdata;
+
+ if (depth == 15) {
+ for (x = 0; x < bmp->w; x++) {
+ int c = getpixel(bmp, x, y);
+ *p++ = getr15(c);
+ *p++ = getg15(c);
+ *p++ = getb15(c);
+ }
+ }
+ else if (depth == 16) {
+ for (x = 0; x < bmp->w; x++) {
+ int c = getpixel(bmp, x, y);
+ *p++ = getr16(c);
+ *p++ = getg16(c);
+ *p++ = getb16(c);
+ }
+ }
+ else { /* depth == 24 */
+ for (x = 0; x < bmp->w; x++) {
+ int c = getpixel(bmp, x, y);
+ *p++ = getr24(c);
+ *p++ = getg24(c);
+ *p++ = getb24(c);
+ }
+ }
+
+ png_write_row(png_ptr, rowdata);
+ }
+
+ free(rowdata);
+
+ return 1;
+}
+
+
+
+/* save_rgba:
+ * Core save routine for 32 bpp images.
+ */
+static int save_rgba(png_structp png_ptr, BITMAP *bmp)
+{
+ unsigned char *rowdata;
+ int x, y;
+
+ ASSERT(bitmap_color_depth(bmp) == 32);
+
+ rowdata = (unsigned char *)malloc(bmp->w * 4);
+ if (!rowdata)
+ return 0;
+
+ for (y=0; y<bmp->h; y++) {
+ unsigned char *p = rowdata;
+
+ for (x=0; x<bmp->w; x++) {
+ int c = getpixel(bmp, x, y);
+ *p++ = getr32(c);
+ *p++ = getg32(c);
+ *p++ = getb32(c);
+ *p++ = geta32(c);
+ }
+
+ png_write_row(png_ptr, rowdata);
+ }
+
+ free(rowdata);
+
+ return 1;
+}
+
+
+
+/* save_png:
+ * Writes a non-interlaced, no-frills PNG, taking the usual save_xyz
+ * parameters. Returns non-zero on error.
+ */
+static int really_save_png(PACKFILE *fp, BITMAP *bmp, AL_CONST RGB *pal)
+{
+ png_structp png_ptr = NULL;
+ png_infop info_ptr = NULL;
+ int depth;
+ int colour_type;
+
+ depth = bitmap_color_depth(bmp);
+ if (depth == 8 && !pal)
+ return -1;
+
+ /* Create and initialize the png_struct with the
+ * desired error handler functions.
+ */
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
+ (void *)NULL, NULL, NULL);
+ if (!png_ptr)
+ goto Error;
+
+ /* Allocate/initialize the image information data. */
+ info_ptr = png_create_info_struct(png_ptr);
+ if (!info_ptr)
+ goto Error;
+
+ /* Set error handling. */
+ if (setjmp(png_ptr->jmpbuf)) {
+ /* If we get here, we had a problem reading the file. */
+ goto Error;
+ }
+
+ /* Use packfile routines. */
+ png_set_write_fn(png_ptr, fp, (png_rw_ptr)write_data, flush_data);
+
+ /* Set the image information here. Width and height are up to 2^31,
+ * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE.
+ */
+ if (depth == 8)
+ colour_type = PNG_COLOR_TYPE_PALETTE;
+ else if (depth == 32)
+ colour_type = PNG_COLOR_TYPE_RGB_ALPHA;
+ else
+ colour_type = PNG_COLOR_TYPE_RGB;
+
+ /* Set compression level. */
+ png_set_compression_level(png_ptr, _png_compression_level);
+
+ png_set_IHDR(png_ptr, info_ptr, bmp->w, bmp->h, 8, colour_type,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
+ PNG_FILTER_TYPE_BASE);
+
+ /* Set the palette if there is one. Required for indexed-color images. */
+ if (colour_type == PNG_COLOR_TYPE_PALETTE) {
+ png_color palette[256];
+ int i;
+
+ for (i = 0; i < 256; i++) {
+ palette[i].red = _rgb_scale_6[pal[i].r]; /* 64 -> 256 */
+ palette[i].green = _rgb_scale_6[pal[i].g];
+ palette[i].blue = _rgb_scale_6[pal[i].b];
+ }
+
+ /* Set palette colors. */
+ png_set_PLTE(png_ptr, info_ptr, palette, 256);
+ }
+
+ /* Optionally write comments into the image ... Nah. */
+
+ /* Write the file header information. */
+ png_write_info(png_ptr, info_ptr);
+
+ /* Once we write out the header, the compression type on the text
+ * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
+ * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
+ * at the end.
+ */
+
+ /* Save the data. */
+ switch (depth) {
+ case 8:
+ if (!save_indexed(png_ptr, bmp))
+ goto Error;
+ break;
+ case 15:
+ case 16:
+ case 24:
+ if (!save_rgb(png_ptr, bmp))
+ goto Error;
+ break;
+ case 32:
+ if (!save_rgba(png_ptr, bmp))
+ goto Error;
+ break;
+ default:
+ ASSERT(FALSE);
+ goto Error;
+ }
+
+ png_write_end(png_ptr, info_ptr);
+
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ return 0;
+
+ Error:
+
+ if (png_ptr) {
+ if (info_ptr)
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ else
+ png_destroy_write_struct(&png_ptr, NULL);
+ }
+
+ return -1;
+}
+
+
+int save_png(AL_CONST char *filename, BITMAP *bmp, AL_CONST RGB *pal)
+{
+ PACKFILE *fp;
+ int result;
+
+ ASSERT(filename);
+ ASSERT(bmp);
+
+ fp = pack_fopen(filename, "w");
+ if (!fp)
+ return -1;
+
+ acquire_bitmap(bmp);
+ result = really_save_png(fp, bmp, pal);
+ release_bitmap(bmp);
+
+ pack_fclose(fp);
+
+ return result;
+}
+
+#endif
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Thu, Jun 11, 12:01 PM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68938
Default Alt Text
(22 KB)
Attached To
Mode
R75 R-Tech1
Attached
Detach File
Event Timeline