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
|
# Setup CFLAGS and LFLAGS for GCC
|
||||||
|
|
||||||
CFLAGS += -Wall -I. -Isrc -Ithird_party \
|
CFLAGS += -Wall -I. -Isrc -Ithird_party \
|
||||||
-I$(LIBFREETYPE_DIR)/include \
|
-I$(LIBFREETYPE_DIR)/include \
|
||||||
-I$(LIBJPEG_DIR) \
|
-I$(LIBJPEG_DIR) \
|
||||||
-I$(LIBPNG_DIR) \
|
-I$(LIBPNG_DIR) \
|
||||||
-I$(ZLIB_DIR) \
|
-I$(ZLIB_DIR) \
|
||||||
-Wno-deprecated-declarations \
|
-I$(LOADPNG_DIR) \
|
||||||
|
-Wno-deprecated-declarations \
|
||||||
-DPNG_NO_MMX_CODE
|
-DPNG_NO_MMX_CODE
|
||||||
|
|
||||||
LFLAGS += $(THIRD_PARTY_LIBS)
|
LFLAGS += $(THIRD_PARTY_LIBS)
|
||||||
@ -76,6 +77,10 @@ $(ZLIB_LIB): $(ZLIB_OBJS)
|
|||||||
-rm -f $@
|
-rm -f $@
|
||||||
ar rs $@ $^
|
ar rs $@ $^
|
||||||
|
|
||||||
|
$(LOADPNG_LIB): $(LOADPNG_OBJS)
|
||||||
|
-rm -f $@
|
||||||
|
ar rs $@ $^
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Rules to build objects and the application
|
# Rules to build objects and the application
|
||||||
|
|
||||||
@ -118,7 +123,8 @@ VPATH = src \
|
|||||||
$(LIBGD_DIR) \
|
$(LIBGD_DIR) \
|
||||||
$(LIBJPEG_DIR) \
|
$(LIBJPEG_DIR) \
|
||||||
$(LIBPNG_DIR) \
|
$(LIBPNG_DIR) \
|
||||||
$(ZLIB_DIR)
|
$(ZLIB_DIR) \
|
||||||
|
$(LOADPNG_DIR)
|
||||||
|
|
||||||
ASE_DEPS = $(ASE_OBJS) $(THIRD_PARTY_LIBS)
|
ASE_DEPS = $(ASE_OBJS) $(THIRD_PARTY_LIBS)
|
||||||
|
|
||||||
@ -149,6 +155,9 @@ $(OBJ_DIR)/png.%$(OBJ): %.c
|
|||||||
$(OBJ_DIR)/zlib.%$(OBJ): %.c
|
$(OBJ_DIR)/zlib.%$(OBJ): %.c
|
||||||
$(CC) $(CFLAGS) -o $@ -c $<
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
|
$(OBJ_DIR)/loadpng.%$(OBJ): %.c
|
||||||
|
$(CC) $(CFLAGS) -o $@ -c $<
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Application
|
# Application
|
||||||
|
|
||||||
|
20
makefile.lst
20
makefile.lst
@ -466,6 +466,20 @@ ZLIB_OBJS = $(addprefix $(OBJ_DIR)/zlib., \
|
|||||||
$(addsuffix $(OBJ), \
|
$(addsuffix $(OBJ), \
|
||||||
$(notdir $(basename $(ZLIB_SOURCES)))))
|
$(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
|
# All objects and libraries
|
||||||
|
|
||||||
@ -475,14 +489,16 @@ ALL_OBJS = \
|
|||||||
$(LIBART_OBJS) \
|
$(LIBART_OBJS) \
|
||||||
$(LIBJPEG_OBJS) \
|
$(LIBJPEG_OBJS) \
|
||||||
$(LIBPNG_OBJS) \
|
$(LIBPNG_OBJS) \
|
||||||
$(ZLIB_OBJS)
|
$(ZLIB_OBJS) \
|
||||||
|
$(LOADPNG_OBJS)
|
||||||
|
|
||||||
THIRD_PARTY_LIBS = \
|
THIRD_PARTY_LIBS = \
|
||||||
$(LIBART_LIB) \
|
$(LIBART_LIB) \
|
||||||
$(LIBFREETYPE_LIB) \
|
$(LIBFREETYPE_LIB) \
|
||||||
$(LIBJPEG_LIB) \
|
$(LIBJPEG_LIB) \
|
||||||
$(LIBPNG_LIB) \
|
$(LIBPNG_LIB) \
|
||||||
$(ZLIB_LIB)
|
$(ZLIB_LIB) \
|
||||||
|
$(LOADPNG_LIB)
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Tests
|
# Tests
|
||||||
|
11
makefile.vc
11
makefile.vc
@ -29,6 +29,7 @@ CFLAGS = -nologo \
|
|||||||
-I$(LIBJPEG_DIR) \
|
-I$(LIBJPEG_DIR) \
|
||||||
-I$(LIBPNG_DIR) \
|
-I$(LIBPNG_DIR) \
|
||||||
-I$(ZLIB_DIR) \
|
-I$(ZLIB_DIR) \
|
||||||
|
-I$(LOADPNG_DIR) \
|
||||||
-DPNG_NO_MMX_CODE
|
-DPNG_NO_MMX_CODE
|
||||||
|
|
||||||
LFLAGS = -NOLOGO -SUBSYSTEM:WINDOWS -MACHINE:X86
|
LFLAGS = -NOLOGO -SUBSYSTEM:WINDOWS -MACHINE:X86
|
||||||
@ -111,6 +112,10 @@ $(ZLIB_LIB): $(ZLIB_OBJS)
|
|||||||
-rm -f $@
|
-rm -f $@
|
||||||
lib -NOLOGO -OUT:$@ $^
|
lib -NOLOGO -OUT:$@ $^
|
||||||
|
|
||||||
|
$(LOADPNG_LIB): $(LOADPNG_OBJS)
|
||||||
|
-rm -f $@
|
||||||
|
lib -NOLOGO -OUT:$@ $^
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Rules to build objects and the application
|
# Rules to build objects and the application
|
||||||
|
|
||||||
@ -153,7 +158,8 @@ VPATH = src \
|
|||||||
$(LIBGD_DIR) \
|
$(LIBGD_DIR) \
|
||||||
$(LIBJPEG_DIR) \
|
$(LIBJPEG_DIR) \
|
||||||
$(LIBPNG_DIR) \
|
$(LIBPNG_DIR) \
|
||||||
$(ZLIB_DIR)
|
$(ZLIB_DIR) \
|
||||||
|
$(LOADPNG_DIR)
|
||||||
|
|
||||||
ASE_DEPS = $(ASE_OBJS) $(THIRD_PARTY_LIBS)
|
ASE_DEPS = $(ASE_OBJS) $(THIRD_PARTY_LIBS)
|
||||||
|
|
||||||
@ -181,6 +187,9 @@ $(OBJ_DIR)/png.%$(OBJ): %.c
|
|||||||
$(OBJ_DIR)/zlib.%$(OBJ): %.c
|
$(OBJ_DIR)/zlib.%$(OBJ): %.c
|
||||||
$(CC) $(CFLAGS) -Fo$@ -c $<
|
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||||
|
|
||||||
|
$(OBJ_DIR)/loadpng.%$(OBJ): %.c
|
||||||
|
$(CC) $(CFLAGS) -Fo$@ -c $<
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
# Application
|
# Application
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ static void select_all_command(JWidget widget)
|
|||||||
static void load_command(JWidget widget)
|
static void load_command(JWidget widget)
|
||||||
{
|
{
|
||||||
Palette *palette;
|
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()) {
|
if (!filename.empty()) {
|
||||||
palette = palette_load(filename.c_str());
|
palette = palette_load(filename.c_str());
|
||||||
if (!palette) {
|
if (!palette) {
|
||||||
@ -324,7 +324,7 @@ static void save_command(JWidget widget)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
again:
|
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 (!filename.empty()) {
|
||||||
if (exists(filename.c_str())) {
|
if (exists(filename.c_str())) {
|
||||||
ret = jalert("%s<<%s<<%s||%s",
|
ret = jalert("%s<<%s<<%s||%s",
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
|
|
||||||
#include "ase_exception.h"
|
#include "ase_exception.h"
|
||||||
#include "core/app.h"
|
#include "core/app.h"
|
||||||
|
#include "loadpng.h"
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
||||||
// Information for "ident".
|
// Information for "ident".
|
||||||
@ -40,6 +41,9 @@ public:
|
|||||||
allegro_init();
|
allegro_init();
|
||||||
set_uformat(U_ASCII);
|
set_uformat(U_ASCII);
|
||||||
install_timer();
|
install_timer();
|
||||||
|
|
||||||
|
// Register PNG as a supported bitmap type
|
||||||
|
register_bitmap_file_type("png", load_png, save_png);
|
||||||
}
|
}
|
||||||
~Allegro() {
|
~Allegro() {
|
||||||
remove_timer();
|
remove_timer();
|
||||||
|
@ -311,7 +311,8 @@ Palette* palette_load(const char *filename)
|
|||||||
|
|
||||||
ustrcpy(ext, get_extension(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, "bmp") == 0) ||
|
||||||
(ustricmp(ext, "tga") == 0) ||
|
(ustricmp(ext, "tga") == 0) ||
|
||||||
(ustricmp(ext, "lbm") == 0)) {
|
(ustricmp(ext, "lbm") == 0)) {
|
||||||
@ -340,7 +341,8 @@ bool palette_save(Palette* pal, const char *filename)
|
|||||||
|
|
||||||
ustrcpy(ext, get_extension(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, "bmp") == 0) ||
|
||||||
(ustricmp(ext, "tga") == 0)) {
|
(ustricmp(ext, "tga") == 0)) {
|
||||||
PALETTE rgbpal;
|
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