mirror of
https://github.com/aseprite/aseprite.git
synced 2025-02-03 20:54:01 +00:00
Added support to load png files through Allegro library (now you can save/load palettes in PNG files)
This commit is contained in:
parent
0e0dacb158
commit
33ca3cf8e0
23
makefile.gcc
23
makefile.gcc
@ -6,12 +6,13 @@ _default: default
|
||||
######################################################################
|
||||
# Setup CFLAGS and LFLAGS for GCC
|
||||
|
||||
CFLAGS += -Wall -I. -Isrc -Ithird_party \
|
||||
-I$(LIBFREETYPE_DIR)/include \
|
||||
-I$(LIBJPEG_DIR) \
|
||||
-I$(LIBPNG_DIR) \
|
||||
-I$(ZLIB_DIR) \
|
||||
-Wno-deprecated-declarations \
|
||||
CFLAGS += -Wall -I. -Isrc -Ithird_party \
|
||||
-I$(LIBFREETYPE_DIR)/include \
|
||||
-I$(LIBJPEG_DIR) \
|
||||
-I$(LIBPNG_DIR) \
|
||||
-I$(ZLIB_DIR) \
|
||||
-I$(LOADPNG_DIR) \
|
||||
-Wno-deprecated-declarations \
|
||||
-DPNG_NO_MMX_CODE
|
||||
|
||||
LFLAGS += $(THIRD_PARTY_LIBS)
|
||||
@ -76,6 +77,10 @@ $(ZLIB_LIB): $(ZLIB_OBJS)
|
||||
-rm -f $@
|
||||
ar rs $@ $^
|
||||
|
||||
$(LOADPNG_LIB): $(LOADPNG_OBJS)
|
||||
-rm -f $@
|
||||
ar rs $@ $^
|
||||
|
||||
######################################################################
|
||||
# Rules to build objects and the application
|
||||
|
||||
@ -118,7 +123,8 @@ VPATH = src \
|
||||
$(LIBGD_DIR) \
|
||||
$(LIBJPEG_DIR) \
|
||||
$(LIBPNG_DIR) \
|
||||
$(ZLIB_DIR)
|
||||
$(ZLIB_DIR) \
|
||||
$(LOADPNG_DIR)
|
||||
|
||||
ASE_DEPS = $(ASE_OBJS) $(THIRD_PARTY_LIBS)
|
||||
|
||||
@ -149,6 +155,9 @@ $(OBJ_DIR)/png.%$(OBJ): %.c
|
||||
$(OBJ_DIR)/zlib.%$(OBJ): %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
$(OBJ_DIR)/loadpng.%$(OBJ): %.c
|
||||
$(CC) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
######################################################################
|
||||
# Application
|
||||
|
||||
|
20
makefile.lst
20
makefile.lst
@ -466,6 +466,20 @@ ZLIB_OBJS = $(addprefix $(OBJ_DIR)/zlib., \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(ZLIB_SOURCES)))))
|
||||
|
||||
######################################################################
|
||||
# loadpng
|
||||
|
||||
LOADPNG_LIB = $(OBJ_DIR)/libloadpng$(LIB_EXT)
|
||||
LOADPNG_DIR = third_party/loadpng
|
||||
LOADPNG_SOURCES = \
|
||||
$(LOADPNG_DIR)/loadpng.c \
|
||||
$(LOADPNG_DIR)/savepng.c \
|
||||
$(LOADPNG_DIR)/regpng.c
|
||||
|
||||
LOADPNG_OBJS = $(addprefix $(OBJ_DIR)/loadpng., \
|
||||
$(addsuffix $(OBJ), \
|
||||
$(notdir $(basename $(LOADPNG_SOURCES)))))
|
||||
|
||||
######################################################################
|
||||
# All objects and libraries
|
||||
|
||||
@ -475,14 +489,16 @@ ALL_OBJS = \
|
||||
$(LIBART_OBJS) \
|
||||
$(LIBJPEG_OBJS) \
|
||||
$(LIBPNG_OBJS) \
|
||||
$(ZLIB_OBJS)
|
||||
$(ZLIB_OBJS) \
|
||||
$(LOADPNG_OBJS)
|
||||
|
||||
THIRD_PARTY_LIBS = \
|
||||
$(LIBART_LIB) \
|
||||
$(LIBFREETYPE_LIB) \
|
||||
$(LIBJPEG_LIB) \
|
||||
$(LIBPNG_LIB) \
|
||||
$(ZLIB_LIB)
|
||||
$(ZLIB_LIB) \
|
||||
$(LOADPNG_LIB)
|
||||
|
||||
######################################################################
|
||||
# Tests
|
||||
|
11
makefile.vc
11
makefile.vc
@ -29,6 +29,7 @@ CFLAGS = -nologo \
|
||||
-I$(LIBJPEG_DIR) \
|
||||
-I$(LIBPNG_DIR) \
|
||||
-I$(ZLIB_DIR) \
|
||||
-I$(LOADPNG_DIR) \
|
||||
-DPNG_NO_MMX_CODE
|
||||
|
||||
LFLAGS = -NOLOGO -SUBSYSTEM:WINDOWS -MACHINE:X86
|
||||
@ -111,6 +112,10 @@ $(ZLIB_LIB): $(ZLIB_OBJS)
|
||||
-rm -f $@
|
||||
lib -NOLOGO -OUT:$@ $^
|
||||
|
||||
$(LOADPNG_LIB): $(LOADPNG_OBJS)
|
||||
-rm -f $@
|
||||
lib -NOLOGO -OUT:$@ $^
|
||||
|
||||
######################################################################
|
||||
# Rules to build objects and the application
|
||||
|
||||
@ -153,7 +158,8 @@ VPATH = src \
|
||||
$(LIBGD_DIR) \
|
||||
$(LIBJPEG_DIR) \
|
||||
$(LIBPNG_DIR) \
|
||||
$(ZLIB_DIR)
|
||||
$(ZLIB_DIR) \
|
||||
$(LOADPNG_DIR)
|
||||
|
||||
ASE_DEPS = $(ASE_OBJS) $(THIRD_PARTY_LIBS)
|
||||
|
||||
@ -181,6 +187,9 @@ $(OBJ_DIR)/png.%$(OBJ): %.c
|
||||
$(OBJ_DIR)/zlib.%$(OBJ): %.c
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
$(OBJ_DIR)/loadpng.%$(OBJ): %.c
|
||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||
|
||||
######################################################################
|
||||
# Application
|
||||
|
||||
|
@ -305,7 +305,7 @@ static void select_all_command(JWidget widget)
|
||||
static void load_command(JWidget widget)
|
||||
{
|
||||
Palette *palette;
|
||||
jstring filename = ase_file_selector(_("Load Palette"), "", "pcx,bmp,tga,lbm,col");
|
||||
jstring filename = ase_file_selector(_("Load Palette"), "", "png,pcx,bmp,tga,lbm,col");
|
||||
if (!filename.empty()) {
|
||||
palette = palette_load(filename.c_str());
|
||||
if (!palette) {
|
||||
@ -324,7 +324,7 @@ static void save_command(JWidget widget)
|
||||
int ret;
|
||||
|
||||
again:
|
||||
filename = ase_file_selector(_("Save Palette"), "", "pcx,bmp,tga,col");
|
||||
filename = ase_file_selector(_("Save Palette"), "", "png,pcx,bmp,tga,col");
|
||||
if (!filename.empty()) {
|
||||
if (exists(filename.c_str())) {
|
||||
ret = jalert("%s<<%s<<%s||%s",
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "ase_exception.h"
|
||||
#include "core/app.h"
|
||||
#include "loadpng.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Information for "ident".
|
||||
@ -40,6 +41,9 @@ public:
|
||||
allegro_init();
|
||||
set_uformat(U_ASCII);
|
||||
install_timer();
|
||||
|
||||
// Register PNG as a supported bitmap type
|
||||
register_bitmap_file_type("png", load_png, save_png);
|
||||
}
|
||||
~Allegro() {
|
||||
remove_timer();
|
||||
|
@ -311,7 +311,8 @@ Palette* palette_load(const char *filename)
|
||||
|
||||
ustrcpy(ext, get_extension(filename));
|
||||
|
||||
if ((ustricmp(ext, "pcx") == 0) ||
|
||||
if ((ustricmp(ext, "png") == 0) ||
|
||||
(ustricmp(ext, "pcx") == 0) ||
|
||||
(ustricmp(ext, "bmp") == 0) ||
|
||||
(ustricmp(ext, "tga") == 0) ||
|
||||
(ustricmp(ext, "lbm") == 0)) {
|
||||
@ -340,7 +341,8 @@ bool palette_save(Palette* pal, const char *filename)
|
||||
|
||||
ustrcpy(ext, get_extension(filename));
|
||||
|
||||
if ((ustricmp(ext, "pcx") == 0) ||
|
||||
if ((ustricmp(ext, "png") == 0) ||
|
||||
(ustricmp(ext, "pcx") == 0) ||
|
||||
(ustricmp(ext, "bmp") == 0) ||
|
||||
(ustricmp(ext, "tga") == 0)) {
|
||||
PALETTE rgbpal;
|
||||
|
165
third_party/loadpng/CHANGES.txt
vendored
Normal file
165
third_party/loadpng/CHANGES.txt
vendored
Normal file
@ -0,0 +1,165 @@
|
||||
------- April 1999 -------
|
||||
|
||||
?? Wrote load_png wrapper
|
||||
|
||||
??+1 Cleaned up a bit, tried getting grayscale and
|
||||
auto-MagicPink conversion working.
|
||||
|
||||
9 Now can read gamma from environment variable.
|
||||
Changed default gamma to 2.2.
|
||||
|
||||
13 Added save_png, using pieces from allpng.c
|
||||
|
||||
15 Fixed stupid bug I created in save_hicolour.
|
||||
Added copyright notice.
|
||||
Now uses packfile routines.
|
||||
Added #ifdef __cplusplus hack.
|
||||
Released: version 0.1.
|
||||
|
||||
------- December 1999 -------
|
||||
|
||||
22 Updated to work with Allegro 3.9.xx.
|
||||
Fixed alpha channel support.
|
||||
Added alpha.c
|
||||
test.c renamed to example.c
|
||||
Released: version 0.2
|
||||
|
||||
------- January 1999 -------
|
||||
|
||||
3 Applied fix for < 8 bpp images (thanks to Dave Dribin)
|
||||
Released: version 0.3
|
||||
|
||||
------- October 2000 -------
|
||||
|
||||
12 Updated const-correctness in accordance with Allegro.
|
||||
Released: version 0.4
|
||||
|
||||
------- April 2001 -------
|
||||
|
||||
11 "Fixed" RGB/BGR problem with loading RGBA images.
|
||||
Use GFX_AUTODETECT in examples (GFX_SAFE changed in Allegro).
|
||||
Released: version 0.5
|
||||
|
||||
------- July 2001 -------
|
||||
|
||||
13 Reverted to 0.4 codebase, as 0.5 was really broken (oops).
|
||||
Added "depth" argument to examples.
|
||||
Commented out the BGR flipping code, which was incorrect I think
|
||||
anyway. Someone with a BGR card should check it out.
|
||||
Released: version 0.6
|
||||
|
||||
------- January 2002 -------
|
||||
|
||||
03 allegro/aintern.h -> allegro/internal/aintern.h (Allegro 4.0)
|
||||
Released: version 0.7
|
||||
|
||||
------- February 2002 -------
|
||||
|
||||
25 Fixed a problem with passing NULL for pal to load_png.
|
||||
Released: version 0.8
|
||||
|
||||
------- March 2002 -------
|
||||
|
||||
30 Tentative fixes for loading/saving RGBA images.
|
||||
Thanks to Chris Graham for reporting the problem.
|
||||
Minor changes to examples and makefile.
|
||||
|
||||
------- May 2002 -------
|
||||
|
||||
06 Added shared library (unix) and install support into makefiles,
|
||||
and cleaned them up. Thanks to Robbert Haarman for the start.
|
||||
Minor changes for -W warnings.
|
||||
|
||||
07 Dave Dribin fixed a problem that surfaced with some buggy versions
|
||||
of libpng (1.0.13, 1.2.2).
|
||||
Moved the thanks section into a separate document.
|
||||
|
||||
08 Fixed a puny mistake in the makefile.
|
||||
|
||||
12 Released: version 0.9
|
||||
|
||||
16 Tentative fixes for sometimes-problems loading RGB images.
|
||||
|
||||
19 Released: version 0.10
|
||||
|
||||
------- September 2002 -------
|
||||
|
||||
03 Dave Dribin fixed two problems with images with alpha channels.
|
||||
|
||||
04 Released: version 0.11
|
||||
|
||||
------- April 2003 -------
|
||||
|
||||
27 Mostly incorporated Ceniza's changes (load_memory_png and loading
|
||||
from datafile support, plus an example).
|
||||
|
||||
28 Reworked those changes a little.
|
||||
|
||||
------- May 2003 -------
|
||||
|
||||
02 Miscellaneous changes; put examples into separate directory
|
||||
(now that we have three!).
|
||||
|
||||
04 Signal errors on read/write failure.
|
||||
Released: version 1.0.
|
||||
|
||||
20 Calling load_png with NULL for palette argument was not converting
|
||||
paletted images to high/truecolour properly. Fixed. Thanks to
|
||||
Lothar May for pointing it out.
|
||||
Released: version 1.1.
|
||||
|
||||
------- October 2003 -------
|
||||
|
||||
13 Changed the method of scaling of palette values from 6 bits
|
||||
to 8 bits. Instead of just multiplying by 4, now we use
|
||||
_rgb_scale_6[] so that e.g. 0 -> 0, but 63 -> 255.
|
||||
Thanks Nicolas Lemal for the idea.
|
||||
Released: version 1.2.
|
||||
|
||||
16 MSVC doesn't like pointer arithmetic on void*'s, pointed out by
|
||||
Chris Condrat.
|
||||
Re-released: version 1.2 (I forgot to update version constants anyway).
|
||||
|
||||
------- April 2004 -------
|
||||
|
||||
26 Jon Rafkind suggested to use _getpixel*/_putpixel* in loader to
|
||||
speed up loading of large images.
|
||||
Split up the code into three files. This prevents the linker pulling
|
||||
in unused code, e.g. many people don't need save_png.
|
||||
|
||||
28 It turns out that loadpng's origin (example.c from libpng docs) was in
|
||||
the public domain, so now loadpng is in the public domain as well.
|
||||
Released: version 1.3.
|
||||
|
||||
------- October 2004 -------
|
||||
|
||||
09 Made save_png handle non-memory bitmaps as well.
|
||||
|
||||
10 Fixed some bugs with load_png(). Now everything in PngSuite loads
|
||||
properly, and with correct gamma correction, except for:
|
||||
- bKGD chunks (solid background colours) are not respected.
|
||||
I chose this in the past, but I wonder if I should change it?
|
||||
- pHYs chunks (physical dimensions) are not respected.
|
||||
(BTW, this was all tested with Valgrind - no errors)
|
||||
|
||||
_png_screen_gamma can now be 0.0 to disable gamma correction, i.e. if
|
||||
you don't know the screen gamma, it might be best not to guess.
|
||||
|
||||
Got rid of inefficient BGR-handling hack and did things properly.
|
||||
|
||||
New example: browse.c (for mass testing, e.g. PngSuite)
|
||||
|
||||
Released: version 1.4pre1.
|
||||
|
||||
------- August 2005 -------
|
||||
|
||||
18 Emmanuel Anne made _png_compression_level actually work.
|
||||
|
||||
Released: version 1.4.
|
||||
|
||||
------- April 2006 -------
|
||||
|
||||
9 Fix an endianness on big-endian machines, from Siarhei Siamashka.
|
||||
I haven't tested it.
|
||||
|
||||
Released: version 1.5.
|
53
third_party/loadpng/README.txt
vendored
Normal file
53
third_party/loadpng/README.txt
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
loadpng: glue for Allegro and libpng
|
||||
|
||||
|
||||
This wrapper is mostly a copy and paste job from example.c in the
|
||||
libpng docs, stripping out the useless transformations and making it
|
||||
use Allegro BITMAP and PALETTE structures. It is placed in the public
|
||||
domain.
|
||||
|
||||
|
||||
Requirements:
|
||||
|
||||
Allegro http://alleg.sourceforge.net/
|
||||
libpng http://www.libpng.org/pub/png/
|
||||
zlib http://www.gzip.org/zlib/
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
See loadpng.h for functions and their descriptions. There is a
|
||||
simple example program called example.c, a program demonstrating
|
||||
alpha translucency in exalpha.c, and a program demonstrating how to
|
||||
load a PNG object from a datafile in exdata.c.
|
||||
|
||||
To compile, just run "make" (or perhaps "mingw32-make"). To use
|
||||
loadpng, you need to link with libpng, zlib in addition to loadpng
|
||||
itself, e.g.
|
||||
|
||||
gcc mygame.c -lldpng -lpng -lz -lalleg
|
||||
|
||||
I recommend you copy loadpng's files into your own project's directory
|
||||
and compile loadpng as part of your project.
|
||||
|
||||
|
||||
Notes:
|
||||
|
||||
- Grayscale images will be loaded in as 24 bit images, or 32 bit
|
||||
images if they contain an alpha channel. These will then be
|
||||
converted as usual, according to Allegro's conversion semantics. Be
|
||||
aware of this if you have disabled automatic colour depth
|
||||
conversion.
|
||||
|
||||
- save_png() doesn't save any gamma chunk. I'm thinking of making it
|
||||
write an sRGB chunk by default. If you want tight control of how
|
||||
your images are saved, I recommend hacking save_png() to suit your
|
||||
needs. There's simply too many options.
|
||||
|
||||
|
||||
Enjoy!
|
||||
|
||||
Peter Wang (tjaden@users.sf.net)
|
||||
http://members.ozadsl.com.au/~tjaden/
|
||||
http://tjaden.strangesoft.net/
|
16
third_party/loadpng/THANKS.txt
vendored
Normal file
16
third_party/loadpng/THANKS.txt
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
Peter Wang is me.
|
||||
|
||||
Thanks to Martijn Versteegh for allpng.c, from which I took the actual
|
||||
routine which saves 15 / 16 bpp images.
|
||||
|
||||
The following people reported or fixed bugs or did something else
|
||||
(assuming I didn't forget):
|
||||
|
||||
- Dave Dribin
|
||||
- Lennart Steinke
|
||||
- Chris Graham
|
||||
- Robbert Haarman
|
||||
- Ceniza
|
||||
- Nicolas Lemal
|
||||
- Jon Rafkind
|
||||
- Emmanuel Anne
|
400
third_party/loadpng/loadpng.c
vendored
Normal file
400
third_party/loadpng/loadpng.c
vendored
Normal file
@ -0,0 +1,400 @@
|
||||
/* 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;
|
||||
}
|
75
third_party/loadpng/loadpng.h
vendored
Normal file
75
third_party/loadpng/loadpng.h
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/* 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 */
|
68
third_party/loadpng/regpng.c
vendored
Normal file
68
third_party/loadpng/regpng.c
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/* 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;
|
||||
}
|
306
third_party/loadpng/savepng.c
vendored
Normal file
306
third_party/loadpng/savepng.c
vendored
Normal file
@ -0,0 +1,306 @@
|
||||
/* 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user