Updated libpng to version 16 and added sdl2_image for sdl2
This commit is contained in:
Submodule project/jni/application/commandergenius/commandergenius updated: 1bcbadd1ea...7c11c95336
+16
-38
@@ -1,58 +1,36 @@
|
||||
|
||||
Libpng 1.4.6beta06 - January 23, 2011
|
||||
Libpng 1.6.6 - September 16, 2013
|
||||
|
||||
This is not intended to be a public release. It will be replaced
|
||||
within a few weeks by a public version or by another test version.
|
||||
This is a public release of libpng, intended for use in production codes.
|
||||
|
||||
Files available for download:
|
||||
|
||||
Source files with LF line endings (for Unix/Linux) and with a
|
||||
"configure" script
|
||||
|
||||
1.4.6beta06.tar.xz (LZMA-compressed, recommended)
|
||||
1.4.6beta06.tar.gz
|
||||
1.4.6beta06.tar.bz2
|
||||
libpng-1.6.6.tar.xz (LZMA-compressed, recommended)
|
||||
libpng-1.6.6.tar.gz
|
||||
|
||||
Source files with CRLF line endings (for Windows), without the
|
||||
"configure" script
|
||||
|
||||
lp146b06.7z (LZMA-compressed, recommended)
|
||||
lp146b06.zip
|
||||
lpng166.7z (LZMA-compressed, recommended)
|
||||
lpng166.zip
|
||||
|
||||
Other information:
|
||||
|
||||
1.4.6beta06-README.txt
|
||||
1.4.6beta06-LICENSE.txt
|
||||
libpng-1.6.6-README.txt
|
||||
libpng-1.6.6-LICENSE.txt
|
||||
Gnupg/*.asc (PGP armored detached signatures)
|
||||
|
||||
Changes since the last public release (1.4.5):
|
||||
Changes since the last public release (1.6.5):
|
||||
|
||||
version 1.4.6beta01 [December 29, 2010]
|
||||
Fixed bug in background transformation handling in pngrtran.c (it was
|
||||
looking for the flag in png_ptr->transformations instead of in
|
||||
png_ptr->flags) (David Raymond).
|
||||
Removed two stray lines of code from arm/arm_init.c, again.
|
||||
|
||||
version 1.4.6beta02 [January 14, 2011]
|
||||
Fixed misspelled macros in contrib/pngminim (Cosmin)
|
||||
Updated CMakeLists.txt (Clifford Yapp)
|
||||
|
||||
version 1.4.6beta03 [January 14, 2011]
|
||||
Fixed some typecasts in png_debug statements (Cosmin).
|
||||
|
||||
version 1.4.6beta04 [January 22, 2011]
|
||||
Updated documentation of png_set|get_tRNS() (Thomas Klausner).
|
||||
Added png_const_structp and png_const_infop types, and used them in
|
||||
prototypes for most png_get_*() functions.
|
||||
In the manual, describe the png_get_IHDR() arguments in the correct order.
|
||||
|
||||
version 1.4.6beta05 [January 23, 2011]
|
||||
Updated the synopses in the manual to reflect recent changes.
|
||||
Fixed a typo in the *.def files and deleted entries that are now
|
||||
declared in pngpriv.h
|
||||
|
||||
version 1.4.6beta06 [January 23, 2011]
|
||||
|
||||
Send comments/corrections/commendations to glennrp at users.sourceforge.net
|
||||
or to png-mng-implement at lists.sf.net (subscription required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-implement).
|
||||
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
|
||||
(subscription required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
|
||||
to subscribe)
|
||||
or to glennrp at users.sourceforge.net
|
||||
|
||||
Glenn R-P
|
||||
|
||||
+2586
-708
File diff suppressed because it is too large
Load Diff
+62
-36
@@ -1,5 +1,5 @@
|
||||
|
||||
Installing libpng version 1.4.6beta06 - January 23, 2011
|
||||
Installing libpng
|
||||
|
||||
On Unix/Linux and similar systems, you can simply type
|
||||
|
||||
@@ -9,14 +9,20 @@ On Unix/Linux and similar systems, you can simply type
|
||||
|
||||
and ignore the rest of this document.
|
||||
|
||||
If configure does not work on your system and you have a reasonably
|
||||
up-to-date set of tools, running ./autogen.sh before running ./configure
|
||||
may fix the problem. You can also run the individual commands in
|
||||
autogen.sh with the --force option, if supported by your version of
|
||||
the tools. If you run 'libtoolize --force', though, this will replace
|
||||
the distributed, patched, version of ltmain.sh with an unpatched version
|
||||
and your shared library builds may fail to produce libraries with the
|
||||
correct version numbers.
|
||||
If configure does not work on your system, or if you have a need to
|
||||
change configure.ac or Makefile.am, and you have a reasonably
|
||||
up-to-date set of tools, running ./autogen.sh in a git clone before
|
||||
running ./configure may fix the problem. To be really sure that you
|
||||
aren't using any of the included pre-built scripts, you can do this:
|
||||
|
||||
./configure --enable-maintainer-mode
|
||||
make maintainer-clean
|
||||
./autogen.sh --maintainer --clean
|
||||
./autogen.sh --maintainer
|
||||
./configure [--prefix=/path] [other options]
|
||||
make
|
||||
make install
|
||||
make check
|
||||
|
||||
Instead, you can use one of the custom-built makefiles in the
|
||||
"scripts" directory
|
||||
@@ -35,19 +41,33 @@ is not already on your system. zlib can usually be found
|
||||
wherever you got libpng. zlib can be placed in another directory,
|
||||
at the same level as libpng.
|
||||
|
||||
If your system already has a preinstalled zlib you will still need
|
||||
to have access to the zlib.h and zconf.h include files that
|
||||
correspond to the version of zlib that's installed.
|
||||
|
||||
If you wish to test with a particular zlib that is not first in the
|
||||
standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS,
|
||||
and LD_LIBRARY_PATH in your environment before running "make test"
|
||||
or "make distcheck":
|
||||
|
||||
ZLIBLIB=/path/to/lib export ZLIBLIB
|
||||
ZLIBINC=/path/to/include export ZLIBINC
|
||||
CPPFLAGS="-I$ZLIBINC" export CPPFLAGS
|
||||
LDFLAGS="-L$ZLIBLIB" export LDFLAGS
|
||||
LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH
|
||||
|
||||
If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC
|
||||
in your environment and type "make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test".
|
||||
|
||||
If you want to use "cmake" (see www.cmake.org), type
|
||||
|
||||
cmake . -DCMAKE_INSTALL_PREFIX=/path
|
||||
make
|
||||
make install
|
||||
|
||||
If your system already has a preinstalled zlib you will still need
|
||||
to have access to the zlib.h and zconf.h include files that
|
||||
correspond to the version of zlib that's installed.
|
||||
|
||||
You can rename the directories that you downloaded (they
|
||||
might be called "libpng-1.4.6beta06" or "libpng14" and "zlib-1.2.3"
|
||||
or "zlib123") so that you have directories called "zlib" and "libpng".
|
||||
might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.7"
|
||||
or "zlib127") so that you have directories called "zlib" and "libpng".
|
||||
|
||||
Your directory structure should look like this:
|
||||
|
||||
@@ -60,24 +80,23 @@ Your directory structure should look like this:
|
||||
CMakeLists.txt => "cmake" script
|
||||
configuration files:
|
||||
configure.ac, configure, Makefile.am, Makefile.in,
|
||||
autogen.sh, config.guess, ltmain.sh, missing,
|
||||
aclocal.m4, config.h.in, config.sub,
|
||||
depcomp, install-sh, test-pngtest.sh
|
||||
autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in,
|
||||
libpng-config.in, aclocal.m4, config.h.in, config.sub,
|
||||
depcomp, install-sh, mkinstalldirs, test-pngtest.sh
|
||||
contrib
|
||||
gregbook
|
||||
libtests
|
||||
pngminim
|
||||
pngminus
|
||||
pngsuite
|
||||
visupng
|
||||
projects
|
||||
cbuilder5 (Borland)
|
||||
visualc6 (msvc)
|
||||
visualc71
|
||||
vstudio
|
||||
xcode
|
||||
scripts
|
||||
makefile.*
|
||||
*.def (module definition files)
|
||||
etc.
|
||||
pngtest.png
|
||||
etc.
|
||||
zlib
|
||||
@@ -108,7 +127,7 @@ scripts directory into this directory, for example
|
||||
Read the makefile to see if you need to change any source or
|
||||
target directories to match your preferences.
|
||||
|
||||
Then read pngconf.h to see if you want to make any configuration
|
||||
Then read pnglibconf.dfa to see if you want to make any configuration
|
||||
changes.
|
||||
|
||||
Then just run "make" which will create the libpng library in
|
||||
@@ -126,19 +145,26 @@ do that, run "make install" in the zlib directory first if necessary).
|
||||
Some also allow you to run "make test-installed" after you have
|
||||
run "make install".
|
||||
|
||||
If you encounter a compiler error message complaining about the
|
||||
lines
|
||||
|
||||
__png.h__ already includes setjmp.h;
|
||||
__dont__ include it again.;
|
||||
|
||||
this means you have compiled another module that includes setjmp.h,
|
||||
which is hazardous because the two modules might not include exactly
|
||||
the same setjmp.h. If you are sure that you know what you are doing
|
||||
and that they are exactly the same, then you can comment out or
|
||||
delete the two lines. Better yet, use the cexcept interface
|
||||
instead, as demonstrated in contrib/visupng of the libpng distribution.
|
||||
|
||||
Further information can be found in the README and libpng.txt
|
||||
Further information can be found in the README and libpng-manual.txt
|
||||
files, in the individual makefiles, in png.h, and the manual pages
|
||||
libpng.3 and png.5.
|
||||
|
||||
Using the ./configure script -- 16 December 2002.
|
||||
=================================================
|
||||
|
||||
The ./configure script should work compatibly with what scripts/makefile.*
|
||||
did, however there are some options you might need to add to configure
|
||||
explicitly, which previously was done semi-automatically (if you didn't edit
|
||||
scripts/makefile.* yourself, that is)
|
||||
|
||||
CFLAGS="-Wall -O -funroll-loops \
|
||||
-malign-loops=2 -malign-functions=2" ./configure --prefix=/usr/include \
|
||||
--with-pkgconfigdir=/usr/lib/pkgconfig --includedir=/usr/include
|
||||
|
||||
You can alternatively specify --includedir=/usr/include, /usr/local/include,
|
||||
/usr/include/libpng%NN%, or whatever.
|
||||
|
||||
If you find that the configure script is out-of-date or is not supporting
|
||||
your platform properly, try running autogen.sh to regenerate "configure",
|
||||
"Makefile.in", and the other configuration files. Then try configure again.
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@ this sentence.
|
||||
|
||||
This code is released under the libpng license.
|
||||
|
||||
libpng versions 1.2.6, August 15, 2004, through 1.4.6beta06, January 23, 2011, are
|
||||
Copyright (c) 2004, 2006-2010 Glenn Randers-Pehrson, and are
|
||||
libpng versions 1.2.6, August 15, 2004, through 1.6.6, September 16, 2013, are
|
||||
Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
|
||||
distributed according to the same disclaimer and license as libpng-1.2.5
|
||||
with the following individual added to the list of Contributing Authors
|
||||
|
||||
@@ -108,4 +108,4 @@ certification mark of the Open Source Initiative.
|
||||
|
||||
Glenn Randers-Pehrson
|
||||
glennrp at users.sourceforge.net
|
||||
January 23, 2011
|
||||
September 16, 2013
|
||||
|
||||
+34
-89
@@ -1,11 +1,11 @@
|
||||
README for libpng version 1.4.6beta06 - January 23, 2011 (shared library 14.0)
|
||||
README for libpng version 1.6.6 - September 16, 2013 (shared library 16.0)
|
||||
See the note about version numbers near the top of png.h
|
||||
|
||||
See INSTALL for instructions on how to install libpng.
|
||||
|
||||
Libpng comes in several distribution formats. Get libpng-*.tar.gz,
|
||||
libpng-*.tar.xz or libpng-*.tar.bz2 if you want UNIX-style line endings
|
||||
in the text files, or lpng*.zip if you want DOS-style line endings.
|
||||
Libpng comes in several distribution formats. Get libpng-*.tar.gz or
|
||||
libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
|
||||
or lpng*.7z or lpng*.zip if you want DOS-style line endings.
|
||||
|
||||
Version 0.89 was the first official release of libpng. Don't let the
|
||||
fact that it's the first release fool you. The libpng library has been in
|
||||
@@ -58,7 +58,7 @@ on the PNG-implement mailing list and not on material submitted
|
||||
privately to Guy, Andreas, or Glenn. They will forward any good
|
||||
suggestions to the list.
|
||||
|
||||
For a detailed description on using libpng, read libpng.txt. For
|
||||
For a detailed description on using libpng, read libpng-manual.txt. For
|
||||
examples of libpng in a program, see example.c and pngtest.c. For usage
|
||||
information and restrictions (what little they are) on libpng, see
|
||||
png.h. For a description on using zlib (the compression library used by
|
||||
@@ -77,17 +77,15 @@ compression library that is useful for more things than just PNG files.
|
||||
You can use zlib as a drop-in replacement for fread() and fwrite() if
|
||||
you are so inclined.
|
||||
|
||||
zlib should be available at the same place that libpng is, or at.
|
||||
ftp://ftp.info-zip.org/pub/infozip/zlib
|
||||
zlib should be available at the same place that libpng is, or at zlib.net.
|
||||
|
||||
You may also want a copy of the PNG specification. It is available
|
||||
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
|
||||
these at http://www.libpng.org/pub/png/documents/
|
||||
|
||||
This code is currently being archived at libpng.sf.net in the
|
||||
[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT)
|
||||
at GO GRAPHSUP. If you can't find it in any of those places,
|
||||
e-mail me, and I'll help you find it.
|
||||
[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it
|
||||
in any of those places, e-mail me, and I'll help you find it.
|
||||
|
||||
If you have any code changes, requests, problems, etc., please e-mail
|
||||
them to me. Also, I'd appreciate any make files or project files,
|
||||
@@ -105,7 +103,7 @@ based in a large way on Guy's and Andreas' earlier work), and the PNG
|
||||
development group.
|
||||
|
||||
Send comments/corrections/commendations to png-mng-implement at
|
||||
lists.sourceforge.net (subscription required; visit
|
||||
lists.sourceforge.net (subscription required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
|
||||
to subscribe) or to glennrp at users.sourceforge.net
|
||||
|
||||
@@ -114,19 +112,16 @@ given in previous versions of this document. He and Andreas will
|
||||
read mail addressed to the png-implement list, however.
|
||||
|
||||
Please do not send general questions about PNG. Send them to
|
||||
the (png-list at ccrc.wustl.edu, subscription required, write to
|
||||
majordomo at ccrc.wustl.edu with "subscribe png-list" in your message).
|
||||
On the other hand,
|
||||
please do not send libpng questions to that address, send them to me
|
||||
or to the png-implement list. I'll
|
||||
get them in the end anyway. If you have a question about something
|
||||
png-mng-misc at lists.sf.net (subscription required; visit
|
||||
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
|
||||
subscribe). If you have a question about something
|
||||
in the PNG specification that is related to using libpng, send it
|
||||
to me. Send me any questions that start with "I was using libpng,
|
||||
and ...". If in doubt, send questions to me. I'll bounce them
|
||||
to others, if necessary.
|
||||
|
||||
Please do not send suggestions on how to change PNG. We have
|
||||
been discussing PNG for nine years now, and it is official and
|
||||
been discussing PNG for eighteen years now, and it is official and
|
||||
finished. If you have suggestions for libpng, however, I'll
|
||||
gladly listen. Even if your suggestion is not used immediately,
|
||||
it may be used later.
|
||||
@@ -141,13 +136,17 @@ Files in this distribution:
|
||||
TODO => Things not implemented in the current library
|
||||
Y2KINFO => Statement of Y2K compliance
|
||||
example.c => Example code for using libpng functions
|
||||
libpng.3 => manual page for libpng (includes libpng.txt)
|
||||
libpng.txt => Description of libpng and its functions
|
||||
libpng.3 => manual page for libpng (includes libpng-manual.txt)
|
||||
libpng-manual.txt => Description of libpng and its functions
|
||||
libpngpf.3 => manual page for libpng's private functions
|
||||
png.5 => manual page for the PNG format
|
||||
png.c => Basic interface functions common to library
|
||||
png.h => Library function and interface declarations
|
||||
pngconf.h => System specific library configuration
|
||||
png.h => Library function and interface declarations (public)
|
||||
pngpriv.h => Library function and interface declarations (private)
|
||||
pngconf.h => System specific library configuration (public)
|
||||
pngstruct.h => png_struct declaration (private)
|
||||
pnginfo.h => png_info struct declaration (private)
|
||||
pngdebug.h => debugging macros (private)
|
||||
pngerror.c => Error/warning message I/O functions
|
||||
pngget.c => Functions for retrieving info from struct
|
||||
pngmem.c => Memory handling functions
|
||||
@@ -166,82 +165,28 @@ Files in this distribution:
|
||||
pngwrite.c => High-level write functions
|
||||
pngwtran.c => Write data transformations
|
||||
pngwutil.c => Write utility functions
|
||||
arm => Contains optimized code for the ARM platform
|
||||
contrib => Contributions
|
||||
examples => Example programs
|
||||
gregbook => source code for PNG reading and writing, from
|
||||
Greg Roelofs' "PNG: The Definitive Guide",
|
||||
O'Reilly, 1999
|
||||
msvctest => Builds and runs pngtest using a MSVC workspace
|
||||
pngminus => Simple pnm2png and png2pnm programs
|
||||
pngsuite => Test images
|
||||
libtests => Test programs
|
||||
pngminim => Minimal decoder, encoder, and progressive decoder
|
||||
programs demonstrating use of pngusr.dfa
|
||||
pngminus => Simple pnm2png and png2pnm programs
|
||||
pngsuite => Test images
|
||||
tools => Various tools
|
||||
visupng => Contains a MSVC workspace for VisualPng
|
||||
projects => Contains project files and workspaces for
|
||||
building a DLL
|
||||
c5builder => Contains a Borland workspace for building
|
||||
libpng and zlib
|
||||
visualc6 => Contains a Microsoft Visual C++ (MSVC)
|
||||
owatcom => Contains a WATCOM project for building libpng
|
||||
visualc71 => Contains a Microsoft Visual C++ (MSVC)
|
||||
workspace for building libpng and zlib
|
||||
vstudio => Contains a Microsoft Visual C++ (MSVC)
|
||||
workspace for building libpng and zlib
|
||||
scripts => Directory containing scripts for building libpng:
|
||||
descrip.mms => VMS makefile for MMS or MMK
|
||||
makefile.std => Generic UNIX makefile (cc, creates static
|
||||
libpng.a)
|
||||
makefile.elf => Linux/ELF makefile symbol versioning,
|
||||
(gcc, creates libpng14.so.14.1.4.6beta06)
|
||||
makefile.linux => Linux/ELF makefile
|
||||
(gcc, creates libpng14.so.14.1.4.6beta06)
|
||||
makefile.gcc => Generic makefile (gcc, creates static libpng.a)
|
||||
makefile.knr => Archaic UNIX Makefile that converts files with
|
||||
ansi2knr (Requires ansi2knr.c from
|
||||
ftp://ftp.cs.wisc.edu/ghost)
|
||||
makefile.aix => AIX makefile
|
||||
makefile.cygwin => Cygwin/gcc makefile
|
||||
makefile.darwin => Darwin makefile
|
||||
makefile.dec => DEC Alpha UNIX makefile
|
||||
makefile.freebsd => FreeBSD makefile
|
||||
makefile.hpgcc => HPUX makefile using gcc
|
||||
makefile.hpux => HPUX (10.20 and 11.00) makefile
|
||||
makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit
|
||||
makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 (static)
|
||||
makefile.intel => Intel C/C++ version 4.0 and later
|
||||
makefile.mingw => Mingw/gcc makefile
|
||||
makefile.netbsd => NetBSD/cc makefile, makes libpng.so.
|
||||
makefile.ne14bsd => NetBSD/cc makefile, makes
|
||||
libpng14.so
|
||||
makefile.openbsd => OpenBSD makefile
|
||||
makefile.sgi => Silicon Graphics IRIX (cc, creates static lib)
|
||||
makefile.sggcc => Silicon Graphics
|
||||
(gcc, creates libpng14.so.14.1.4.6beta06)
|
||||
makefile.sunos => Sun makefile
|
||||
makefile.solaris => Solaris 2.X makefile
|
||||
(gcc, creates libpng14.so.14.1.4.6beta06)
|
||||
makefile.so9 => Solaris 9 makefile
|
||||
(gcc, creates libpng14.so.14.1.4.6beta06)
|
||||
makefile.32sunu => Sun Ultra 32-bit makefile
|
||||
makefile.64sunu => Sun Ultra 64-bit makefile
|
||||
makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc
|
||||
makefile.mips => MIPS makefile
|
||||
makefile.acorn => Acorn makefile
|
||||
makefile.amiga => Amiga makefile
|
||||
smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC
|
||||
compiler (Requires SCOPTIONS, copied from
|
||||
scripts/SCOPTIONS.ppc)
|
||||
makefile.atari => Atari makefile
|
||||
makefile.beos => BEOS makefile for X86
|
||||
makefile.bor => Borland makefile (uses bcc)
|
||||
makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode)
|
||||
makefile.tc3 => Turbo C 3.0 makefile
|
||||
makefile.dj2 => DJGPP 2 makefile
|
||||
makefile.msc => Microsoft C makefile
|
||||
makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and
|
||||
later (does not use assembler code)
|
||||
makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def)
|
||||
png32ce.def => module definition for makefile.cegccg
|
||||
pngos2.def => OS/2 module definition file used by
|
||||
makefile.os2
|
||||
pngwin.def => module definition file used by
|
||||
makefile.cygwin and makefile.mingw
|
||||
makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model
|
||||
makevms.com => VMS build script
|
||||
SCOPTIONS.ppc => Used with smakefile.ppc
|
||||
(see scripts/README.txt for the list of scripts)
|
||||
|
||||
Good luck, and happy coding.
|
||||
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
TODO - list of things to do for libpng:
|
||||
|
||||
Final bug fixes.
|
||||
Improve API by hiding the png_struct and png_info structs.
|
||||
Finish work on the no-floating-point version (including gamma compensation)
|
||||
Better C++ wrapper/full C++ implementation?
|
||||
Fix problem with C++ and EXTERN "C".
|
||||
cHRM transformation.
|
||||
Improve setjmp/longjmp usage or remove it in favor of returning error codes.
|
||||
Remove setjmp/longjmp usage in favor of returning error codes.
|
||||
Add "grayscale->palette" transformation and "palette->grayscale" detection.
|
||||
Improved quantizing and dithering.
|
||||
Improved dithering.
|
||||
Multi-lingual error and warning message support.
|
||||
Complete sRGB transformation (presently it simply uses gamma=0.45455).
|
||||
Man pages for function calls.
|
||||
@@ -18,14 +16,12 @@ Better filter selection
|
||||
(counting huffman bits/precompression? filter inertia? filter costs?).
|
||||
Histogram creation.
|
||||
Text conversion between different code pages (Latin-1 -> Mac and DOS).
|
||||
Build gamma tables using fixed point (and do away with floating point entirely).
|
||||
Avoid building gamma tables whenever possible.
|
||||
Use greater precision when changing to linear gamma for compositing against
|
||||
background and doing rgb-to-gray transformation.
|
||||
Investigate pre-incremented loop counters and other loop constructions.
|
||||
Add interpolated method of handling interlacing.
|
||||
Provide for conditional compilation of 16-bit support (except for the
|
||||
initial stripping down to 8-bits when reading a 16-bit PNG datastream).
|
||||
Switch to the simpler zlib (zlib/libpng) license if legally possible.
|
||||
Extend pngvalid.c to validate more of the libpng transformations.
|
||||
|
||||
*/
|
||||
|
||||
+2001
-1408
File diff suppressed because it is too large
Load Diff
+493
-1416
File diff suppressed because it is too large
Load Diff
+3701
-317
File diff suppressed because it is too large
Load Diff
+693
-163
File diff suppressed because it is too large
Load Diff
+557
-311
File diff suppressed because it is too large
Load Diff
+181
-515
@@ -1,8 +1,8 @@
|
||||
|
||||
/* pngmem.c - stub functions for memory allocation
|
||||
*
|
||||
* Last changed in libpng 1.4.6 [January 23, 2011]
|
||||
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
||||
* Last changed in libpng 1.6.0 [February 14, 2013]
|
||||
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
@@ -17,421 +17,26 @@
|
||||
* identify the replacement functions.
|
||||
*/
|
||||
|
||||
#define PNG_NO_PEDANTIC_WARNINGS
|
||||
#include "png.h"
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
#include "pngpriv.h"
|
||||
|
||||
/* Borland DOS special memory handler */
|
||||
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
|
||||
/* If you change this, be sure to change the one in png.h also */
|
||||
|
||||
/* Allocate memory for a png_struct. The malloc and memset can be replaced
|
||||
by a single call to calloc() if this is thought to improve performance. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct(int type)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
return (png_create_struct_2(type, NULL, NULL));
|
||||
}
|
||||
|
||||
/* Alternate version of png_create_struct, for use with user-defined malloc. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
png_size_t size;
|
||||
png_voidp struct_ptr;
|
||||
|
||||
if (type == PNG_STRUCT_INFO)
|
||||
size = png_sizeof(png_info);
|
||||
else if (type == PNG_STRUCT_PNG)
|
||||
size = png_sizeof(png_struct);
|
||||
else
|
||||
return (png_get_copyright(NULL));
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (malloc_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size);
|
||||
}
|
||||
else
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
struct_ptr = (png_voidp)farmalloc(size);
|
||||
if (struct_ptr != NULL)
|
||||
png_memset(struct_ptr, 0, size);
|
||||
return (struct_ptr);
|
||||
}
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
/* Free a png_struct */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct(png_voidp struct_ptr)
|
||||
png_destroy_png_struct(png_structrp png_ptr)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
png_destroy_struct_2(struct_ptr, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
|
||||
png_voidp mem_ptr)
|
||||
{
|
||||
#endif
|
||||
if (struct_ptr != NULL)
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (free_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
(*(free_fn))(png_ptr, struct_ptr);
|
||||
return;
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
farfree (struct_ptr);
|
||||
}
|
||||
}
|
||||
/* png_free might call png_error and may certainly call
|
||||
* png_get_mem_ptr, so fake a temporary png_struct to support this.
|
||||
*/
|
||||
png_struct dummy_struct = *png_ptr;
|
||||
memset(png_ptr, 0, (sizeof *png_ptr));
|
||||
png_free(&dummy_struct, png_ptr);
|
||||
|
||||
/* Allocate memory. For reasonable files, size should never exceed
|
||||
* 64K. However, zlib may allocate more then 64K if you don't tell
|
||||
* it not to. See zconf.h and png.h for more information. zlib does
|
||||
* need to allocate exactly 64K, so whatever you call here must
|
||||
* have the ability to do that.
|
||||
*
|
||||
* Borland seems to have a problem in DOS mode for exactly 64K.
|
||||
* It gives you a segment with an offset of 8 (perhaps to store its
|
||||
* memory stuff). zlib doesn't like this at all, so we have to
|
||||
* detect and deal with it. This code should not be needed in
|
||||
* Windows or OS/2 modes, and only in 16 bit mode. This code has
|
||||
* been updated by Alexander Lehmann for version 0.89 to waste less
|
||||
* memory.
|
||||
*
|
||||
* Note that we can't use png_size_t for the "size" declaration,
|
||||
* since on some systems a png_size_t is a 16-bit quantity, and as a
|
||||
* result, we would be truncating potentially larger memory requests
|
||||
* (which should cause a fatal error) and introducing major problems.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_calloc(png_structp png_ptr, png_alloc_size_t size)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
ret = (png_malloc(png_ptr, size));
|
||||
if (ret != NULL)
|
||||
png_memset(ret,0,(png_size_t)size);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc(png_structp png_ptr, png_alloc_size_t size)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr->malloc_fn != NULL)
|
||||
ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
|
||||
else
|
||||
ret = (png_malloc_default(png_ptr, size));
|
||||
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of memory");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc_default(png_structp png_ptr, png_alloc_size_t size)
|
||||
{
|
||||
png_voidp ret;
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
{
|
||||
png_warning(png_ptr, "Cannot Allocate > 64K");
|
||||
ret = NULL;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
if (size != (size_t)size)
|
||||
ret = NULL;
|
||||
else if (size == (png_uint_32)65536L)
|
||||
{
|
||||
if (png_ptr->offset_table == NULL)
|
||||
{
|
||||
/* Try to see if we need to do any of this fancy stuff */
|
||||
ret = farmalloc(size);
|
||||
if (ret == NULL || ((png_size_t)ret & 0xffff))
|
||||
{
|
||||
int num_blocks;
|
||||
png_uint_32 total_size;
|
||||
png_bytep table;
|
||||
int i;
|
||||
png_byte huge * hptr;
|
||||
|
||||
if (ret != NULL)
|
||||
{
|
||||
farfree(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
if (png_ptr->zlib_window_bits > 14)
|
||||
num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
|
||||
else
|
||||
num_blocks = 1;
|
||||
if (png_ptr->zlib_mem_level >= 7)
|
||||
num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7));
|
||||
else
|
||||
num_blocks++;
|
||||
|
||||
total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
|
||||
|
||||
table = farmalloc(total_size);
|
||||
|
||||
if (table == NULL)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */
|
||||
else
|
||||
png_warning(png_ptr, "Out Of Memory");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((png_size_t)table & 0xfff0)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr,
|
||||
"Farmalloc didn't return normalized pointer");
|
||||
else
|
||||
png_warning(png_ptr,
|
||||
"Farmalloc didn't return normalized pointer");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
png_ptr->offset_table = table;
|
||||
png_ptr->offset_table_ptr = farmalloc(num_blocks *
|
||||
png_sizeof(png_bytep));
|
||||
|
||||
if (png_ptr->offset_table_ptr == NULL)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */
|
||||
else
|
||||
png_warning(png_ptr, "Out Of memory");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
hptr = (png_byte huge *)table;
|
||||
if ((png_size_t)hptr & 0xf)
|
||||
{
|
||||
hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
|
||||
hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
|
||||
}
|
||||
for (i = 0; i < num_blocks; i++)
|
||||
{
|
||||
png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
|
||||
hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
|
||||
}
|
||||
|
||||
png_ptr->offset_table_number = num_blocks;
|
||||
png_ptr->offset_table_count = 0;
|
||||
png_ptr->offset_table_count_free = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */
|
||||
else
|
||||
png_warning(png_ptr, "Out of Memory");
|
||||
#endif
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
|
||||
}
|
||||
else
|
||||
ret = farmalloc(size);
|
||||
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if (ret == NULL)
|
||||
{
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */
|
||||
else
|
||||
png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */
|
||||
}
|
||||
#endif
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* Free a pointer allocated by png_malloc(). In the default
|
||||
* configuration, png_ptr is not used, but is passed in case it
|
||||
* is needed. If ptr is NULL, return without taking any action.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_free(png_structp png_ptr, png_voidp ptr)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr->free_fn != NULL)
|
||||
{
|
||||
(*(png_ptr->free_fn))(png_ptr, ptr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
png_free_default(png_ptr, ptr);
|
||||
}
|
||||
|
||||
void PNGAPI
|
||||
png_free_default(png_structp png_ptr, png_voidp ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
if (png_ptr->offset_table != NULL)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < png_ptr->offset_table_count; i++)
|
||||
{
|
||||
if (ptr == png_ptr->offset_table_ptr[i])
|
||||
{
|
||||
ptr = NULL;
|
||||
png_ptr->offset_table_count_free++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
|
||||
{
|
||||
farfree(png_ptr->offset_table);
|
||||
farfree(png_ptr->offset_table_ptr);
|
||||
png_ptr->offset_table = NULL;
|
||||
png_ptr->offset_table_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ptr != NULL)
|
||||
{
|
||||
farfree(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* Not the Borland DOS special memory handler */
|
||||
|
||||
/* Allocate memory for a png_struct or a png_info. The malloc and
|
||||
memset can be replaced by a single call to calloc() if this is thought
|
||||
to improve performance noticably. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct(int type)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
return (png_create_struct_2(type, NULL, NULL));
|
||||
}
|
||||
|
||||
/* Allocate memory for a png_struct or a png_info. The malloc and
|
||||
memset can be replaced by a single call to calloc() if this is thought
|
||||
to improve performance noticably. */
|
||||
png_voidp /* PRIVATE */
|
||||
png_create_struct_2(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
png_size_t size;
|
||||
png_voidp struct_ptr;
|
||||
|
||||
if (type == PNG_STRUCT_INFO)
|
||||
size = png_sizeof(png_info);
|
||||
else if (type == PNG_STRUCT_PNG)
|
||||
size = png_sizeof(png_struct);
|
||||
else
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (malloc_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
struct_ptr = (*(malloc_fn))(png_ptr, size);
|
||||
if (struct_ptr != NULL)
|
||||
png_memset(struct_ptr, 0, size);
|
||||
return (struct_ptr);
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
struct_ptr = (png_voidp)farmalloc(size);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
struct_ptr = (png_voidp)halloc(size, 1);
|
||||
# else
|
||||
struct_ptr = (png_voidp)malloc(size);
|
||||
# endif
|
||||
#endif
|
||||
if (struct_ptr != NULL)
|
||||
png_memset(struct_ptr, 0, size);
|
||||
|
||||
return (struct_ptr);
|
||||
}
|
||||
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct(png_voidp struct_ptr)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
png_destroy_struct_2(struct_ptr, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Free memory allocated by a png_create_struct() call */
|
||||
void /* PRIVATE */
|
||||
png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
|
||||
png_voidp mem_ptr)
|
||||
{
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
if (struct_ptr != NULL)
|
||||
{
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (free_fn != NULL)
|
||||
{
|
||||
png_struct dummy_struct;
|
||||
png_structp png_ptr = &dummy_struct;
|
||||
png_ptr->mem_ptr=mem_ptr;
|
||||
(*(free_fn))(png_ptr, struct_ptr);
|
||||
return;
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
farfree(struct_ptr);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
hfree(struct_ptr);
|
||||
# else
|
||||
free(struct_ptr);
|
||||
# endif
|
||||
#endif
|
||||
# ifdef PNG_SETJMP_SUPPORTED
|
||||
/* We may have a jmp_buf left to deallocate. */
|
||||
png_free_jmpbuf(&dummy_struct);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -441,151 +46,211 @@ png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
|
||||
* need to allocate exactly 64K, so whatever you call here must
|
||||
* have the ability to do that.
|
||||
*/
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_calloc(png_structp png_ptr, png_alloc_size_t size)
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
ret = (png_malloc(png_ptr, size));
|
||||
ret = png_malloc(png_ptr, size);
|
||||
|
||||
if (ret != NULL)
|
||||
png_memset(ret,0,(png_size_t)size);
|
||||
return (ret);
|
||||
memset(ret, 0, size);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc(png_structp png_ptr, png_alloc_size_t size)
|
||||
/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
|
||||
* allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
|
||||
* Checking and error handling must happen outside this routine; it returns NULL
|
||||
* if the allocation cannot be done (for any reason.)
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
/* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
|
||||
* allocators have also been removed in 1.6.0, so any 16-bit system now has
|
||||
* to implement a user memory handler. This checks to be sure it isn't
|
||||
* called with big numbers.
|
||||
*/
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
if (png_ptr->malloc_fn != NULL)
|
||||
ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
|
||||
else
|
||||
ret = (png_malloc_default(png_ptr, size));
|
||||
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
return (ret);
|
||||
}
|
||||
|
||||
png_voidp PNGAPI
|
||||
png_malloc_default(png_structp png_ptr, png_alloc_size_t size)
|
||||
{
|
||||
png_voidp ret;
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
if (png_ptr == NULL || size == 0)
|
||||
return (NULL);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
PNG_UNUSED(png_ptr)
|
||||
#endif
|
||||
if (size > 0 && size <= PNG_SIZE_MAX
|
||||
# ifdef PNG_MAX_MALLOC_64K
|
||||
&& size <= 65536U
|
||||
# endif
|
||||
)
|
||||
{
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
|
||||
return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
|
||||
|
||||
else
|
||||
#endif
|
||||
return NULL;
|
||||
return malloc((size_t)size); /* checked for truncation above */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check for overflow */
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
if (size != (unsigned long)size)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = farmalloc(size);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
if (size != (unsigned long)size)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = halloc(size, 1);
|
||||
# else
|
||||
if (size != (size_t)size)
|
||||
ret = NULL;
|
||||
else
|
||||
ret = malloc((size_t)size);
|
||||
# endif
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef PNG_USER_MEM_SUPPORTED
|
||||
if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
#endif
|
||||
/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
|
||||
* that arises because of the checks in png_realloc_array that are repeated in
|
||||
* png_malloc_array.
|
||||
*/
|
||||
static png_voidp
|
||||
png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
|
||||
size_t element_size)
|
||||
{
|
||||
png_alloc_size_t req = nelements; /* known to be > 0 */
|
||||
|
||||
return (ret);
|
||||
if (req <= PNG_SIZE_MAX/element_size)
|
||||
return png_malloc_base(png_ptr, req * element_size);
|
||||
|
||||
/* The failure case when the request is too large */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_malloc_array,(png_const_structrp png_ptr, int nelements,
|
||||
size_t element_size),PNG_ALLOCATED)
|
||||
{
|
||||
if (nelements <= 0 || element_size == 0)
|
||||
png_error(png_ptr, "internal error: array alloc");
|
||||
|
||||
return png_malloc_array_checked(png_ptr, nelements, element_size);
|
||||
}
|
||||
|
||||
PNG_FUNCTION(png_voidp /* PRIVATE */,
|
||||
png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
|
||||
int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
|
||||
{
|
||||
/* These are internal errors: */
|
||||
if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
|
||||
(old_array == NULL && old_elements > 0))
|
||||
png_error(png_ptr, "internal error: array realloc");
|
||||
|
||||
/* Check for overflow on the elements count (so the caller does not have to
|
||||
* check.)
|
||||
*/
|
||||
if (add_elements <= INT_MAX - old_elements)
|
||||
{
|
||||
png_voidp new_array = png_malloc_array_checked(png_ptr,
|
||||
old_elements+add_elements, element_size);
|
||||
|
||||
if (new_array != NULL)
|
||||
{
|
||||
/* Because png_malloc_array worked the size calculations below cannot
|
||||
* overflow.
|
||||
*/
|
||||
if (old_elements > 0)
|
||||
memcpy(new_array, old_array, element_size*(unsigned)old_elements);
|
||||
|
||||
memset((char*)new_array + element_size*(unsigned)old_elements, 0,
|
||||
element_size*(unsigned)add_elements);
|
||||
|
||||
return new_array;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL; /* error */
|
||||
}
|
||||
|
||||
/* Various functions that have different error handling are derived from this.
|
||||
* png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
|
||||
* function png_malloc_default is also provided.
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
ret = png_malloc_base(png_ptr, size);
|
||||
|
||||
if (ret == NULL)
|
||||
png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED PNG_DEPRECATED)
|
||||
{
|
||||
png_voidp ret;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Passing 'NULL' here bypasses the application provided memory handler. */
|
||||
ret = png_malloc_base(NULL/*use malloc*/, size);
|
||||
|
||||
if (ret == NULL)
|
||||
png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
|
||||
* function will issue a png_warning and return NULL instead of issuing a
|
||||
* png_error, if it fails to allocate the requested memory.
|
||||
*/
|
||||
PNG_FUNCTION(png_voidp,PNGAPI
|
||||
png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size),
|
||||
PNG_ALLOCATED)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
png_voidp ret = png_malloc_base(png_ptr, size);
|
||||
|
||||
if (ret != NULL)
|
||||
return ret;
|
||||
|
||||
png_warning(png_ptr, "Out of memory");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
|
||||
* without taking any action.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_free(png_structp png_ptr, png_voidp ptr)
|
||||
png_free(png_const_structrp png_ptr, png_voidp ptr)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
if (png_ptr->free_fn != NULL)
|
||||
{
|
||||
(*(png_ptr->free_fn))(png_ptr, ptr);
|
||||
return;
|
||||
}
|
||||
png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr);
|
||||
|
||||
else
|
||||
png_free_default(png_ptr, ptr);
|
||||
}
|
||||
void PNGAPI
|
||||
png_free_default(png_structp png_ptr, png_voidp ptr)
|
||||
|
||||
PNG_FUNCTION(void,PNGAPI
|
||||
png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
|
||||
{
|
||||
if (png_ptr == NULL || ptr == NULL)
|
||||
return;
|
||||
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
|
||||
#if defined(__TURBOC__) && !defined(__FLAT__)
|
||||
farfree(ptr);
|
||||
#else
|
||||
# if defined(_MSC_VER) && defined(MAXSEG_64K)
|
||||
hfree(ptr);
|
||||
# else
|
||||
free(ptr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* Not Borland DOS special memory handler */
|
||||
|
||||
/* This function was added at libpng version 1.2.3. The png_malloc_warn()
|
||||
* function will set up png_malloc() to issue a png_warning and return NULL
|
||||
* instead of issuing a png_error, if it fails to allocate the requested
|
||||
* memory.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_malloc_warn(png_structp png_ptr, png_alloc_size_t size)
|
||||
{
|
||||
png_voidp ptr;
|
||||
png_uint_32 save_flags;
|
||||
if (png_ptr == NULL)
|
||||
return (NULL);
|
||||
|
||||
save_flags = png_ptr->flags;
|
||||
png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
|
||||
ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
|
||||
png_ptr->flags=save_flags;
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
||||
#ifdef PNG_USER_MEM_SUPPORTED
|
||||
/* This function is called when the application wants to use another method
|
||||
* of allocating and freeing memory.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
|
||||
png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
|
||||
malloc_fn, png_free_ptr free_fn)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
@@ -601,11 +266,12 @@ png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
|
||||
* pointer before png_write_destroy and png_read_destroy are called.
|
||||
*/
|
||||
png_voidp PNGAPI
|
||||
png_get_mem_ptr(png_const_structp png_ptr)
|
||||
png_get_mem_ptr(png_const_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return (NULL);
|
||||
return ((png_voidp)png_ptr->mem_ptr);
|
||||
return NULL;
|
||||
|
||||
return png_ptr->mem_ptr;
|
||||
}
|
||||
#endif /* PNG_USER_MEM_SUPPORTED */
|
||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||
|
||||
+305
-781
File diff suppressed because it is too large
Load Diff
+3307
-653
File diff suppressed because it is too large
Load Diff
+17
-62
@@ -1,8 +1,8 @@
|
||||
|
||||
/* pngrio.c - functions for data input
|
||||
*
|
||||
* Last changed in libpng 1.4.6 [January 14, 2011]
|
||||
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
||||
* Last changed in libpng 1.6.0 [February 14, 2013]
|
||||
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
@@ -18,11 +18,10 @@
|
||||
* libpng use it at run time with png_set_read_fn(...).
|
||||
*/
|
||||
|
||||
#define PNG_NO_PEDANTIC_WARNINGS
|
||||
#include "png.h"
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
#include "pngpriv.h"
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
|
||||
/* Read the data from whatever input you are using. The default routine
|
||||
* reads from a file pointer. Note that this routine sometimes gets called
|
||||
* with very small lengths, so you should implement some kind of simple
|
||||
@@ -30,12 +29,13 @@
|
||||
* to read more then 64K on a 16 bit machine.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_debug1(4, "reading %d bytes", (int)length);
|
||||
|
||||
if (png_ptr->read_data_fn != NULL)
|
||||
(*(png_ptr->read_data_fn))(png_ptr, data, length);
|
||||
|
||||
else
|
||||
png_error(png_ptr, "Call to NULL read function");
|
||||
}
|
||||
@@ -46,80 +46,34 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
* read_data function and use it at run time with png_set_read_fn(), rather
|
||||
* than changing the library.
|
||||
*/
|
||||
#ifndef USE_FAR_KEYWORD
|
||||
void PNGAPI
|
||||
void PNGCBAPI
|
||||
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_size_t check;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
|
||||
* instead of an int, which is what fread() actually returns.
|
||||
*/
|
||||
check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr);
|
||||
check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Read Error");
|
||||
}
|
||||
#else
|
||||
/* This is the model-independent version. Since the standard I/O library
|
||||
can't handle far buffers in the medium and small models, we have to copy
|
||||
the data.
|
||||
*/
|
||||
|
||||
#define NEAR_BUF_SIZE 1024
|
||||
#define MIN(a,b) (a <= b ? a : b)
|
||||
|
||||
static void PNGAPI
|
||||
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_size_t check;
|
||||
png_byte *n_data;
|
||||
png_FILE_p io_ptr;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
/* Check if data really is near. If so, use usual code. */
|
||||
n_data = (png_byte *)CVT_PTR_NOCHECK(data);
|
||||
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
|
||||
if ((png_bytep)n_data == data)
|
||||
{
|
||||
check = fread(n_data, 1, length, io_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
png_byte buf[NEAR_BUF_SIZE];
|
||||
png_size_t read, remaining, err;
|
||||
check = 0;
|
||||
remaining = length;
|
||||
do
|
||||
{
|
||||
read = MIN(NEAR_BUF_SIZE, remaining);
|
||||
err = fread(buf, 1, read, io_ptr);
|
||||
png_memcpy(data, buf, read); /* copy far buffer to near buffer */
|
||||
if (err != read)
|
||||
break;
|
||||
else
|
||||
check += err;
|
||||
data += read;
|
||||
remaining -= read;
|
||||
}
|
||||
while (remaining != 0);
|
||||
}
|
||||
if ((png_uint_32)check != (png_uint_32)length)
|
||||
png_error(png_ptr, "read Error");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This function allows the application to supply a new input function
|
||||
* for libpng if standard C streams aren't being used.
|
||||
*
|
||||
* This function takes as its arguments:
|
||||
*
|
||||
* png_ptr - pointer to a png input data structure
|
||||
*
|
||||
* io_ptr - pointer to user supplied structure containing info about
|
||||
* the input functions. May be NULL.
|
||||
*
|
||||
* read_data_fn - pointer to a new input function that takes as its
|
||||
* arguments a pointer to a png_struct, a pointer to
|
||||
* a location where input data can be stored, and a 32-bit
|
||||
@@ -130,16 +84,18 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
* be used.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
|
||||
png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr read_data_fn)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
if (read_data_fn != NULL)
|
||||
png_ptr->read_data_fn = read_data_fn;
|
||||
|
||||
else
|
||||
png_ptr->read_data_fn = png_default_read_data;
|
||||
#else
|
||||
@@ -151,9 +107,8 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
|
||||
{
|
||||
png_ptr->write_data_fn = NULL;
|
||||
png_warning(png_ptr,
|
||||
"It's an error to set both read_data_fn and write_data_fn in the ");
|
||||
png_warning(png_ptr,
|
||||
"same structure. Resetting write_data_fn to NULL");
|
||||
"Can't set both read_data_fn and write_data_fn in the"
|
||||
" same structure");
|
||||
}
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
|
||||
+2317
-1441
File diff suppressed because it is too large
Load Diff
+2738
-1690
File diff suppressed because it is too large
Load Diff
+961
-538
File diff suppressed because it is too large
Load Diff
+658
-377
File diff suppressed because it is too large
Load Diff
+375
-211
@@ -1,8 +1,8 @@
|
||||
|
||||
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
|
||||
*
|
||||
* Last changed in libpng 1.4.6 [January 23, 2011]
|
||||
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
|
||||
* Last changed in libpng 1.6.2 [April 25, 2013]
|
||||
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
@@ -11,20 +11,20 @@
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#define PNG_NO_PEDANTIC_WARNINGS
|
||||
#include "png.h"
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
#include "pngpriv.h"
|
||||
|
||||
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
|
||||
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
|
||||
/* Turn on BGR-to-RGB mapping */
|
||||
void PNGAPI
|
||||
png_set_bgr(png_structp png_ptr)
|
||||
png_set_bgr(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_bgr");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->transformations |= PNG_BGR;
|
||||
}
|
||||
#endif
|
||||
@@ -32,12 +32,13 @@ png_set_bgr(png_structp png_ptr)
|
||||
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
|
||||
/* Turn on 16 bit byte swapping */
|
||||
void PNGAPI
|
||||
png_set_swap(png_structp png_ptr)
|
||||
png_set_swap(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_swap");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
if (png_ptr->bit_depth == 16)
|
||||
png_ptr->transformations |= PNG_SWAP_BYTES;
|
||||
}
|
||||
@@ -46,12 +47,13 @@ png_set_swap(png_structp png_ptr)
|
||||
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
|
||||
/* Turn on pixel packing */
|
||||
void PNGAPI
|
||||
png_set_packing(png_structp png_ptr)
|
||||
png_set_packing(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_packing");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
if (png_ptr->bit_depth < 8)
|
||||
{
|
||||
png_ptr->transformations |= PNG_PACK;
|
||||
@@ -63,12 +65,13 @@ png_set_packing(png_structp png_ptr)
|
||||
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
/* Turn on packed pixel swapping */
|
||||
void PNGAPI
|
||||
png_set_packswap(png_structp png_ptr)
|
||||
png_set_packswap(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_packswap");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
if (png_ptr->bit_depth < 8)
|
||||
png_ptr->transformations |= PNG_PACKSWAP;
|
||||
}
|
||||
@@ -76,12 +79,13 @@ png_set_packswap(png_structp png_ptr)
|
||||
|
||||
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_shift(png_structp png_ptr, png_color_8p true_bits)
|
||||
png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
|
||||
{
|
||||
png_debug(1, "in png_set_shift");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->transformations |= PNG_SHIFT;
|
||||
png_ptr->shift = *true_bits;
|
||||
}
|
||||
@@ -90,7 +94,7 @@ png_set_shift(png_structp png_ptr, png_color_8p true_bits)
|
||||
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
|
||||
defined(PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
int PNGAPI
|
||||
png_set_interlace_handling(png_structp png_ptr)
|
||||
png_set_interlace_handling(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_interlace handling");
|
||||
|
||||
@@ -111,48 +115,101 @@ png_set_interlace_handling(png_structp png_ptr)
|
||||
* that don't like bytes as parameters.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
{
|
||||
png_debug(1, "in png_set_filler");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
/* In libpng 1.6 it is possible to determine whether this is a read or write
|
||||
* operation and therefore to do more checking here for a valid call.
|
||||
*/
|
||||
if (png_ptr->mode & PNG_IS_READ_STRUCT)
|
||||
{
|
||||
# ifdef PNG_READ_FILLER_SUPPORTED
|
||||
/* On read png_set_filler is always valid, regardless of the base PNG
|
||||
* format, because other transformations can give a format where the
|
||||
* filler code can execute (basically an 8 or 16-bit component RGB or G
|
||||
* format.)
|
||||
*
|
||||
* NOTE: usr_channels is not used by the read code! (This has led to
|
||||
* confusion in the past.) The filler is only used in the read code.
|
||||
*/
|
||||
png_ptr->filler = (png_uint_16)filler;
|
||||
# else
|
||||
png_app_error(png_ptr, "png_set_filler not supported on read");
|
||||
PNG_UNUSED(filler) /* not used in the write case */
|
||||
return;
|
||||
# endif
|
||||
}
|
||||
|
||||
else /* write */
|
||||
{
|
||||
# ifdef PNG_WRITE_FILLER_SUPPORTED
|
||||
/* On write the usr_channels parameter must be set correctly at the
|
||||
* start to record the number of channels in the app-supplied data.
|
||||
*/
|
||||
switch (png_ptr->color_type)
|
||||
{
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
png_ptr->usr_channels = 4;
|
||||
break;
|
||||
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
if (png_ptr->bit_depth >= 8)
|
||||
{
|
||||
png_ptr->usr_channels = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* There simply isn't any code in libpng to strip out bits
|
||||
* from bytes when the components are less than a byte in
|
||||
* size!
|
||||
*/
|
||||
png_app_error(png_ptr,
|
||||
"png_set_filler is invalid for low bit depth gray output");
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
png_app_error(png_ptr,
|
||||
"png_set_filler: inappropriate color type");
|
||||
return;
|
||||
}
|
||||
# else
|
||||
png_app_error(png_ptr, "png_set_filler not supported on write");
|
||||
return;
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Here on success - libpng supports the operation, set the transformation
|
||||
* and the flag to say where the filler channel is.
|
||||
*/
|
||||
png_ptr->transformations |= PNG_FILLER;
|
||||
png_ptr->filler = (png_uint_16)filler;
|
||||
|
||||
if (filler_loc == PNG_FILLER_AFTER)
|
||||
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
|
||||
|
||||
else
|
||||
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
|
||||
|
||||
/* This should probably go in the "do_read_filler" routine.
|
||||
* I attempted to do that in libpng-1.0.1a but that caused problems
|
||||
* so I restored it in libpng-1.0.2a
|
||||
*/
|
||||
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
|
||||
{
|
||||
png_ptr->usr_channels = 4;
|
||||
}
|
||||
|
||||
/* Also I added this in libpng-1.0.2a (what happens when we expand
|
||||
* a less-than-8-bit grayscale to GA? */
|
||||
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
|
||||
{
|
||||
png_ptr->usr_channels = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Added to libpng-1.2.7 */
|
||||
void PNGAPI
|
||||
png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
{
|
||||
png_debug(1, "in png_set_add_alpha");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_set_filler(png_ptr, filler, filler_loc);
|
||||
png_ptr->transformations |= PNG_ADD_ALPHA;
|
||||
/* The above may fail to do anything. */
|
||||
if (png_ptr->transformations & PNG_FILLER)
|
||||
png_ptr->transformations |= PNG_ADD_ALPHA;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -160,12 +217,13 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
|
||||
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
|
||||
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_swap_alpha(png_structp png_ptr)
|
||||
png_set_swap_alpha(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_swap_alpha");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->transformations |= PNG_SWAP_ALPHA;
|
||||
}
|
||||
#endif
|
||||
@@ -173,24 +231,26 @@ png_set_swap_alpha(png_structp png_ptr)
|
||||
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
|
||||
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_invert_alpha(png_structp png_ptr)
|
||||
png_set_invert_alpha(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_invert_alpha");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->transformations |= PNG_INVERT_ALPHA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
|
||||
void PNGAPI
|
||||
png_set_invert_mono(png_structp png_ptr)
|
||||
png_set_invert_mono(png_structrp png_ptr)
|
||||
{
|
||||
png_debug(1, "in png_set_invert_mono");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
png_ptr->transformations |= PNG_INVERT_MONO;
|
||||
}
|
||||
|
||||
@@ -206,8 +266,8 @@ png_do_invert(png_row_infop row_info, png_bytep row)
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = row_info->rowbytes;
|
||||
png_size_t i;
|
||||
png_size_t istop = row_info->rowbytes;
|
||||
|
||||
for (i = 0; i < istop; i++)
|
||||
{
|
||||
@@ -215,36 +275,41 @@ png_do_invert(png_row_infop row_info, png_bytep row)
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
|
||||
row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = row_info->rowbytes;
|
||||
png_size_t i;
|
||||
png_size_t istop = row_info->rowbytes;
|
||||
|
||||
for (i = 0; i < istop; i+=2)
|
||||
for (i = 0; i < istop; i += 2)
|
||||
{
|
||||
*rp = (png_byte)(~(*rp));
|
||||
rp+=2;
|
||||
rp += 2;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PNG_16BIT_SUPPORTED
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
|
||||
row_info->bit_depth == 16)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
png_uint_32 istop = row_info->rowbytes;
|
||||
png_size_t i;
|
||||
png_size_t istop = row_info->rowbytes;
|
||||
|
||||
for (i = 0; i < istop; i+=4)
|
||||
for (i = 0; i < istop; i += 4)
|
||||
{
|
||||
*rp = (png_byte)(~(*rp));
|
||||
*(rp+1) = (png_byte)(~(*(rp+1)));
|
||||
rp+=4;
|
||||
*(rp + 1) = (png_byte)(~(*(rp + 1)));
|
||||
rp += 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_16BIT_SUPPORTED
|
||||
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
|
||||
/* Swaps byte order on 16 bit depth images */
|
||||
void /* PRIVATE */
|
||||
@@ -252,8 +317,7 @@ png_do_swap(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_swap");
|
||||
|
||||
if (
|
||||
row_info->bit_depth == 16)
|
||||
if (row_info->bit_depth == 16)
|
||||
{
|
||||
png_bytep rp = row;
|
||||
png_uint_32 i;
|
||||
@@ -268,6 +332,7 @@ png_do_swap(png_row_infop row_info, png_bytep row)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
|
||||
static PNG_CONST png_byte onebppswaptable[256] = {
|
||||
@@ -381,19 +446,22 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_packswap");
|
||||
|
||||
if (
|
||||
row_info->bit_depth < 8)
|
||||
if (row_info->bit_depth < 8)
|
||||
{
|
||||
png_bytep rp, end, table;
|
||||
png_bytep rp;
|
||||
png_const_bytep end, table;
|
||||
|
||||
end = row + row_info->rowbytes;
|
||||
|
||||
if (row_info->bit_depth == 1)
|
||||
table = (png_bytep)onebppswaptable;
|
||||
table = onebppswaptable;
|
||||
|
||||
else if (row_info->bit_depth == 2)
|
||||
table = (png_bytep)twobppswaptable;
|
||||
table = twobppswaptable;
|
||||
|
||||
else if (row_info->bit_depth == 4)
|
||||
table = (png_bytep)fourbppswaptable;
|
||||
table = fourbppswaptable;
|
||||
|
||||
else
|
||||
return;
|
||||
|
||||
@@ -405,158 +473,119 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
|
||||
|
||||
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
|
||||
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
|
||||
/* Remove filler or alpha byte(s) */
|
||||
/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
|
||||
* somewhat weird combination of flags to determine what to do. All the calls
|
||||
* to png_do_strip_filler are changed in 1.5.2 to call this instead with the
|
||||
* correct arguments.
|
||||
*
|
||||
* The routine isn't general - the channel must be the channel at the start or
|
||||
* end (not in the middle) of each pixel.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
|
||||
png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
|
||||
{
|
||||
png_debug(1, "in png_do_strip_filler");
|
||||
png_bytep sp = row; /* source pointer */
|
||||
png_bytep dp = row; /* destination pointer */
|
||||
png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
|
||||
|
||||
/* At the start sp will point to the first byte to copy and dp to where
|
||||
* it is copied to. ep always points just beyond the end of the row, so
|
||||
* the loop simply copies (channels-1) channels until sp reaches ep.
|
||||
*
|
||||
* at_start: 0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
|
||||
* nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
|
||||
*/
|
||||
|
||||
/* GA, GX, XG cases */
|
||||
if (row_info->channels == 2)
|
||||
{
|
||||
png_bytep sp=row;
|
||||
png_bytep dp=row;
|
||||
png_uint_32 row_width=row_info->width;
|
||||
png_uint_32 i;
|
||||
|
||||
if ((row_info->color_type == PNG_COLOR_TYPE_RGB ||
|
||||
(row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
|
||||
(flags & PNG_FLAG_STRIP_ALPHA))) &&
|
||||
row_info->channels == 4)
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This converts from RGBX or RGBA to RGB */
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
dp+=3; sp+=4;
|
||||
for (i = 1; i < row_width; i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
/* This converts from XRGB or ARGB to RGB */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 24;
|
||||
row_info->rowbytes = row_width * 3;
|
||||
}
|
||||
else /* if (row_info->bit_depth == 16) */
|
||||
{
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
/* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
|
||||
sp += 8; dp += 6;
|
||||
for (i = 1; i < row_width; i++)
|
||||
{
|
||||
/* This could be (although png_memcpy is probably slower):
|
||||
png_memcpy(dp, sp, 6);
|
||||
sp += 8;
|
||||
dp += 6;
|
||||
*/
|
||||
if (at_start) /* Skip initial filler */
|
||||
++sp;
|
||||
else /* Skip initial channel and, for sp, the filler */
|
||||
sp += 2, ++dp;
|
||||
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
/* This could be (although png_memcpy is probably slower):
|
||||
png_memcpy(dp, sp, 6);
|
||||
sp += 8;
|
||||
dp += 6;
|
||||
*/
|
||||
/* For a 1 pixel wide image there is nothing to do */
|
||||
while (sp < ep)
|
||||
*dp++ = *sp, sp += 2;
|
||||
|
||||
sp+=2;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 48;
|
||||
row_info->rowbytes = row_width * 6;
|
||||
}
|
||||
row_info->channels = 3;
|
||||
row_info->pixel_depth = 8;
|
||||
}
|
||||
else if ((row_info->color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
(row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
|
||||
(flags & PNG_FLAG_STRIP_ALPHA))) &&
|
||||
row_info->channels == 2)
|
||||
|
||||
else if (row_info->bit_depth == 16)
|
||||
{
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This converts from GX or GA to G */
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
/* This converts from XG or AG to G */
|
||||
else
|
||||
{
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 8;
|
||||
row_info->rowbytes = row_width;
|
||||
}
|
||||
else /* if (row_info->bit_depth == 16) */
|
||||
{
|
||||
if (flags & PNG_FLAG_FILLER_AFTER)
|
||||
{
|
||||
/* This converts from GGXX or GGAA to GG */
|
||||
sp += 4; dp += 2;
|
||||
for (i = 1; i < row_width; i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This converts from XXGG or AAGG to GG */
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
sp += 2;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
}
|
||||
row_info->pixel_depth = 16;
|
||||
row_info->rowbytes = row_width * 2;
|
||||
}
|
||||
row_info->channels = 1;
|
||||
if (at_start) /* Skip initial filler */
|
||||
sp += 2;
|
||||
else /* Skip initial channel and, for sp, the filler */
|
||||
sp += 4, dp += 2;
|
||||
|
||||
while (sp < ep)
|
||||
*dp++ = *sp++, *dp++ = *sp, sp += 3;
|
||||
|
||||
row_info->pixel_depth = 16;
|
||||
}
|
||||
if (flags & PNG_FLAG_STRIP_ALPHA)
|
||||
row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
|
||||
|
||||
else
|
||||
return; /* bad bit depth */
|
||||
|
||||
row_info->channels = 1;
|
||||
|
||||
/* Finally fix the color type if it records an alpha channel */
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
row_info->color_type = PNG_COLOR_TYPE_GRAY;
|
||||
}
|
||||
|
||||
/* RGBA, RGBX, XRGB cases */
|
||||
else if (row_info->channels == 4)
|
||||
{
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
if (at_start) /* Skip initial filler */
|
||||
++sp;
|
||||
else /* Skip initial channels and, for sp, the filler */
|
||||
sp += 4, dp += 3;
|
||||
|
||||
/* Note that the loop adds 3 to dp and 4 to sp each time. */
|
||||
while (sp < ep)
|
||||
*dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2;
|
||||
|
||||
row_info->pixel_depth = 24;
|
||||
}
|
||||
|
||||
else if (row_info->bit_depth == 16)
|
||||
{
|
||||
if (at_start) /* Skip initial filler */
|
||||
sp += 2;
|
||||
else /* Skip initial channels and, for sp, the filler */
|
||||
sp += 8, dp += 6;
|
||||
|
||||
while (sp < ep)
|
||||
{
|
||||
/* Copy 6 bytes, skip 2 */
|
||||
*dp++ = *sp++, *dp++ = *sp++;
|
||||
*dp++ = *sp++, *dp++ = *sp++;
|
||||
*dp++ = *sp++, *dp++ = *sp, sp += 3;
|
||||
}
|
||||
|
||||
row_info->pixel_depth = 48;
|
||||
}
|
||||
|
||||
else
|
||||
return; /* bad bit depth */
|
||||
|
||||
row_info->channels = 3;
|
||||
|
||||
/* Finally fix the color type if it records an alpha channel */
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
row_info->color_type = PNG_COLOR_TYPE_RGB;
|
||||
}
|
||||
|
||||
else
|
||||
return; /* The filler channel has gone already */
|
||||
|
||||
/* Fix the rowbytes value. */
|
||||
row_info->rowbytes = dp-row;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -567,8 +596,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_bgr");
|
||||
|
||||
if (
|
||||
(row_info->color_type & PNG_COLOR_MASK_COLOR))
|
||||
if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
|
||||
{
|
||||
png_uint_32 row_width = row_info->width;
|
||||
if (row_info->bit_depth == 8)
|
||||
@@ -585,6 +613,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
|
||||
*(rp + 2) = save;
|
||||
}
|
||||
}
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
png_bytep rp;
|
||||
@@ -598,6 +627,8 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PNG_16BIT_SUPPORTED
|
||||
else if (row_info->bit_depth == 16)
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
@@ -615,6 +646,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
|
||||
*(rp + 5) = save;
|
||||
}
|
||||
}
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
png_bytep rp;
|
||||
@@ -631,47 +663,179 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
|
||||
|
||||
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
|
||||
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
|
||||
/* Added at libpng-1.5.10 */
|
||||
void /* PRIVATE */
|
||||
png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
|
||||
png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
|
||||
{
|
||||
/* Calculations moved outside switch in an attempt to stop different
|
||||
* compiler warnings. 'padding' is in *bits* within the last byte, it is
|
||||
* an 'int' because pixel_depth becomes an 'int' in the expression below,
|
||||
* and this calculation is used because it avoids warnings that other
|
||||
* forms produced on either GCC or MSVC.
|
||||
*/
|
||||
int padding = (-row_info->pixel_depth * row_info->width) & 7;
|
||||
png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
|
||||
|
||||
switch (row_info->bit_depth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
/* in this case, all bytes must be 0 so we don't need
|
||||
* to unpack the pixels except for the rightmost one.
|
||||
*/
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
if (*rp >> padding != 0)
|
||||
png_ptr->num_palette_max = 1;
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
int i = ((*rp >> padding) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 2) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 4) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 6) & 0x03);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
int i = ((*rp >> padding) & 0x0f);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
i = (((*rp >> padding) >> 4) & 0x0f);
|
||||
|
||||
if (i > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = i;
|
||||
|
||||
padding = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
for (; rp > png_ptr->row_buf; rp--)
|
||||
{
|
||||
if (*rp > png_ptr->num_palette_max)
|
||||
png_ptr->num_palette_max = (int) *rp;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
|
||||
|
||||
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
|
||||
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
|
||||
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
void PNGAPI
|
||||
png_set_user_transform_info(png_structp png_ptr, png_voidp
|
||||
png_set_user_transform_info(png_structrp png_ptr, png_voidp
|
||||
user_transform_ptr, int user_transform_depth, int user_transform_channels)
|
||||
{
|
||||
png_debug(1, "in png_set_user_transform_info");
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
|
||||
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
|
||||
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
|
||||
(png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
|
||||
{
|
||||
png_app_error(png_ptr,
|
||||
"info change after png_start_read_image or png_read_update_info");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
png_ptr->user_transform_ptr = user_transform_ptr;
|
||||
png_ptr->user_transform_depth = (png_byte)user_transform_depth;
|
||||
png_ptr->user_transform_channels = (png_byte)user_transform_channels;
|
||||
#else
|
||||
if (user_transform_ptr || user_transform_depth || user_transform_channels)
|
||||
png_warning(png_ptr,
|
||||
"This version of libpng does not support user transform info");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function returns a pointer to the user_transform_ptr associated with
|
||||
* the user transform functions. The application should free any memory
|
||||
* associated with this pointer before png_write_destroy and png_read_destroy
|
||||
* are called.
|
||||
*/
|
||||
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
png_voidp PNGAPI
|
||||
png_get_user_transform_ptr(png_const_structp png_ptr)
|
||||
png_get_user_transform_ptr(png_const_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return (NULL);
|
||||
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
|
||||
return ((png_voidp)png_ptr->user_transform_ptr);
|
||||
#else
|
||||
return (NULL);
|
||||
#endif
|
||||
|
||||
return png_ptr->user_transform_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_current_row_number(png_const_structrp png_ptr)
|
||||
{
|
||||
/* See the comments in png.h - this is the sub-image row when reading and
|
||||
* interlaced image.
|
||||
*/
|
||||
if (png_ptr != NULL)
|
||||
return png_ptr->row_number;
|
||||
|
||||
return PNG_UINT_32_MAX; /* help the app not to fail silently */
|
||||
}
|
||||
|
||||
png_byte PNGAPI
|
||||
png_get_current_pass_number(png_const_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
return png_ptr->pass;
|
||||
return 8; /* invalid */
|
||||
}
|
||||
#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
|
||||
#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
|
||||
PNG_WRITE_USER_TRANSFORM_SUPPORTED */
|
||||
#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
|
||||
|
||||
+30
-107
@@ -1,8 +1,8 @@
|
||||
|
||||
/* pngwio.c - functions for data output
|
||||
*
|
||||
* Last changed in libpng 1.4.0 [January 3, 2010]
|
||||
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
|
||||
* Last changed in libpng 1.6.0 [February 14, 2013]
|
||||
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
@@ -18,11 +18,10 @@
|
||||
* them at run time with png_set_write_fn(...).
|
||||
*/
|
||||
|
||||
#define PNG_NO_PEDANTIC_WARNINGS
|
||||
#include "png.h"
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
#include "pngpriv.h"
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
|
||||
/* Write the data to whatever output you are using. The default routine
|
||||
* writes to a file pointer. Note that this routine sometimes gets called
|
||||
* with very small lengths, so you should implement some kind of simple
|
||||
@@ -31,10 +30,13 @@
|
||||
*/
|
||||
|
||||
void /* PRIVATE */
|
||||
png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
|
||||
{
|
||||
/* NOTE: write_data_fn must not change the buffer! */
|
||||
if (png_ptr->write_data_fn != NULL )
|
||||
(*(png_ptr->write_data_fn))(png_ptr, data, length);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data),
|
||||
length);
|
||||
|
||||
else
|
||||
png_error(png_ptr, "Call to NULL write function");
|
||||
}
|
||||
@@ -45,70 +47,19 @@ png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
* write_data function and use it at run time with png_set_write_fn(), rather
|
||||
* than changing the library.
|
||||
*/
|
||||
#ifndef USE_FAR_KEYWORD
|
||||
void PNGAPI
|
||||
void PNGCBAPI
|
||||
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
png_size_t check;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
|
||||
check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
|
||||
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
#else
|
||||
/* This is the model-independent version. Since the standard I/O library
|
||||
* can't handle far buffers in the medium and small models, we have to copy
|
||||
* the data.
|
||||
*/
|
||||
|
||||
#define NEAR_BUF_SIZE 1024
|
||||
#define MIN(a,b) (a <= b ? a : b)
|
||||
|
||||
void PNGAPI
|
||||
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
|
||||
png_FILE_p io_ptr;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
/* Check if data really is near. If so, use usual code. */
|
||||
near_data = (png_byte *)CVT_PTR_NOCHECK(data);
|
||||
io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
|
||||
if ((png_bytep)near_data == data)
|
||||
{
|
||||
check = fwrite(near_data, 1, length, io_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
png_byte buf[NEAR_BUF_SIZE];
|
||||
png_size_t written, remaining, err;
|
||||
check = 0;
|
||||
remaining = length;
|
||||
do
|
||||
{
|
||||
written = MIN(NEAR_BUF_SIZE, remaining);
|
||||
png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
|
||||
err = fwrite(buf, 1, written, io_ptr);
|
||||
if (err != written)
|
||||
break;
|
||||
|
||||
else
|
||||
check += err;
|
||||
|
||||
data += written;
|
||||
remaining -= written;
|
||||
}
|
||||
while (remaining != 0);
|
||||
}
|
||||
if (check != length)
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* This function is called to output any data pending writing (normally
|
||||
@@ -117,23 +68,25 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
*/
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_flush(png_structp png_ptr)
|
||||
png_flush(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr->output_flush_fn != NULL)
|
||||
(*(png_ptr->output_flush_fn))(png_ptr);
|
||||
}
|
||||
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
void PNGAPI
|
||||
# ifdef PNG_STDIO_SUPPORTED
|
||||
void PNGCBAPI
|
||||
png_default_flush(png_structp png_ptr)
|
||||
{
|
||||
png_FILE_p io_ptr;
|
||||
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
|
||||
|
||||
io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr));
|
||||
fflush(io_ptr);
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* This function allows the application to supply new output functions for
|
||||
@@ -166,8 +119,8 @@ png_default_flush(png_structp png_ptr)
|
||||
* *FILE structure.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
|
||||
png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
|
||||
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
|
||||
{
|
||||
if (png_ptr == NULL)
|
||||
return;
|
||||
@@ -185,57 +138,27 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
#ifdef PNG_STDIO_SUPPORTED
|
||||
# ifdef PNG_STDIO_SUPPORTED
|
||||
|
||||
if (output_flush_fn != NULL)
|
||||
png_ptr->output_flush_fn = output_flush_fn;
|
||||
|
||||
else
|
||||
png_ptr->output_flush_fn = png_default_flush;
|
||||
#else
|
||||
|
||||
# else
|
||||
png_ptr->output_flush_fn = output_flush_fn;
|
||||
#endif
|
||||
# endif
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
|
||||
/* It is an error to read while writing a png file */
|
||||
if (png_ptr->read_data_fn != NULL)
|
||||
{
|
||||
png_ptr->read_data_fn = NULL;
|
||||
|
||||
png_warning(png_ptr,
|
||||
"Attempted to set both read_data_fn and write_data_fn in");
|
||||
png_warning(png_ptr,
|
||||
"the same structure. Resetting read_data_fn to NULL");
|
||||
"Can't set both read_data_fn and write_data_fn in the"
|
||||
" same structure");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
#ifdef _MSC_VER
|
||||
void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
|
||||
{
|
||||
void *near_ptr;
|
||||
void FAR *far_ptr;
|
||||
FP_OFF(near_ptr) = FP_OFF(ptr);
|
||||
far_ptr = (void FAR *)near_ptr;
|
||||
|
||||
if (check != 0)
|
||||
if (FP_SEG(ptr) != FP_SEG(far_ptr))
|
||||
png_error(png_ptr, "segment lost in conversion");
|
||||
|
||||
return(near_ptr);
|
||||
}
|
||||
# else
|
||||
void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
|
||||
{
|
||||
void *near_ptr;
|
||||
void FAR *far_ptr;
|
||||
near_ptr = (void FAR *)ptr;
|
||||
far_ptr = (void FAR *)near_ptr;
|
||||
|
||||
if (check != 0)
|
||||
if (far_ptr != ptr)
|
||||
png_error(png_ptr, "segment lost in conversion");
|
||||
|
||||
return(near_ptr);
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
#endif /* PNG_WRITE_SUPPORTED */
|
||||
|
||||
+1464
-592
File diff suppressed because it is too large
Load Diff
+137
-69
@@ -1,8 +1,8 @@
|
||||
|
||||
/* pngwtran.c - transforms the data in a row for PNG writers
|
||||
*
|
||||
* Last changed in libpng 1.4.1 [February 25, 2010]
|
||||
* Copyright (c) 1998-2010 Glenn Randers-Pehrson
|
||||
* Last changed in libpng 1.6.0 [February 14, 2013]
|
||||
* Copyright (c) 1998-2013 Glenn Randers-Pehrson
|
||||
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
|
||||
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
|
||||
*
|
||||
@@ -11,16 +11,16 @@
|
||||
* and license in png.h
|
||||
*/
|
||||
|
||||
#define PNG_NO_PEDANTIC_WARNINGS
|
||||
#include "png.h"
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
#include "pngpriv.h"
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
|
||||
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
/* Transform the data according to the user's wishes. The order of
|
||||
* transformations is significant.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_write_transformations(png_structp png_ptr)
|
||||
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
|
||||
{
|
||||
png_debug(1, "in png_do_write_transformations");
|
||||
|
||||
@@ -30,56 +30,65 @@ png_do_write_transformations(png_structp png_ptr)
|
||||
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_USER_TRANSFORM)
|
||||
if (png_ptr->write_user_transform_fn != NULL)
|
||||
(*(png_ptr->write_user_transform_fn)) /* User write transform
|
||||
(*(png_ptr->write_user_transform_fn)) /* User write transform
|
||||
function */
|
||||
(png_ptr, /* png_ptr */
|
||||
&(png_ptr->row_info), /* row_info: */
|
||||
/* png_uint_32 width; width of row */
|
||||
/* png_uint_32 rowbytes; number of bytes in row */
|
||||
/* png_byte color_type; color type of pixels */
|
||||
/* png_byte bit_depth; bit depth of samples */
|
||||
/* png_byte channels; number of channels (1-4) */
|
||||
/* png_byte pixel_depth; bits per pixel (depth*channels) */
|
||||
png_ptr->row_buf + 1); /* start of pixel data for row */
|
||||
(png_ptr, /* png_ptr */
|
||||
row_info, /* row_info: */
|
||||
/* png_uint_32 width; width of row */
|
||||
/* png_size_t rowbytes; number of bytes in row */
|
||||
/* png_byte color_type; color type of pixels */
|
||||
/* png_byte bit_depth; bit depth of samples */
|
||||
/* png_byte channels; number of channels (1-4) */
|
||||
/* png_byte pixel_depth; bits per pixel (depth*channels) */
|
||||
png_ptr->row_buf + 1); /* start of pixel data for row */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_FILLER_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_FILLER)
|
||||
png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
png_ptr->flags);
|
||||
png_do_strip_channel(row_info, png_ptr->row_buf + 1,
|
||||
!(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_PACKSWAP)
|
||||
png_do_packswap(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
png_do_packswap(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_PACK_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_PACK)
|
||||
png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
(png_uint_32)png_ptr->bit_depth);
|
||||
png_do_pack(row_info, png_ptr->row_buf + 1,
|
||||
(png_uint_32)png_ptr->bit_depth);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SWAP_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_SWAP_BYTES)
|
||||
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
png_do_swap(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SHIFT_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_SHIFT)
|
||||
png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
&(png_ptr->shift));
|
||||
png_do_shift(row_info, png_ptr->row_buf + 1,
|
||||
&(png_ptr->shift));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_SWAP_ALPHA)
|
||||
png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_INVERT_ALPHA)
|
||||
png_do_write_invert_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_BGR_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_BGR)
|
||||
png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
png_do_bgr(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_INVERT_SUPPORTED
|
||||
if (png_ptr->transformations & PNG_INVERT_MONO)
|
||||
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
png_do_invert(row_info, png_ptr->row_buf + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -114,9 +123,12 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
{
|
||||
if (*sp != 0)
|
||||
v |= mask;
|
||||
|
||||
sp++;
|
||||
|
||||
if (mask > 1)
|
||||
mask >>= 1;
|
||||
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
@@ -125,10 +137,13 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mask != 0x80)
|
||||
*dp = (png_byte)v;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
@@ -140,12 +155,14 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
dp = row;
|
||||
shift = 6;
|
||||
v = 0;
|
||||
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
png_byte value;
|
||||
|
||||
value = (png_byte)(*sp & 0x03);
|
||||
v |= (value << shift);
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 6;
|
||||
@@ -153,14 +170,19 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
else
|
||||
shift -= 2;
|
||||
|
||||
sp++;
|
||||
}
|
||||
|
||||
if (shift != 6)
|
||||
*dp = (png_byte)v;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
png_bytep sp, dp;
|
||||
@@ -172,6 +194,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
dp = row;
|
||||
shift = 4;
|
||||
v = 0;
|
||||
|
||||
for (i = 0; i < row_width; i++)
|
||||
{
|
||||
png_byte value;
|
||||
@@ -186,23 +209,27 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
|
||||
else
|
||||
shift -= 4;
|
||||
|
||||
sp++;
|
||||
}
|
||||
|
||||
if (shift != 4)
|
||||
*dp = (png_byte)v;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
row_info->bit_depth = (png_byte)bit_depth;
|
||||
row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
|
||||
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
|
||||
row_info->width);
|
||||
row_info->width);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -216,12 +243,12 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
|
||||
* data to 0 to 15.
|
||||
*/
|
||||
void /* PRIVATE */
|
||||
png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
|
||||
png_do_shift(png_row_infop row_info, png_bytep row,
|
||||
png_const_color_8p bit_depth)
|
||||
{
|
||||
png_debug(1, "in png_do_shift");
|
||||
|
||||
if (
|
||||
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
{
|
||||
int shift_start[4], shift_dec[4];
|
||||
int channels = 0;
|
||||
@@ -231,19 +258,23 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->red;
|
||||
shift_dec[channels] = bit_depth->red;
|
||||
channels++;
|
||||
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->green;
|
||||
shift_dec[channels] = bit_depth->green;
|
||||
channels++;
|
||||
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->blue;
|
||||
shift_dec[channels] = bit_depth->blue;
|
||||
channels++;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->gray;
|
||||
shift_dec[channels] = bit_depth->gray;
|
||||
channels++;
|
||||
}
|
||||
|
||||
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
|
||||
@@ -255,33 +286,40 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
|
||||
if (row_info->bit_depth < 8)
|
||||
{
|
||||
png_bytep bp = row;
|
||||
png_uint_32 i;
|
||||
png_byte mask;
|
||||
png_uint_32 row_bytes = row_info->rowbytes;
|
||||
png_size_t i;
|
||||
unsigned int mask;
|
||||
png_size_t row_bytes = row_info->rowbytes;
|
||||
|
||||
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
|
||||
mask = 0x55;
|
||||
|
||||
else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
|
||||
mask = 0x11;
|
||||
|
||||
else
|
||||
mask = 0xff;
|
||||
|
||||
for (i = 0; i < row_bytes; i++, bp++)
|
||||
{
|
||||
png_uint_16 v;
|
||||
int j;
|
||||
unsigned int v, out;
|
||||
|
||||
v = *bp;
|
||||
*bp = 0;
|
||||
out = 0;
|
||||
|
||||
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
|
||||
{
|
||||
if (j > 0)
|
||||
*bp |= (png_byte)((v << j) & 0xff);
|
||||
out |= v << j;
|
||||
|
||||
else
|
||||
*bp |= (png_byte)((v >> (-j)) & mask);
|
||||
out |= (v >> (-j)) & mask;
|
||||
}
|
||||
|
||||
*bp = (png_byte)(out & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
else if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_bytep bp = row;
|
||||
@@ -291,21 +329,26 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
|
||||
for (i = 0; i < istop; i++, bp++)
|
||||
{
|
||||
|
||||
png_uint_16 v;
|
||||
const unsigned int c = i%channels;
|
||||
int j;
|
||||
int c = (int)(i%channels);
|
||||
unsigned int v, out;
|
||||
|
||||
v = *bp;
|
||||
*bp = 0;
|
||||
out = 0;
|
||||
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
*bp |= (png_byte)((v << j) & 0xff);
|
||||
out |= v << j;
|
||||
|
||||
else
|
||||
*bp |= (png_byte)((v >> (-j)) & 0xff);
|
||||
out |= v >> (-j);
|
||||
}
|
||||
|
||||
*bp = (png_byte)(out & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
png_bytep bp;
|
||||
@@ -314,20 +357,22 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
|
||||
|
||||
for (bp = row, i = 0; i < istop; i++)
|
||||
{
|
||||
int c = (int)(i%channels);
|
||||
png_uint_16 value, v;
|
||||
const unsigned int c = i%channels;
|
||||
int j;
|
||||
unsigned int value, v;
|
||||
|
||||
v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
|
||||
v = png_get_uint_16(bp);
|
||||
value = 0;
|
||||
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
|
||||
value |= v << j;
|
||||
|
||||
else
|
||||
value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
|
||||
value |= v >> (-j);
|
||||
}
|
||||
*bp++ = (png_byte)(value >> 8);
|
||||
*bp++ = (png_byte)((value >> 8) & 0xff);
|
||||
*bp++ = (png_byte)(value & 0xff);
|
||||
}
|
||||
}
|
||||
@@ -344,12 +389,13 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
/* This converts from ARGB to RGBA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This converts from ARGB to RGBA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
png_byte save = *(sp++);
|
||||
@@ -359,9 +405,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = save;
|
||||
}
|
||||
}
|
||||
/* This converts from AARRGGBB to RRGGBBAA */
|
||||
|
||||
#ifdef PNG_WRITE_16BIT_SUPPORTED
|
||||
else
|
||||
{
|
||||
/* This converts from AARRGGBB to RRGGBBAA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -381,12 +429,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = save[1];
|
||||
}
|
||||
}
|
||||
#endif /* PNG_WRITE_16BIT_SUPPORTED */
|
||||
}
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
{
|
||||
/* This converts from AG to GA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This converts from AG to GA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -398,9 +448,11 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = save;
|
||||
}
|
||||
}
|
||||
/* This converts from AAGG to GGAA */
|
||||
|
||||
#ifdef PNG_WRITE_16BIT_SUPPORTED
|
||||
else
|
||||
{
|
||||
/* This converts from AAGG to GGAA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -416,6 +468,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = save[1];
|
||||
}
|
||||
}
|
||||
#endif /* PNG_WRITE_16BIT_SUPPORTED */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,12 +483,13 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
/* This inverts the alpha channel in RGBA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This inverts the alpha channel in RGBA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
|
||||
for (i = 0, sp = dp = row; i < row_width; i++)
|
||||
{
|
||||
/* Does nothing
|
||||
@@ -447,9 +501,11 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
/* This inverts the alpha channel in RRGGBBAA */
|
||||
|
||||
#ifdef PNG_WRITE_16BIT_SUPPORTED
|
||||
else
|
||||
{
|
||||
/* This inverts the alpha channel in RRGGBBAA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -469,12 +525,14 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
#endif /* PNG_WRITE_16BIT_SUPPORTED */
|
||||
}
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
{
|
||||
/* This inverts the alpha channel in GA */
|
||||
if (row_info->bit_depth == 8)
|
||||
{
|
||||
/* This inverts the alpha channel in GA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -485,9 +543,11 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
/* This inverts the alpha channel in GGAA */
|
||||
|
||||
#ifdef PNG_WRITE_16BIT_SUPPORTED
|
||||
else
|
||||
{
|
||||
/* This inverts the alpha channel in GGAA */
|
||||
png_bytep sp, dp;
|
||||
png_uint_32 i;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -503,10 +563,12 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
|
||||
*(dp++) = (png_byte)(255 - *(sp++));
|
||||
}
|
||||
}
|
||||
#endif /* PNG_WRITE_16BIT_SUPPORTED */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
|
||||
|
||||
#ifdef PNG_MNG_FEATURES_SUPPORTED
|
||||
/* Undoes intrapixel differencing */
|
||||
@@ -515,8 +577,7 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_do_write_intrapixel");
|
||||
|
||||
if (
|
||||
(row_info->color_type & PNG_COLOR_MASK_COLOR))
|
||||
if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
|
||||
{
|
||||
int bytes_per_pixel;
|
||||
png_uint_32 row_width = row_info->width;
|
||||
@@ -527,17 +588,21 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
|
||||
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
bytes_per_pixel = 3;
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
bytes_per_pixel = 4;
|
||||
|
||||
else
|
||||
return;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
|
||||
{
|
||||
*(rp) = (png_byte)((*rp - *(rp+1))&0xff);
|
||||
*(rp+2) = (png_byte)((*(rp+2) - *(rp+1))&0xff);
|
||||
*(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff);
|
||||
*(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PNG_WRITE_16BIT_SUPPORTED
|
||||
else if (row_info->bit_depth == 16)
|
||||
{
|
||||
png_bytep rp;
|
||||
@@ -545,24 +610,27 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
|
||||
|
||||
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
|
||||
bytes_per_pixel = 6;
|
||||
|
||||
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
bytes_per_pixel = 8;
|
||||
|
||||
else
|
||||
return;
|
||||
|
||||
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
|
||||
{
|
||||
png_uint_32 s0 = (*(rp ) << 8) | *(rp+1);
|
||||
png_uint_32 s1 = (*(rp+2) << 8) | *(rp+3);
|
||||
png_uint_32 s2 = (*(rp+4) << 8) | *(rp+5);
|
||||
png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
|
||||
png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
|
||||
png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
|
||||
png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
|
||||
png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
|
||||
*(rp ) = (png_byte)((red >> 8) & 0xff);
|
||||
*(rp+1) = (png_byte)(red & 0xff);
|
||||
*(rp+4) = (png_byte)((blue >> 8) & 0xff);
|
||||
*(rp+5) = (png_byte)(blue & 0xff);
|
||||
*(rp ) = (png_byte)((red >> 8) & 0xff);
|
||||
*(rp + 1) = (png_byte)(red & 0xff);
|
||||
*(rp + 4) = (png_byte)((blue >> 8) & 0xff);
|
||||
*(rp + 5) = (png_byte)(blue & 0xff);
|
||||
}
|
||||
}
|
||||
#endif /* PNG_WRITE_16BIT_SUPPORTED */
|
||||
}
|
||||
}
|
||||
#endif /* PNG_MNG_FEATURES_SUPPORTED */
|
||||
|
||||
+1283
-1048
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := sdl2_image
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/../jpeg/include $(LOCAL_PATH)/../png/include $(LOCAL_PATH)/../sdl-$(SDL_VERSION)/include $(LOCAL_PATH)/include
|
||||
LOCAL_CFLAGS := -O3 \
|
||||
-DLOAD_JPG -DLOAD_PNG -DLOAD_BMP -DLOAD_GIF -DLOAD_LBM \
|
||||
-DLOAD_PCX -DLOAD_PNM -DLOAD_TGA -DLOAD_XCF -DLOAD_XPM \
|
||||
-DLOAD_XV
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
LOCAL_SRC_FILES := $(notdir $(wildcard $(LOCAL_PATH)/*.c))
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := png jpeg
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := sdl-$(SDL_VERSION)
|
||||
|
||||
LOCAL_LDLIBS := -lz
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
2.0.0:
|
||||
Sam Lantinga - Sun Jun 2 22:25:31 PDT 2013
|
||||
* Added PNG save support based on miniz.c by Rich Geldreich
|
||||
IMG_SavePNG(), IMG_SavePNG_RW()
|
||||
Sam Lantinga - Sat Jun 1 19:11:26 PDT 2013
|
||||
* Updated for SDL 2.0 release
|
||||
Sam Lantinga - Sat Mar 23 13:36:51 PDT 2013
|
||||
* Fixed bug setting colorkey for indexed PNG images
|
||||
Torsten Stremlau - Sun Mar 10 10:19:25 PDT 2013
|
||||
* Added support for alpha and lossless WEBP images
|
||||
|
||||
1.2.12:
|
||||
mscott - 2012-02-06 19:40:23 PST
|
||||
* Fixed image corruption when using ImageIO framework
|
||||
Sylvain - Thu Nov 22 13:09:59 PST 2012
|
||||
* Added extended XPM color table (disabled by default in IMG_xpm.c)
|
||||
Sam Lantinga - Thu Jan 19 23:18:09 EST 2012
|
||||
* Fixed regression in 1.2.11 loading 8-bit PNG images with libpng
|
||||
|
||||
1.2.11:
|
||||
Sam Lantinga - Sat Jan 14 17:54:38 EST 2012
|
||||
* Fixed loading 8-bit PNG images on Mac OS X
|
||||
Sam Lantinga - Sat Dec 31 09:35:40 EST 2011
|
||||
* SDL_image is now under the zlib license
|
||||
Michael Bonfils - Mon Nov 28 21:46:00 EST 2011
|
||||
* Added WEBP image support
|
||||
Thomas Klausner - Wed Jan 19 19:31:25 PST 2011
|
||||
* Fixed compiling with libpng 1.4
|
||||
Sam Lantinga - Mon Jan 10 12:09:57 2011 -0800
|
||||
* Added Android.mk to build on the Android platform
|
||||
Sam Lantinga - Mon May 10 22:42:53 PDT 2010
|
||||
* Fixed loading HAM6 images with stencil mask
|
||||
Mark Tucker - Fri, 27 Nov 2009 12:38:21 -0500
|
||||
* Fixed bug loading 15 and 16 bit BMP images
|
||||
|
||||
1.2.10:
|
||||
Sam Lantinga - Sat Nov 14 11:22:14 PST 2009
|
||||
* Fixed bug loading multiple images
|
||||
|
||||
1.2.9:
|
||||
Sam Lantinga - Tue Nov 10 00:29:20 PST 2009
|
||||
* Fixed alpha premultiplication on Mac OS X and iPhone OS
|
||||
Sam Lantinga - Sun Nov 8 07:52:11 PST 2009
|
||||
* Fixed checking for IMG_Init() return value in image loaders
|
||||
|
||||
1.2.8:
|
||||
Sam Lantinga - Sun Oct 4 13:12:54 PDT 2009
|
||||
* Added support for uncompressed PCX files
|
||||
Mason Wheeler - 2009-06-10 06:29:45 PDT
|
||||
* Added IMG_Init()/IMG_Quit() to prevent constantly loading and unloading DLLs
|
||||
Couriersud - Mon, 12 Jan 2009 17:21:13 -0800
|
||||
* Added support for ICO and CUR image files
|
||||
Eric Wing - Fri, 2 Jan 2009 02:01:16 -0800
|
||||
* Added ImageIO loading infrastructure for Mac OS X
|
||||
* Added UIImage loading infrastructure for iPhone / iPod Touch
|
||||
|
||||
1.2.7:
|
||||
Sam Lantinga - Sun Nov 2 15:08:27 PST 2008
|
||||
* Fixed buffer overflow in BMP loading code, discovered by j00ru//vx
|
||||
Sam Lantinga - Fri Dec 28 08:34:54 PST 2007
|
||||
* Fixed buffer overflow in GIF loading code, discovered by Michael Skladnikiewicz
|
||||
|
||||
1.2.6:
|
||||
Sam lantinga - Wed Jul 18 00:30:32 PDT 2007
|
||||
* Improved detection of libjpeg, libpng, and libtiff at configure time
|
||||
* PNG and TIFF images are correctly identified even if dynamic libraries
|
||||
to load them aren't available.
|
||||
* Fixed loading of TIFF images using libtiff 3.6
|
||||
Sam Lantinga - Thu Jul 5 07:52:35 2007
|
||||
* Fixed static linking with libjpeg
|
||||
Michael Koch - Tue Feb 13 10:09:17 2007
|
||||
* Fixed crash in IMG_ReadXPMFromArray()
|
||||
|
||||
1.2.5:
|
||||
Maurizio Monge - Sun May 14 13:57:32 PDT 2006
|
||||
* Fixed loading BMP palettes at unusual offsets
|
||||
Sam Lantinga - Thu May 11 21:51:19 PDT 2006
|
||||
* Added support for dynamically loading libjpeg, libpng, and libtiff.
|
||||
Sam Lantinga - Sun Apr 30 01:48:40 PDT 2006
|
||||
* Added gcc-fat.sh for generating Universal binaries on Mac OS X
|
||||
* Updated libtool support to version 1.5.22
|
||||
Sam Lantinga - Sat Feb 4 15:17:44 PST 2006
|
||||
* Added support for XV thumbnail images
|
||||
Gautier Portet - Fri, 19 Mar 2004 17:35:12 +0100
|
||||
* Added support for 32-bit BMP files with alpha
|
||||
|
||||
1.2.4:
|
||||
Pierre G. Richard - Fri, 30 Jul 2004 11:13:11 +0000 (UTC)
|
||||
* Added support for RLE encoded BMP files
|
||||
Marc Le Douarain - Fri, 26 Dec 2003 18:23:42 +0100
|
||||
* Added EHB and HAM mode support to the ILBM loader
|
||||
Sam Lantinga - Wed Nov 19 00:23:44 PST 2003
|
||||
* Updated libtool support for new mingw32 DLL build process
|
||||
Holger Schemel - Mon, 04 Aug 2003 21:50:52 +0200
|
||||
* Fixed crash loading certain PCX images
|
||||
Kyle Davenport - Sat, 19 Apr 2003 17:13:31 -0500
|
||||
* Added .la files to the development RPM, fixing RPM build on RedHat 8
|
||||
|
||||
1.2.3:
|
||||
Ryan C. Gordon - Sat, 8 Feb 2003 09:36:33 -0500
|
||||
* Fixed memory leak with non-seekable SDL_RWops
|
||||
Marc Le Douarain - Sun, 22 Dec 2002 22:59:51 +0100
|
||||
* Added 24-bit support to the ILBM format loader
|
||||
Sam Lantinga - Sun Oct 20 20:55:46 PDT 2002
|
||||
* Added shared library support for MacOS X
|
||||
Pete Shinners - Thu Jun 20 10:05:54 PDT 2002
|
||||
* The JPEG loader can now load EXIF format JPEG images
|
||||
Dag-Erling Smorgrav - Thu May 2 19:09:48 PDT 2002
|
||||
* The XCF loader now ignores invisible layers and channels
|
||||
|
||||
1.2.2:
|
||||
Sam Lantinga - Sat Apr 13 07:49:47 PDT 2002
|
||||
* Updated autogen.sh for new versions of automake
|
||||
* Specify the SDL API calling convention (C by default)
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* A simple library to load images of various formats as SDL surfaces */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#define ARRAYSIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
/* Table of image detection and loading functions */
|
||||
static struct {
|
||||
char *type;
|
||||
int (SDLCALL *is)(SDL_RWops *src);
|
||||
SDL_Surface *(SDLCALL *load)(SDL_RWops *src);
|
||||
} supported[] = {
|
||||
/* keep magicless formats first */
|
||||
{ "TGA", NULL, IMG_LoadTGA_RW },
|
||||
{ "CUR", IMG_isCUR, IMG_LoadCUR_RW },
|
||||
{ "ICO", IMG_isICO, IMG_LoadICO_RW },
|
||||
{ "BMP", IMG_isBMP, IMG_LoadBMP_RW },
|
||||
{ "GIF", IMG_isGIF, IMG_LoadGIF_RW },
|
||||
{ "JPG", IMG_isJPG, IMG_LoadJPG_RW },
|
||||
{ "LBM", IMG_isLBM, IMG_LoadLBM_RW },
|
||||
{ "PCX", IMG_isPCX, IMG_LoadPCX_RW },
|
||||
{ "PNG", IMG_isPNG, IMG_LoadPNG_RW },
|
||||
{ "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */
|
||||
{ "TIF", IMG_isTIF, IMG_LoadTIF_RW },
|
||||
{ "XCF", IMG_isXCF, IMG_LoadXCF_RW },
|
||||
{ "XPM", IMG_isXPM, IMG_LoadXPM_RW },
|
||||
{ "XV", IMG_isXV, IMG_LoadXV_RW },
|
||||
{ "WEBP", IMG_isWEBP, IMG_LoadWEBP_RW },
|
||||
};
|
||||
|
||||
const SDL_version *IMG_Linked_Version(void)
|
||||
{
|
||||
static SDL_version linked_version;
|
||||
SDL_IMAGE_VERSION(&linked_version);
|
||||
return(&linked_version);
|
||||
}
|
||||
|
||||
extern int IMG_InitJPG();
|
||||
extern void IMG_QuitJPG();
|
||||
extern int IMG_InitPNG();
|
||||
extern void IMG_QuitPNG();
|
||||
extern int IMG_InitTIF();
|
||||
extern void IMG_QuitTIF();
|
||||
|
||||
extern int IMG_InitWEBP();
|
||||
extern void IMG_QuitWEBP();
|
||||
|
||||
static int initialized = 0;
|
||||
|
||||
int IMG_Init(int flags)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (flags & IMG_INIT_JPG) {
|
||||
if ((initialized & IMG_INIT_JPG) || IMG_InitJPG() == 0) {
|
||||
result |= IMG_INIT_JPG;
|
||||
}
|
||||
}
|
||||
if (flags & IMG_INIT_PNG) {
|
||||
if ((initialized & IMG_INIT_PNG) || IMG_InitPNG() == 0) {
|
||||
result |= IMG_INIT_PNG;
|
||||
}
|
||||
}
|
||||
if (flags & IMG_INIT_TIF) {
|
||||
if ((initialized & IMG_INIT_TIF) || IMG_InitTIF() == 0) {
|
||||
result |= IMG_INIT_TIF;
|
||||
}
|
||||
}
|
||||
if (flags & IMG_INIT_WEBP) {
|
||||
if ((initialized & IMG_INIT_WEBP) || IMG_InitWEBP() == 0) {
|
||||
result |= IMG_INIT_WEBP;
|
||||
}
|
||||
}
|
||||
initialized |= result;
|
||||
|
||||
return (initialized);
|
||||
}
|
||||
|
||||
void IMG_Quit()
|
||||
{
|
||||
if (initialized & IMG_INIT_JPG) {
|
||||
IMG_QuitJPG();
|
||||
}
|
||||
if (initialized & IMG_INIT_PNG) {
|
||||
IMG_QuitPNG();
|
||||
}
|
||||
if (initialized & IMG_INIT_TIF) {
|
||||
IMG_QuitTIF();
|
||||
}
|
||||
if (initialized & IMG_INIT_WEBP) {
|
||||
IMG_QuitWEBP();
|
||||
}
|
||||
initialized = 0;
|
||||
}
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
/* Load an image from a file */
|
||||
SDL_Surface *IMG_Load(const char *file)
|
||||
{
|
||||
SDL_RWops *src = SDL_RWFromFile(file, "rb");
|
||||
const char *ext = strrchr(file, '.');
|
||||
if(ext) {
|
||||
ext++;
|
||||
}
|
||||
if(!src) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
return IMG_LoadTyped_RW(src, 1, ext);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Load an image from an SDL datasource (for compatibility) */
|
||||
SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc)
|
||||
{
|
||||
return IMG_LoadTyped_RW(src, freesrc, NULL);
|
||||
}
|
||||
|
||||
/* Portable case-insensitive string compare function */
|
||||
static int IMG_string_equals(const char *str1, const char *str2)
|
||||
{
|
||||
while ( *str1 && *str2 ) {
|
||||
if ( toupper((unsigned char)*str1) !=
|
||||
toupper((unsigned char)*str2) )
|
||||
break;
|
||||
++str1;
|
||||
++str2;
|
||||
}
|
||||
return (!*str1 && !*str2);
|
||||
}
|
||||
|
||||
/* Load an image from an SDL datasource, optionally specifying the type */
|
||||
SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, const char *type)
|
||||
{
|
||||
int i;
|
||||
SDL_Surface *image;
|
||||
|
||||
/* Make sure there is something to do.. */
|
||||
if ( src == NULL ) {
|
||||
IMG_SetError("Passed a NULL data source");
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* See whether or not this data source can handle seeking */
|
||||
if ( SDL_RWseek(src, 0, RW_SEEK_CUR) < 0 ) {
|
||||
IMG_SetError("Can't seek in this data source");
|
||||
if(freesrc)
|
||||
SDL_RWclose(src);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Detect the type of image being loaded */
|
||||
image = NULL;
|
||||
for ( i=0; i < ARRAYSIZE(supported); ++i ) {
|
||||
if(supported[i].is) {
|
||||
if(!supported[i].is(src))
|
||||
continue;
|
||||
} else {
|
||||
/* magicless format */
|
||||
if(!type
|
||||
|| !IMG_string_equals(type, supported[i].type))
|
||||
continue;
|
||||
}
|
||||
#ifdef DEBUG_IMGLIB
|
||||
fprintf(stderr, "IMGLIB: Loading image as %s\n",
|
||||
supported[i].type);
|
||||
#endif
|
||||
image = supported[i].load(src);
|
||||
if(freesrc)
|
||||
SDL_RWclose(src);
|
||||
return image;
|
||||
}
|
||||
|
||||
if ( freesrc ) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
IMG_SetError("Unsupported image format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2,0,0)
|
||||
SDL_Texture *IMG_LoadTexture(SDL_Renderer *renderer, const char *file)
|
||||
{
|
||||
SDL_Texture *texture = NULL;
|
||||
SDL_Surface *surface = IMG_Load(file);
|
||||
if (surface) {
|
||||
texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
SDL_Texture *IMG_LoadTexture_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc)
|
||||
{
|
||||
SDL_Texture *texture = NULL;
|
||||
SDL_Surface *surface = IMG_Load_RW(src, freesrc);
|
||||
if (surface) {
|
||||
texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
|
||||
SDL_Texture *IMG_LoadTextureTyped_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc, const char *type)
|
||||
{
|
||||
SDL_Texture *texture = NULL;
|
||||
SDL_Surface *surface = IMG_LoadTyped_RW(src, freesrc, type);
|
||||
if (surface) {
|
||||
texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
return texture;
|
||||
}
|
||||
#endif /* SDL 2.0 */
|
||||
@@ -0,0 +1,892 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if (!defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)) || !defined(BMP_USES_IMAGEIO)
|
||||
|
||||
/* This is a BMP image file loading framework
|
||||
*
|
||||
* ICO/CUR file support is here as well since it uses similar internal
|
||||
* representation
|
||||
*
|
||||
* A good test suite of BMP images is available at:
|
||||
* http://entropymine.com/jason/bmpsuite/bmpsuite/html/bmpsuite.html
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_BMP
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isBMP(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_BMP;
|
||||
char magic[2];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_BMP = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if ( SDL_strncmp(magic, "BM", 2) == 0 ) {
|
||||
is_BMP = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_BMP);
|
||||
}
|
||||
|
||||
static int IMG_isICOCUR(SDL_RWops *src, int type)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_ICOCUR;
|
||||
|
||||
/* The Win32 ICO file header (14 bytes) */
|
||||
Uint16 bfReserved;
|
||||
Uint16 bfType;
|
||||
Uint16 bfCount;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_ICOCUR = 0;
|
||||
bfReserved = SDL_ReadLE16(src);
|
||||
bfType = SDL_ReadLE16(src);
|
||||
bfCount = SDL_ReadLE16(src);
|
||||
if ((bfReserved == 0) && (bfType == type) && (bfCount != 0))
|
||||
is_ICOCUR = 1;
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
|
||||
return (is_ICOCUR);
|
||||
}
|
||||
|
||||
int IMG_isICO(SDL_RWops *src)
|
||||
{
|
||||
return IMG_isICOCUR(src, 1);
|
||||
}
|
||||
|
||||
int IMG_isCUR(SDL_RWops *src)
|
||||
{
|
||||
return IMG_isICOCUR(src, 2);
|
||||
}
|
||||
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_endian.h"
|
||||
|
||||
/* Compression encodings for BMP files */
|
||||
#ifndef BI_RGB
|
||||
#define BI_RGB 0
|
||||
#define BI_RLE8 1
|
||||
#define BI_RLE4 2
|
||||
#define BI_BITFIELDS 3
|
||||
#endif
|
||||
|
||||
static int readRlePixels(SDL_Surface * surface, SDL_RWops * src, int isRle8)
|
||||
{
|
||||
/*
|
||||
| Sets the surface pixels from src. A bmp image is upside down.
|
||||
*/
|
||||
int pitch = surface->pitch;
|
||||
int height = surface->h;
|
||||
Uint8 *start = (Uint8 *)surface->pixels;
|
||||
Uint8 *end = start + (height*pitch);
|
||||
Uint8 *bits = end-pitch, *spot;
|
||||
int ofs = 0;
|
||||
Uint8 ch;
|
||||
Uint8 needsPad;
|
||||
|
||||
#define COPY_PIXEL(x) spot = &bits[ofs++]; if(spot >= start && spot < end) *spot = (x)
|
||||
|
||||
for (;;) {
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
/*
|
||||
| encoded mode starts with a run length, and then a byte
|
||||
| with two colour indexes to alternate between for the run
|
||||
*/
|
||||
if ( ch ) {
|
||||
Uint8 pixel;
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
|
||||
if ( isRle8 ) { /* 256-color bitmap, compressed */
|
||||
do {
|
||||
COPY_PIXEL(pixel);
|
||||
} while (--ch);
|
||||
} else { /* 16-color bitmap, compressed */
|
||||
Uint8 pixel0 = pixel >> 4;
|
||||
Uint8 pixel1 = pixel & 0x0F;
|
||||
for (;;) {
|
||||
COPY_PIXEL(pixel0); /* even count, high nibble */
|
||||
if (!--ch) break;
|
||||
COPY_PIXEL(pixel1); /* odd count, low nibble */
|
||||
if (!--ch) break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
| A leading zero is an escape; it may signal the end of the bitmap,
|
||||
| a cursor move, or some absolute data.
|
||||
| zero tag may be absolute mode or an escape
|
||||
*/
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
switch (ch) {
|
||||
case 0: /* end of line */
|
||||
ofs = 0;
|
||||
bits -= pitch; /* go to previous */
|
||||
break;
|
||||
case 1: /* end of bitmap */
|
||||
return 0; /* success! */
|
||||
case 2: /* delta */
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
ofs += ch;
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
bits -= (ch * pitch);
|
||||
break;
|
||||
default: /* no compression */
|
||||
if (isRle8) {
|
||||
needsPad = ( ch & 1 );
|
||||
do {
|
||||
Uint8 pixel;
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
|
||||
COPY_PIXEL(pixel);
|
||||
} while (--ch);
|
||||
} else {
|
||||
needsPad = ( ((ch+1)>>1) & 1 ); /* (ch+1)>>1: bytes size */
|
||||
for (;;) {
|
||||
Uint8 pixel;
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) return 1;
|
||||
COPY_PIXEL(pixel >> 4);
|
||||
if (!--ch) break;
|
||||
COPY_PIXEL(pixel & 0x0F);
|
||||
if (!--ch) break;
|
||||
}
|
||||
}
|
||||
/* pad at even boundary */
|
||||
if ( needsPad && !SDL_RWread(src, &ch, 1, 1) ) return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void CorrectAlphaChannel(SDL_Surface *surface)
|
||||
{
|
||||
/* Check to see if there is any alpha channel data */
|
||||
SDL_bool hasAlpha = SDL_FALSE;
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
int alphaChannelOffset = 0;
|
||||
#else
|
||||
int alphaChannelOffset = 3;
|
||||
#endif
|
||||
Uint8 *alpha = ((Uint8*)surface->pixels) + alphaChannelOffset;
|
||||
Uint8 *end = alpha + surface->h * surface->pitch;
|
||||
|
||||
while (alpha < end) {
|
||||
if (*alpha != 0) {
|
||||
hasAlpha = SDL_TRUE;
|
||||
break;
|
||||
}
|
||||
alpha += 4;
|
||||
}
|
||||
|
||||
if (!hasAlpha) {
|
||||
alpha = ((Uint8*)surface->pixels) + alphaChannelOffset;
|
||||
while (alpha < end) {
|
||||
*alpha = SDL_ALPHA_OPAQUE;
|
||||
alpha += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SDL_Surface *LoadBMP_RW (SDL_RWops *src, int freesrc)
|
||||
{
|
||||
SDL_bool was_error;
|
||||
Sint64 fp_offset;
|
||||
int bmpPitch;
|
||||
int i, pad;
|
||||
SDL_Surface *surface;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
SDL_Palette *palette;
|
||||
Uint8 *bits;
|
||||
Uint8 *top, *end;
|
||||
SDL_bool topDown;
|
||||
int ExpandBMP;
|
||||
SDL_bool correctAlpha = SDL_FALSE;
|
||||
|
||||
/* The Win32 BMP file header (14 bytes) */
|
||||
char magic[2];
|
||||
Uint32 bfSize;
|
||||
Uint16 bfReserved1;
|
||||
Uint16 bfReserved2;
|
||||
Uint32 bfOffBits;
|
||||
|
||||
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
|
||||
Uint32 biSize;
|
||||
Sint32 biWidth;
|
||||
Sint32 biHeight;
|
||||
Uint16 biPlanes;
|
||||
Uint16 biBitCount;
|
||||
Uint32 biCompression;
|
||||
Uint32 biSizeImage;
|
||||
Sint32 biXPelsPerMeter;
|
||||
Sint32 biYPelsPerMeter;
|
||||
Uint32 biClrUsed;
|
||||
Uint32 biClrImportant;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
surface = NULL;
|
||||
was_error = SDL_FALSE;
|
||||
if ( src == NULL ) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read in the BMP file header */
|
||||
fp_offset = SDL_RWtell(src);
|
||||
SDL_ClearError();
|
||||
if ( SDL_RWread(src, magic, 1, 2) != 2 ) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if ( SDL_strncmp(magic, "BM", 2) != 0 ) {
|
||||
IMG_SetError("File is not a Windows BMP file");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
bfSize = SDL_ReadLE32(src);
|
||||
bfReserved1 = SDL_ReadLE16(src);
|
||||
bfReserved2 = SDL_ReadLE16(src);
|
||||
bfOffBits = SDL_ReadLE32(src);
|
||||
|
||||
/* Read the Win32 BITMAPINFOHEADER */
|
||||
biSize = SDL_ReadLE32(src);
|
||||
if ( biSize == 12 ) {
|
||||
biWidth = (Uint32)SDL_ReadLE16(src);
|
||||
biHeight = (Uint32)SDL_ReadLE16(src);
|
||||
biPlanes = SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = BI_RGB;
|
||||
biSizeImage = 0;
|
||||
biXPelsPerMeter = 0;
|
||||
biYPelsPerMeter = 0;
|
||||
biClrUsed = 0;
|
||||
biClrImportant = 0;
|
||||
} else {
|
||||
biWidth = SDL_ReadLE32(src);
|
||||
biHeight = SDL_ReadLE32(src);
|
||||
biPlanes = SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = SDL_ReadLE32(src);
|
||||
biSizeImage = SDL_ReadLE32(src);
|
||||
biXPelsPerMeter = SDL_ReadLE32(src);
|
||||
biYPelsPerMeter = SDL_ReadLE32(src);
|
||||
biClrUsed = SDL_ReadLE32(src);
|
||||
biClrImportant = SDL_ReadLE32(src);
|
||||
}
|
||||
if (biHeight < 0) {
|
||||
topDown = SDL_TRUE;
|
||||
biHeight = -biHeight;
|
||||
} else {
|
||||
topDown = SDL_FALSE;
|
||||
}
|
||||
|
||||
/* Check for read error */
|
||||
if ( strcmp(SDL_GetError(), "") != 0 ) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Expand 1 and 4 bit bitmaps to 8 bits per pixel */
|
||||
switch (biBitCount) {
|
||||
case 1:
|
||||
case 4:
|
||||
ExpandBMP = biBitCount;
|
||||
biBitCount = 8;
|
||||
break;
|
||||
default:
|
||||
ExpandBMP = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* RLE4 and RLE8 BMP compression is supported */
|
||||
Rmask = Gmask = Bmask = Amask = 0;
|
||||
switch (biCompression) {
|
||||
case BI_RGB:
|
||||
/* If there are no masks, use the defaults */
|
||||
if ( bfOffBits == (14+biSize) ) {
|
||||
/* Default values for the BMP format */
|
||||
switch (biBitCount) {
|
||||
case 15:
|
||||
case 16:
|
||||
Rmask = 0x7C00;
|
||||
Gmask = 0x03E0;
|
||||
Bmask = 0x001F;
|
||||
break;
|
||||
case 24:
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
#else
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
#endif
|
||||
break;
|
||||
case 32:
|
||||
/* We don't know if this has alpha channel or not */
|
||||
correctAlpha = SDL_TRUE;
|
||||
Amask = 0xFF000000;
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Fall through -- read the RGB masks */
|
||||
|
||||
default:
|
||||
switch (biBitCount) {
|
||||
case 15:
|
||||
case 16:
|
||||
Rmask = SDL_ReadLE32(src);
|
||||
Gmask = SDL_ReadLE32(src);
|
||||
Bmask = SDL_ReadLE32(src);
|
||||
break;
|
||||
case 32:
|
||||
Rmask = SDL_ReadLE32(src);
|
||||
Gmask = SDL_ReadLE32(src);
|
||||
Bmask = SDL_ReadLE32(src);
|
||||
Amask = SDL_ReadLE32(src);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Create a compatible surface, note that the colors are RGB ordered */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
biWidth, biHeight, biBitCount, Rmask, Gmask, Bmask, Amask);
|
||||
if ( surface == NULL ) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Load the palette, if any */
|
||||
palette = (surface->format)->palette;
|
||||
if ( palette ) {
|
||||
if ( SDL_RWseek(src, fp_offset+14+biSize, RW_SEEK_SET) < 0 ) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
| guich: always use 1<<bpp b/c some bitmaps can bring wrong information
|
||||
| for colorsUsed
|
||||
*/
|
||||
/* if ( biClrUsed == 0 ) { */
|
||||
biClrUsed = 1 << biBitCount;
|
||||
/* } */
|
||||
if ( biSize == 12 ) {
|
||||
for ( i = 0; i < (int)biClrUsed; ++i ) {
|
||||
SDL_RWread(src, &palette->colors[i].b, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].g, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].r, 1, 1);
|
||||
palette->colors[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
} else {
|
||||
for ( i = 0; i < (int)biClrUsed; ++i ) {
|
||||
SDL_RWread(src, &palette->colors[i].b, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].g, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].r, 1, 1);
|
||||
SDL_RWread(src, &palette->colors[i].a, 1, 1);
|
||||
|
||||
/* According to Microsoft documentation, the fourth element
|
||||
is reserved and must be zero, so we shouldn't treat it as
|
||||
alpha.
|
||||
*/
|
||||
palette->colors[i].a = SDL_ALPHA_OPAQUE;
|
||||
}
|
||||
}
|
||||
palette->ncolors = biClrUsed;
|
||||
}
|
||||
|
||||
/* Read the surface pixels. Note that the bmp image is upside down */
|
||||
if ( SDL_RWseek(src, fp_offset+bfOffBits, RW_SEEK_SET) < 0 ) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
if ((biCompression == BI_RLE4) || (biCompression == BI_RLE8)) {
|
||||
was_error = (SDL_bool)readRlePixels(surface, src, biCompression == BI_RLE8);
|
||||
if (was_error) IMG_SetError("Error reading from BMP");
|
||||
goto done;
|
||||
}
|
||||
top = (Uint8 *)surface->pixels;
|
||||
end = (Uint8 *)surface->pixels+(surface->h*surface->pitch);
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
|
||||
break;
|
||||
case 4:
|
||||
bmpPitch = (biWidth + 1) >> 1;
|
||||
pad = (((bmpPitch)%4) ? (4-((bmpPitch)%4)) : 0);
|
||||
break;
|
||||
default:
|
||||
pad = ((surface->pitch%4) ?
|
||||
(4-(surface->pitch%4)) : 0);
|
||||
break;
|
||||
}
|
||||
if ( topDown ) {
|
||||
bits = top;
|
||||
} else {
|
||||
bits = end - surface->pitch;
|
||||
}
|
||||
while ( bits >= top && bits < end ) {
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
case 4: {
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8-ExpandBMP);
|
||||
for ( i=0; i<surface->w; ++i ) {
|
||||
if ( i%(8/ExpandBMP) == 0 ) {
|
||||
if ( !SDL_RWread(src, &pixel, 1, 1) ) {
|
||||
IMG_SetError("Error reading from BMP");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*(bits+i) = (pixel>>shift);
|
||||
pixel <<= ExpandBMP;
|
||||
} }
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( SDL_RWread(src, bits, 1, surface->pitch) != surface->pitch ) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
/* Byte-swap the pixels if needed. Note that the 24bpp
|
||||
case has already been taken care of above. */
|
||||
switch(biBitCount) {
|
||||
case 15:
|
||||
case 16: {
|
||||
Uint16 *pix = (Uint16 *)bits;
|
||||
for(i = 0; i < surface->w; i++)
|
||||
pix[i] = SDL_Swap16(pix[i]);
|
||||
break;
|
||||
}
|
||||
|
||||
case 32: {
|
||||
Uint32 *pix = (Uint32 *)bits;
|
||||
for(i = 0; i < surface->w; i++)
|
||||
pix[i] = SDL_Swap32(pix[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if ( pad ) {
|
||||
Uint8 padbyte;
|
||||
for ( i=0; i<pad; ++i ) {
|
||||
SDL_RWread(src, &padbyte, 1, 1);
|
||||
}
|
||||
}
|
||||
if ( topDown ) {
|
||||
bits += surface->pitch;
|
||||
} else {
|
||||
bits -= surface->pitch;
|
||||
}
|
||||
}
|
||||
if (correctAlpha) {
|
||||
CorrectAlphaChannel(surface);
|
||||
}
|
||||
done:
|
||||
if ( was_error ) {
|
||||
if ( src ) {
|
||||
SDL_RWseek(src, fp_offset, RW_SEEK_SET);
|
||||
}
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
surface = NULL;
|
||||
}
|
||||
if ( freesrc && src ) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
static Uint8
|
||||
SDL_Read8(SDL_RWops * src)
|
||||
{
|
||||
Uint8 value;
|
||||
|
||||
SDL_RWread(src, &value, 1, 1);
|
||||
return (value);
|
||||
}
|
||||
|
||||
static SDL_Surface *
|
||||
LoadICOCUR_RW(SDL_RWops * src, int type, int freesrc)
|
||||
{
|
||||
SDL_bool was_error;
|
||||
Sint64 fp_offset;
|
||||
int bmpPitch;
|
||||
int i, pad;
|
||||
SDL_Surface *surface;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint8 *bits;
|
||||
int ExpandBMP;
|
||||
int maxCol = 0;
|
||||
int icoOfs = 0;
|
||||
Uint32 palette[256];
|
||||
|
||||
/* The Win32 ICO file header (14 bytes) */
|
||||
Uint16 bfReserved;
|
||||
Uint16 bfType;
|
||||
Uint16 bfCount;
|
||||
|
||||
/* The Win32 BITMAPINFOHEADER struct (40 bytes) */
|
||||
Uint32 biSize;
|
||||
Sint32 biWidth;
|
||||
Sint32 biHeight;
|
||||
Uint16 biPlanes;
|
||||
Uint16 biBitCount;
|
||||
Uint32 biCompression;
|
||||
Uint32 biSizeImage;
|
||||
Sint32 biXPelsPerMeter;
|
||||
Sint32 biYPelsPerMeter;
|
||||
Uint32 biClrUsed;
|
||||
Uint32 biClrImportant;
|
||||
|
||||
/* Make sure we are passed a valid data source */
|
||||
surface = NULL;
|
||||
was_error = SDL_FALSE;
|
||||
if (src == NULL) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read in the ICO file header */
|
||||
fp_offset = SDL_RWtell(src);
|
||||
SDL_ClearError();
|
||||
|
||||
bfReserved = SDL_ReadLE16(src);
|
||||
bfType = SDL_ReadLE16(src);
|
||||
bfCount = SDL_ReadLE16(src);
|
||||
if ((bfReserved != 0) || (bfType != type) || (bfCount == 0)) {
|
||||
IMG_SetError("File is not a Windows %s file", type == 1 ? "ICO" : "CUR");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the Win32 Icon Directory */
|
||||
for (i = 0; i < bfCount; i++) {
|
||||
/* Icon Directory Entries */
|
||||
int bWidth = SDL_Read8(src); /* Uint8, but 0 = 256 ! */
|
||||
int bHeight = SDL_Read8(src); /* Uint8, but 0 = 256 ! */
|
||||
int bColorCount = SDL_Read8(src); /* Uint8, but 0 = 256 ! */
|
||||
Uint8 bReserved = SDL_Read8(src);
|
||||
Uint16 wPlanes = SDL_ReadLE16(src);
|
||||
Uint16 wBitCount = SDL_ReadLE16(src);
|
||||
Uint32 dwBytesInRes = SDL_ReadLE32(src);
|
||||
Uint32 dwImageOffset = SDL_ReadLE32(src);
|
||||
|
||||
if (!bWidth)
|
||||
bWidth = 256;
|
||||
if (!bHeight)
|
||||
bHeight = 256;
|
||||
if (!bColorCount)
|
||||
bColorCount = 256;
|
||||
|
||||
//printf("%dx%d@%d - %08x\n", bWidth, bHeight, bColorCount, dwImageOffset);
|
||||
if (bColorCount > maxCol) {
|
||||
maxCol = bColorCount;
|
||||
icoOfs = dwImageOffset;
|
||||
//printf("marked\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Advance to the DIB Data */
|
||||
if (SDL_RWseek(src, icoOfs, RW_SEEK_SET) < 0) {
|
||||
SDL_Error(SDL_EFSEEK);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the Win32 BITMAPINFOHEADER */
|
||||
biSize = SDL_ReadLE32(src);
|
||||
if (biSize == 40) {
|
||||
biWidth = SDL_ReadLE32(src);
|
||||
biHeight = SDL_ReadLE32(src);
|
||||
biPlanes = SDL_ReadLE16(src);
|
||||
biBitCount = SDL_ReadLE16(src);
|
||||
biCompression = SDL_ReadLE32(src);
|
||||
biSizeImage = SDL_ReadLE32(src);
|
||||
biXPelsPerMeter = SDL_ReadLE32(src);
|
||||
biYPelsPerMeter = SDL_ReadLE32(src);
|
||||
biClrUsed = SDL_ReadLE32(src);
|
||||
biClrImportant = SDL_ReadLE32(src);
|
||||
} else {
|
||||
IMG_SetError("Unsupported ICO bitmap format");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check for read error */
|
||||
if (SDL_strcmp(SDL_GetError(), "") != 0) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* We don't support any BMP compression right now */
|
||||
switch (biCompression) {
|
||||
case BI_RGB:
|
||||
/* Default values for the BMP format */
|
||||
switch (biBitCount) {
|
||||
case 1:
|
||||
case 4:
|
||||
ExpandBMP = biBitCount;
|
||||
biBitCount = 8;
|
||||
break;
|
||||
case 8:
|
||||
ExpandBMP = 8;
|
||||
break;
|
||||
case 32:
|
||||
Rmask = 0x00FF0000;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x000000FF;
|
||||
ExpandBMP = 0;
|
||||
break;
|
||||
default:
|
||||
IMG_SetError("ICO file with unsupported bit count");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
IMG_SetError("Compressed ICO files not supported");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create a RGBA surface */
|
||||
biHeight = biHeight >> 1;
|
||||
//printf("%d x %d\n", biWidth, biHeight);
|
||||
surface =
|
||||
SDL_CreateRGBSurface(0, biWidth, biHeight, 32, 0x00FF0000,
|
||||
0x0000FF00, 0x000000FF, 0xFF000000);
|
||||
if (surface == NULL) {
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Load the palette, if any */
|
||||
//printf("bc %d bused %d\n", biBitCount, biClrUsed);
|
||||
if (biBitCount <= 8) {
|
||||
if (biClrUsed == 0) {
|
||||
biClrUsed = 1 << biBitCount;
|
||||
}
|
||||
for (i = 0; i < (int) biClrUsed; ++i) {
|
||||
SDL_RWread(src, &palette[i], 4, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the surface pixels. Note that the bmp image is upside down */
|
||||
bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
case 4:
|
||||
bmpPitch = (biWidth + 1) >> 1;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
case 8:
|
||||
bmpPitch = biWidth;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
break;
|
||||
default:
|
||||
bmpPitch = biWidth * 4;
|
||||
pad = 0;
|
||||
break;
|
||||
}
|
||||
while (bits > (Uint8 *) surface->pixels) {
|
||||
bits -= surface->pitch;
|
||||
switch (ExpandBMP) {
|
||||
case 1:
|
||||
case 4:
|
||||
case 8:
|
||||
{
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8 - ExpandBMP);
|
||||
for (i = 0; i < surface->w; ++i) {
|
||||
if (i % (8 / ExpandBMP) == 0) {
|
||||
if (!SDL_RWread(src, &pixel, 1, 1)) {
|
||||
IMG_SetError("Error reading from ICO");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*((Uint32 *) bits + i) = (palette[pixel >> shift]);
|
||||
pixel <<= ExpandBMP;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (SDL_RWread(src, bits, 1, surface->pitch)
|
||||
!= surface->pitch) {
|
||||
SDL_Error(SDL_EFREAD);
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if (pad) {
|
||||
Uint8 padbyte;
|
||||
for (i = 0; i < pad; ++i) {
|
||||
SDL_RWread(src, &padbyte, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Read the mask pixels. Note that the bmp image is upside down */
|
||||
bits = (Uint8 *) surface->pixels + (surface->h * surface->pitch);
|
||||
ExpandBMP = 1;
|
||||
bmpPitch = (biWidth + 7) >> 3;
|
||||
pad = (((bmpPitch) % 4) ? (4 - ((bmpPitch) % 4)) : 0);
|
||||
while (bits > (Uint8 *) surface->pixels) {
|
||||
Uint8 pixel = 0;
|
||||
int shift = (8 - ExpandBMP);
|
||||
|
||||
bits -= surface->pitch;
|
||||
for (i = 0; i < surface->w; ++i) {
|
||||
if (i % (8 / ExpandBMP) == 0) {
|
||||
if (!SDL_RWread(src, &pixel, 1, 1)) {
|
||||
IMG_SetError("Error reading from ICO");
|
||||
was_error = SDL_TRUE;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
*((Uint32 *) bits + i) |= ((pixel >> shift) ? 0 : 0xFF000000);
|
||||
pixel <<= ExpandBMP;
|
||||
}
|
||||
/* Skip padding bytes, ugh */
|
||||
if (pad) {
|
||||
Uint8 padbyte;
|
||||
for (i = 0; i < pad; ++i) {
|
||||
SDL_RWread(src, &padbyte, 1, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
done:
|
||||
if (was_error) {
|
||||
if (src) {
|
||||
SDL_RWseek(src, fp_offset, RW_SEEK_SET);
|
||||
}
|
||||
if (surface) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
surface = NULL;
|
||||
}
|
||||
if (freesrc && src) {
|
||||
SDL_RWclose(src);
|
||||
}
|
||||
return (surface);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src)
|
||||
{
|
||||
return(LoadBMP_RW(src, 0));
|
||||
}
|
||||
|
||||
/* Load a ICO type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadICO_RW(SDL_RWops *src)
|
||||
{
|
||||
return(LoadICOCUR_RW(src, 1, 0));
|
||||
}
|
||||
|
||||
/* Load a CUR type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadCUR_RW(SDL_RWops *src)
|
||||
{
|
||||
return(LoadICOCUR_RW(src, 2, 0));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isBMP(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int IMG_isICO(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
int IMG_isCUR(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadBMP_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadCUR_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Load a BMP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadICO_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_BMP */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
@@ -0,0 +1,636 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a GIF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_GIF
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isGIF(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_GIF;
|
||||
char magic[6];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_GIF = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if ( (SDL_strncmp(magic, "GIF", 3) == 0) &&
|
||||
((SDL_memcmp(magic + 3, "87a", 3) == 0) ||
|
||||
(SDL_memcmp(magic + 3, "89a", 3) == 0)) ) {
|
||||
is_GIF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_GIF);
|
||||
}
|
||||
|
||||
/* Code from here to end of file has been adapted from XPaint: */
|
||||
/* +-------------------------------------------------------------------+ */
|
||||
/* | Copyright 1990, 1991, 1993 David Koblas. | */
|
||||
/* | Copyright 1996 Torsten Martinsen. | */
|
||||
/* | Permission to use, copy, modify, and distribute this software | */
|
||||
/* | and its documentation for any purpose and without fee is hereby | */
|
||||
/* | granted, provided that the above copyright notice appear in all | */
|
||||
/* | copies and that both that copyright notice and this permission | */
|
||||
/* | notice appear in supporting documentation. This software is | */
|
||||
/* | provided "as is" without express or implied warranty. | */
|
||||
/* +-------------------------------------------------------------------+ */
|
||||
|
||||
/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
|
||||
#define USED_BY_SDL
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef USED_BY_SDL
|
||||
/* Changes to work with SDL:
|
||||
|
||||
Include SDL header file
|
||||
Use SDL_Surface rather than xpaint Image structure
|
||||
Define SDL versions of RWSetMsg(), ImageNewCmap() and ImageSetCmap()
|
||||
*/
|
||||
#include "SDL.h"
|
||||
|
||||
#define Image SDL_Surface
|
||||
#define RWSetMsg IMG_SetError
|
||||
#define ImageNewCmap(w, h, s) SDL_CreateRGBSurface(SDL_SWSURFACE,w,h,8,0,0,0,0)
|
||||
#define ImageSetCmap(s, i, R, G, B) do { \
|
||||
s->format->palette->colors[i].r = R; \
|
||||
s->format->palette->colors[i].g = G; \
|
||||
s->format->palette->colors[i].b = B; \
|
||||
} while (0)
|
||||
/* * * * * */
|
||||
|
||||
#else
|
||||
|
||||
/* Original XPaint sources */
|
||||
|
||||
#include "image.h"
|
||||
#include "rwTable.h"
|
||||
|
||||
#define SDL_RWops FILE
|
||||
#define SDL_RWclose fclose
|
||||
|
||||
#endif /* USED_BY_SDL */
|
||||
|
||||
|
||||
#define MAXCOLORMAPSIZE 256
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define CM_RED 0
|
||||
#define CM_GREEN 1
|
||||
#define CM_BLUE 2
|
||||
|
||||
#define MAX_LWZ_BITS 12
|
||||
|
||||
#define INTERLACE 0x40
|
||||
#define LOCALCOLORMAP 0x80
|
||||
#define BitSet(byte, bit) (((byte) & (bit)) == (bit))
|
||||
|
||||
#define ReadOK(file,buffer,len) SDL_RWread(file, buffer, len, 1)
|
||||
|
||||
#define LM_to_uint(a,b) (((b)<<8)|(a))
|
||||
|
||||
static struct {
|
||||
unsigned int Width;
|
||||
unsigned int Height;
|
||||
unsigned char ColorMap[3][MAXCOLORMAPSIZE];
|
||||
unsigned int BitPixel;
|
||||
unsigned int ColorResolution;
|
||||
unsigned int Background;
|
||||
unsigned int AspectRatio;
|
||||
int GrayScale;
|
||||
} GifScreen;
|
||||
|
||||
static struct {
|
||||
int transparent;
|
||||
int delayTime;
|
||||
int inputFlag;
|
||||
int disposal;
|
||||
} Gif89;
|
||||
|
||||
static int ReadColorMap(SDL_RWops * src, int number,
|
||||
unsigned char buffer[3][MAXCOLORMAPSIZE], int *flag);
|
||||
static int DoExtension(SDL_RWops * src, int label);
|
||||
static int GetDataBlock(SDL_RWops * src, unsigned char *buf);
|
||||
static int GetCode(SDL_RWops * src, int code_size, int flag);
|
||||
static int LWZReadByte(SDL_RWops * src, int flag, int input_code_size);
|
||||
static Image *ReadImage(SDL_RWops * src, int len, int height, int,
|
||||
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
||||
int gray, int interlace, int ignore);
|
||||
|
||||
Image *
|
||||
IMG_LoadGIF_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
unsigned char buf[16];
|
||||
unsigned char c;
|
||||
unsigned char localColorMap[3][MAXCOLORMAPSIZE];
|
||||
int grayScale;
|
||||
int useGlobalColormap;
|
||||
int bitPixel;
|
||||
int imageCount = 0;
|
||||
char version[4];
|
||||
int imageNumber = 1;
|
||||
Image *image = NULL;
|
||||
|
||||
if ( src == NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if (!ReadOK(src, buf, 6)) {
|
||||
RWSetMsg("error reading magic number");
|
||||
goto done;
|
||||
}
|
||||
if (SDL_strncmp((char *) buf, "GIF", 3) != 0) {
|
||||
RWSetMsg("not a GIF file");
|
||||
goto done;
|
||||
}
|
||||
SDL_memcpy(version, (char *) buf + 3, 3);
|
||||
version[3] = '\0';
|
||||
|
||||
if ((SDL_strcmp(version, "87a") != 0) && (SDL_strcmp(version, "89a") != 0)) {
|
||||
RWSetMsg("bad version number, not '87a' or '89a'");
|
||||
goto done;
|
||||
}
|
||||
Gif89.transparent = -1;
|
||||
Gif89.delayTime = -1;
|
||||
Gif89.inputFlag = -1;
|
||||
Gif89.disposal = 0;
|
||||
|
||||
if (!ReadOK(src, buf, 7)) {
|
||||
RWSetMsg("failed to read screen descriptor");
|
||||
goto done;
|
||||
}
|
||||
GifScreen.Width = LM_to_uint(buf[0], buf[1]);
|
||||
GifScreen.Height = LM_to_uint(buf[2], buf[3]);
|
||||
GifScreen.BitPixel = 2 << (buf[4] & 0x07);
|
||||
GifScreen.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
|
||||
GifScreen.Background = buf[5];
|
||||
GifScreen.AspectRatio = buf[6];
|
||||
|
||||
if (BitSet(buf[4], LOCALCOLORMAP)) { /* Global Colormap */
|
||||
if (ReadColorMap(src, GifScreen.BitPixel, GifScreen.ColorMap,
|
||||
&GifScreen.GrayScale)) {
|
||||
RWSetMsg("error reading global colormap");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
do {
|
||||
if (!ReadOK(src, &c, 1)) {
|
||||
RWSetMsg("EOF / read error on image data");
|
||||
goto done;
|
||||
}
|
||||
if (c == ';') { /* GIF terminator */
|
||||
if (imageCount < imageNumber) {
|
||||
RWSetMsg("only %d image%s found in file",
|
||||
imageCount, imageCount > 1 ? "s" : "");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (c == '!') { /* Extension */
|
||||
if (!ReadOK(src, &c, 1)) {
|
||||
RWSetMsg("EOF / read error on extention function code");
|
||||
goto done;
|
||||
}
|
||||
DoExtension(src, c);
|
||||
continue;
|
||||
}
|
||||
if (c != ',') { /* Not a valid start character */
|
||||
continue;
|
||||
}
|
||||
++imageCount;
|
||||
|
||||
if (!ReadOK(src, buf, 9)) {
|
||||
RWSetMsg("couldn't read left/top/width/height");
|
||||
goto done;
|
||||
}
|
||||
useGlobalColormap = !BitSet(buf[8], LOCALCOLORMAP);
|
||||
|
||||
bitPixel = 1 << ((buf[8] & 0x07) + 1);
|
||||
|
||||
if (!useGlobalColormap) {
|
||||
if (ReadColorMap(src, bitPixel, localColorMap, &grayScale)) {
|
||||
RWSetMsg("error reading local colormap");
|
||||
goto done;
|
||||
}
|
||||
image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
|
||||
LM_to_uint(buf[6], buf[7]),
|
||||
bitPixel, localColorMap, grayScale,
|
||||
BitSet(buf[8], INTERLACE),
|
||||
imageCount != imageNumber);
|
||||
} else {
|
||||
image = ReadImage(src, LM_to_uint(buf[4], buf[5]),
|
||||
LM_to_uint(buf[6], buf[7]),
|
||||
GifScreen.BitPixel, GifScreen.ColorMap,
|
||||
GifScreen.GrayScale, BitSet(buf[8], INTERLACE),
|
||||
imageCount != imageNumber);
|
||||
}
|
||||
} while (image == NULL);
|
||||
|
||||
#ifdef USED_BY_SDL
|
||||
if ( Gif89.transparent >= 0 ) {
|
||||
SDL_SetColorKey(image, SDL_TRUE, Gif89.transparent);
|
||||
}
|
||||
#endif
|
||||
|
||||
done:
|
||||
if ( image == NULL ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
static int
|
||||
ReadColorMap(SDL_RWops *src, int number,
|
||||
unsigned char buffer[3][MAXCOLORMAPSIZE], int *gray)
|
||||
{
|
||||
int i;
|
||||
unsigned char rgb[3];
|
||||
int flag;
|
||||
|
||||
flag = TRUE;
|
||||
|
||||
for (i = 0; i < number; ++i) {
|
||||
if (!ReadOK(src, rgb, sizeof(rgb))) {
|
||||
RWSetMsg("bad colormap");
|
||||
return 1;
|
||||
}
|
||||
buffer[CM_RED][i] = rgb[0];
|
||||
buffer[CM_GREEN][i] = rgb[1];
|
||||
buffer[CM_BLUE][i] = rgb[2];
|
||||
flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (flag)
|
||||
*gray = (number == 2) ? PBM_TYPE : PGM_TYPE;
|
||||
else
|
||||
*gray = PPM_TYPE;
|
||||
#else
|
||||
*gray = 0;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int
|
||||
DoExtension(SDL_RWops *src, int label)
|
||||
{
|
||||
static unsigned char buf[256];
|
||||
char *str;
|
||||
|
||||
switch (label) {
|
||||
case 0x01: /* Plain Text Extension */
|
||||
str = "Plain Text Extension";
|
||||
break;
|
||||
case 0xff: /* Application Extension */
|
||||
str = "Application Extension";
|
||||
break;
|
||||
case 0xfe: /* Comment Extension */
|
||||
str = "Comment Extension";
|
||||
while (GetDataBlock(src, (unsigned char *) buf) != 0)
|
||||
;
|
||||
return FALSE;
|
||||
case 0xf9: /* Graphic Control Extension */
|
||||
str = "Graphic Control Extension";
|
||||
(void) GetDataBlock(src, (unsigned char *) buf);
|
||||
Gif89.disposal = (buf[0] >> 2) & 0x7;
|
||||
Gif89.inputFlag = (buf[0] >> 1) & 0x1;
|
||||
Gif89.delayTime = LM_to_uint(buf[1], buf[2]);
|
||||
if ((buf[0] & 0x1) != 0)
|
||||
Gif89.transparent = buf[3];
|
||||
|
||||
while (GetDataBlock(src, (unsigned char *) buf) != 0)
|
||||
;
|
||||
return FALSE;
|
||||
default:
|
||||
str = (char *)buf;
|
||||
SDL_snprintf(str, 256, "UNKNOWN (0x%02x)", label);
|
||||
break;
|
||||
}
|
||||
|
||||
while (GetDataBlock(src, (unsigned char *) buf) != 0)
|
||||
;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int ZeroDataBlock = FALSE;
|
||||
|
||||
static int
|
||||
GetDataBlock(SDL_RWops *src, unsigned char *buf)
|
||||
{
|
||||
unsigned char count;
|
||||
|
||||
if (!ReadOK(src, &count, 1)) {
|
||||
/* pm_message("error in getting DataBlock size" ); */
|
||||
return -1;
|
||||
}
|
||||
ZeroDataBlock = count == 0;
|
||||
|
||||
if ((count != 0) && (!ReadOK(src, buf, count))) {
|
||||
/* pm_message("error in reading DataBlock" ); */
|
||||
return -1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
static int
|
||||
GetCode(SDL_RWops *src, int code_size, int flag)
|
||||
{
|
||||
static unsigned char buf[280];
|
||||
static int curbit, lastbit, done, last_byte;
|
||||
int i, j, ret;
|
||||
unsigned char count;
|
||||
|
||||
if (flag) {
|
||||
curbit = 0;
|
||||
lastbit = 0;
|
||||
done = FALSE;
|
||||
return 0;
|
||||
}
|
||||
if ((curbit + code_size) >= lastbit) {
|
||||
if (done) {
|
||||
if (curbit >= lastbit)
|
||||
RWSetMsg("ran off the end of my bits");
|
||||
return -1;
|
||||
}
|
||||
buf[0] = buf[last_byte - 2];
|
||||
buf[1] = buf[last_byte - 1];
|
||||
|
||||
if ((count = GetDataBlock(src, &buf[2])) == 0)
|
||||
done = TRUE;
|
||||
|
||||
last_byte = 2 + count;
|
||||
curbit = (curbit - lastbit) + 16;
|
||||
lastbit = (2 + count) * 8;
|
||||
}
|
||||
ret = 0;
|
||||
for (i = curbit, j = 0; j < code_size; ++i, ++j)
|
||||
ret |= ((buf[i / 8] & (1 << (i % 8))) != 0) << j;
|
||||
|
||||
curbit += code_size;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
LWZReadByte(SDL_RWops *src, int flag, int input_code_size)
|
||||
{
|
||||
static int fresh = FALSE;
|
||||
int code, incode;
|
||||
static int code_size, set_code_size;
|
||||
static int max_code, max_code_size;
|
||||
static int firstcode, oldcode;
|
||||
static int clear_code, end_code;
|
||||
static int table[2][(1 << MAX_LWZ_BITS)];
|
||||
static int stack[(1 << (MAX_LWZ_BITS)) * 2], *sp;
|
||||
register int i;
|
||||
|
||||
/* Fixed buffer overflow found by Michael Skladnikiewicz */
|
||||
if (input_code_size > MAX_LWZ_BITS)
|
||||
return -1;
|
||||
|
||||
if (flag) {
|
||||
set_code_size = input_code_size;
|
||||
code_size = set_code_size + 1;
|
||||
clear_code = 1 << set_code_size;
|
||||
end_code = clear_code + 1;
|
||||
max_code_size = 2 * clear_code;
|
||||
max_code = clear_code + 2;
|
||||
|
||||
GetCode(src, 0, TRUE);
|
||||
|
||||
fresh = TRUE;
|
||||
|
||||
for (i = 0; i < clear_code; ++i) {
|
||||
table[0][i] = 0;
|
||||
table[1][i] = i;
|
||||
}
|
||||
table[1][0] = 0;
|
||||
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
||||
table[0][i] = 0;
|
||||
|
||||
sp = stack;
|
||||
|
||||
return 0;
|
||||
} else if (fresh) {
|
||||
fresh = FALSE;
|
||||
do {
|
||||
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
||||
} while (firstcode == clear_code);
|
||||
return firstcode;
|
||||
}
|
||||
if (sp > stack)
|
||||
return *--sp;
|
||||
|
||||
while ((code = GetCode(src, code_size, FALSE)) >= 0) {
|
||||
if (code == clear_code) {
|
||||
for (i = 0; i < clear_code; ++i) {
|
||||
table[0][i] = 0;
|
||||
table[1][i] = i;
|
||||
}
|
||||
for (; i < (1 << MAX_LWZ_BITS); ++i)
|
||||
table[0][i] = table[1][i] = 0;
|
||||
code_size = set_code_size + 1;
|
||||
max_code_size = 2 * clear_code;
|
||||
max_code = clear_code + 2;
|
||||
sp = stack;
|
||||
firstcode = oldcode = GetCode(src, code_size, FALSE);
|
||||
return firstcode;
|
||||
} else if (code == end_code) {
|
||||
int count;
|
||||
unsigned char buf[260];
|
||||
|
||||
if (ZeroDataBlock)
|
||||
return -2;
|
||||
|
||||
while ((count = GetDataBlock(src, buf)) > 0)
|
||||
;
|
||||
|
||||
if (count != 0) {
|
||||
/*
|
||||
* pm_message("missing EOD in data stream (common occurence)");
|
||||
*/
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
incode = code;
|
||||
|
||||
if (code >= max_code) {
|
||||
*sp++ = firstcode;
|
||||
code = oldcode;
|
||||
}
|
||||
while (code >= clear_code) {
|
||||
/* Guard against buffer overruns */
|
||||
if (code < 0 || code >= (1 << MAX_LWZ_BITS)) {
|
||||
RWSetMsg("invalid LWZ data");
|
||||
return -3;
|
||||
}
|
||||
*sp++ = table[1][code];
|
||||
if (code == table[0][code])
|
||||
RWSetMsg("circular table entry BIG ERROR");
|
||||
code = table[0][code];
|
||||
}
|
||||
|
||||
/* Guard against buffer overruns */
|
||||
if (code < 0 || code >= (1 << MAX_LWZ_BITS)) {
|
||||
RWSetMsg("invalid LWZ data");
|
||||
return -4;
|
||||
}
|
||||
*sp++ = firstcode = table[1][code];
|
||||
|
||||
if ((code = max_code) < (1 << MAX_LWZ_BITS)) {
|
||||
table[0][code] = oldcode;
|
||||
table[1][code] = firstcode;
|
||||
++max_code;
|
||||
if ((max_code >= max_code_size) &&
|
||||
(max_code_size < (1 << MAX_LWZ_BITS))) {
|
||||
max_code_size *= 2;
|
||||
++code_size;
|
||||
}
|
||||
}
|
||||
oldcode = incode;
|
||||
|
||||
if (sp > stack)
|
||||
return *--sp;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
static Image *
|
||||
ReadImage(SDL_RWops * src, int len, int height, int cmapSize,
|
||||
unsigned char cmap[3][MAXCOLORMAPSIZE],
|
||||
int gray, int interlace, int ignore)
|
||||
{
|
||||
Image *image;
|
||||
unsigned char c;
|
||||
int i, v;
|
||||
int xpos = 0, ypos = 0, pass = 0;
|
||||
|
||||
/*
|
||||
** Initialize the compression routines
|
||||
*/
|
||||
if (!ReadOK(src, &c, 1)) {
|
||||
RWSetMsg("EOF / read error on image data");
|
||||
return NULL;
|
||||
}
|
||||
if (LWZReadByte(src, TRUE, c) < 0) {
|
||||
RWSetMsg("error reading image");
|
||||
return NULL;
|
||||
}
|
||||
/*
|
||||
** If this is an "uninteresting picture" ignore it.
|
||||
*/
|
||||
if (ignore) {
|
||||
while (LWZReadByte(src, FALSE, c) >= 0)
|
||||
;
|
||||
return NULL;
|
||||
}
|
||||
image = ImageNewCmap(len, height, cmapSize);
|
||||
|
||||
for (i = 0; i < cmapSize; i++)
|
||||
ImageSetCmap(image, i, cmap[CM_RED][i],
|
||||
cmap[CM_GREEN][i], cmap[CM_BLUE][i]);
|
||||
|
||||
while ((v = LWZReadByte(src, FALSE, c)) >= 0) {
|
||||
#ifdef USED_BY_SDL
|
||||
((Uint8 *)image->pixels)[xpos + ypos * image->pitch] = v;
|
||||
#else
|
||||
image->data[xpos + ypos * len] = v;
|
||||
#endif
|
||||
++xpos;
|
||||
if (xpos == len) {
|
||||
xpos = 0;
|
||||
if (interlace) {
|
||||
switch (pass) {
|
||||
case 0:
|
||||
case 1:
|
||||
ypos += 8;
|
||||
break;
|
||||
case 2:
|
||||
ypos += 4;
|
||||
break;
|
||||
case 3:
|
||||
ypos += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ypos >= height) {
|
||||
++pass;
|
||||
switch (pass) {
|
||||
case 1:
|
||||
ypos = 4;
|
||||
break;
|
||||
case 2:
|
||||
ypos = 2;
|
||||
break;
|
||||
case 3:
|
||||
ypos = 1;
|
||||
break;
|
||||
default:
|
||||
goto fini;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
++ypos;
|
||||
}
|
||||
}
|
||||
if (ypos >= height)
|
||||
break;
|
||||
}
|
||||
|
||||
fini:
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isGIF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a GIF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadGIF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_GIF */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
@@ -0,0 +1,495 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a JPEG image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_JPG
|
||||
|
||||
#include <jpeglib.h>
|
||||
|
||||
#ifdef JPEG_TRUE /* MinGW version of jpeg-8.x renamed TRUE to JPEG_TRUE etc. */
|
||||
typedef JPEG_boolean boolean;
|
||||
#define TRUE JPEG_TRUE
|
||||
#define FALSE JPEG_FALSE
|
||||
#endif
|
||||
|
||||
/* Define this for fast loading and not as good image quality */
|
||||
/*#define FAST_JPEG*/
|
||||
|
||||
/* Define this for quicker (but less perfect) JPEG identification */
|
||||
#define FAST_IS_JPEG
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
void (*jpeg_calc_output_dimensions) (j_decompress_ptr cinfo);
|
||||
void (*jpeg_CreateDecompress) (j_decompress_ptr cinfo, int version, size_t structsize);
|
||||
void (*jpeg_destroy_decompress) (j_decompress_ptr cinfo);
|
||||
boolean (*jpeg_finish_decompress) (j_decompress_ptr cinfo);
|
||||
int (*jpeg_read_header) (j_decompress_ptr cinfo, boolean require_image);
|
||||
JDIMENSION (*jpeg_read_scanlines) (j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines);
|
||||
boolean (*jpeg_resync_to_restart) (j_decompress_ptr cinfo, int desired);
|
||||
boolean (*jpeg_start_decompress) (j_decompress_ptr cinfo);
|
||||
struct jpeg_error_mgr * (*jpeg_std_error) (struct jpeg_error_mgr * err);
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_JPG_DYNAMIC
|
||||
int IMG_InitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_JPG_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_calc_output_dimensions =
|
||||
(void (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_calc_output_dimensions");
|
||||
if ( lib.jpeg_calc_output_dimensions == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_CreateDecompress =
|
||||
(void (*) (j_decompress_ptr, int, size_t))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_CreateDecompress");
|
||||
if ( lib.jpeg_CreateDecompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_destroy_decompress =
|
||||
(void (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_destroy_decompress");
|
||||
if ( lib.jpeg_destroy_decompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_finish_decompress =
|
||||
(boolean (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_finish_decompress");
|
||||
if ( lib.jpeg_finish_decompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_read_header =
|
||||
(int (*) (j_decompress_ptr, boolean))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_read_header");
|
||||
if ( lib.jpeg_read_header == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_read_scanlines =
|
||||
(JDIMENSION (*) (j_decompress_ptr, JSAMPARRAY, JDIMENSION))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_read_scanlines");
|
||||
if ( lib.jpeg_read_scanlines == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_resync_to_restart =
|
||||
(boolean (*) (j_decompress_ptr, int))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_resync_to_restart");
|
||||
if ( lib.jpeg_resync_to_restart == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_start_decompress =
|
||||
(boolean (*) (j_decompress_ptr))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_start_decompress");
|
||||
if ( lib.jpeg_start_decompress == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.jpeg_std_error =
|
||||
(struct jpeg_error_mgr * (*) (struct jpeg_error_mgr *))
|
||||
SDL_LoadFunction(lib.handle, "jpeg_std_error");
|
||||
if ( lib.jpeg_std_error == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.jpeg_calc_output_dimensions = jpeg_calc_output_dimensions;
|
||||
lib.jpeg_CreateDecompress = jpeg_CreateDecompress;
|
||||
lib.jpeg_destroy_decompress = jpeg_destroy_decompress;
|
||||
lib.jpeg_finish_decompress = jpeg_finish_decompress;
|
||||
lib.jpeg_read_header = jpeg_read_header;
|
||||
lib.jpeg_read_scanlines = jpeg_read_scanlines;
|
||||
lib.jpeg_resync_to_restart = jpeg_resync_to_restart;
|
||||
lib.jpeg_start_decompress = jpeg_start_decompress;
|
||||
lib.jpeg_std_error = jpeg_std_error;
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitJPG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_JPG_DYNAMIC */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isJPG(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_JPG;
|
||||
int in_scan;
|
||||
Uint8 magic[4];
|
||||
|
||||
/* This detection code is by Steaphan Greene <stea@cs.binghamton.edu> */
|
||||
/* Blame me, not Sam, if this doesn't work right. */
|
||||
/* And don't forget to report the problem to the the sdl list too! */
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_JPG = 0;
|
||||
in_scan = 0;
|
||||
if ( SDL_RWread(src, magic, 2, 1) ) {
|
||||
if ( (magic[0] == 0xFF) && (magic[1] == 0xD8) ) {
|
||||
is_JPG = 1;
|
||||
while (is_JPG == 1) {
|
||||
if(SDL_RWread(src, magic, 1, 2) != 2) {
|
||||
is_JPG = 0;
|
||||
} else if( (magic[0] != 0xFF) && (in_scan == 0) ) {
|
||||
is_JPG = 0;
|
||||
} else if( (magic[0] != 0xFF) || (magic[1] == 0xFF) ) {
|
||||
/* Extra padding in JPEG (legal) */
|
||||
/* or this is data and we are scanning */
|
||||
SDL_RWseek(src, -1, RW_SEEK_CUR);
|
||||
} else if(magic[1] == 0xD9) {
|
||||
/* Got to end of good JPEG */
|
||||
break;
|
||||
} else if( (in_scan == 1) && (magic[1] == 0x00) ) {
|
||||
/* This is an encoded 0xFF within the data */
|
||||
} else if( (magic[1] >= 0xD0) && (magic[1] < 0xD9) ) {
|
||||
/* These have nothing else */
|
||||
} else if(SDL_RWread(src, magic+2, 1, 2) != 2) {
|
||||
is_JPG = 0;
|
||||
} else {
|
||||
/* Yes, it's big-endian */
|
||||
Sint64 innerStart;
|
||||
Uint32 size;
|
||||
Sint64 end;
|
||||
innerStart = SDL_RWtell(src);
|
||||
size = (magic[2] << 8) + magic[3];
|
||||
end = SDL_RWseek(src, size-2, RW_SEEK_CUR);
|
||||
if ( end != innerStart + size - 2 ) is_JPG = 0;
|
||||
if ( magic[1] == 0xDA ) {
|
||||
/* Now comes the actual JPEG meat */
|
||||
#ifdef FAST_IS_JPEG
|
||||
/* Ok, I'm convinced. It is a JPEG. */
|
||||
break;
|
||||
#else
|
||||
/* I'm not convinced. Prove it! */
|
||||
in_scan = 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_JPG);
|
||||
}
|
||||
|
||||
#define INPUT_BUFFER_SIZE 4096
|
||||
typedef struct {
|
||||
struct jpeg_source_mgr pub;
|
||||
|
||||
SDL_RWops *ctx;
|
||||
Uint8 buffer[INPUT_BUFFER_SIZE];
|
||||
} my_source_mgr;
|
||||
|
||||
/*
|
||||
* Initialize source --- called by jpeg_read_header
|
||||
* before any data is actually read.
|
||||
*/
|
||||
static void init_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* We don't actually need to do anything */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the input buffer --- called whenever buffer is emptied.
|
||||
*/
|
||||
static boolean fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
my_source_mgr * src = (my_source_mgr *) cinfo->src;
|
||||
int nbytes;
|
||||
|
||||
nbytes = SDL_RWread(src->ctx, src->buffer, 1, INPUT_BUFFER_SIZE);
|
||||
if (nbytes <= 0) {
|
||||
/* Insert a fake EOI marker */
|
||||
src->buffer[0] = (Uint8) 0xFF;
|
||||
src->buffer[1] = (Uint8) JPEG_EOI;
|
||||
nbytes = 2;
|
||||
}
|
||||
src->pub.next_input_byte = src->buffer;
|
||||
src->pub.bytes_in_buffer = nbytes;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Skip data --- used to skip over a potentially large amount of
|
||||
* uninteresting data (such as an APPn marker).
|
||||
*
|
||||
* Writers of suspendable-input applications must note that skip_input_data
|
||||
* is not granted the right to give a suspension return. If the skip extends
|
||||
* beyond the data currently in the buffer, the buffer can be marked empty so
|
||||
* that the next read will cause a fill_input_buffer call that can suspend.
|
||||
* Arranging for additional bytes to be discarded before reloading the input
|
||||
* buffer is the application writer's problem.
|
||||
*/
|
||||
static void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
|
||||
{
|
||||
my_source_mgr * src = (my_source_mgr *) cinfo->src;
|
||||
|
||||
/* Just a dumb implementation for now. Could use fseek() except
|
||||
* it doesn't work on pipes. Not clear that being smart is worth
|
||||
* any trouble anyway --- large skips are infrequent.
|
||||
*/
|
||||
if (num_bytes > 0) {
|
||||
while (num_bytes > (long) src->pub.bytes_in_buffer) {
|
||||
num_bytes -= (long) src->pub.bytes_in_buffer;
|
||||
(void) src->pub.fill_input_buffer(cinfo);
|
||||
/* note we assume that fill_input_buffer will never
|
||||
* return FALSE, so suspension need not be handled.
|
||||
*/
|
||||
}
|
||||
src->pub.next_input_byte += (size_t) num_bytes;
|
||||
src->pub.bytes_in_buffer -= (size_t) num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Terminate source --- called by jpeg_finish_decompress
|
||||
* after all data has been read.
|
||||
*/
|
||||
static void term_source (j_decompress_ptr cinfo)
|
||||
{
|
||||
/* We don't actually need to do anything */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prepare for input from a stdio stream.
|
||||
* The caller must have already opened the stream, and is responsible
|
||||
* for closing it after finishing decompression.
|
||||
*/
|
||||
static void jpeg_SDL_RW_src (j_decompress_ptr cinfo, SDL_RWops *ctx)
|
||||
{
|
||||
my_source_mgr *src;
|
||||
|
||||
/* The source object and input buffer are made permanent so that a series
|
||||
* of JPEG images can be read from the same file by calling jpeg_stdio_src
|
||||
* only before the first one. (If we discarded the buffer at the end of
|
||||
* one image, we'd likely lose the start of the next one.)
|
||||
* This makes it unsafe to use this manager and a different source
|
||||
* manager serially with the same JPEG object. Caveat programmer.
|
||||
*/
|
||||
if (cinfo->src == NULL) { /* first time for this JPEG object? */
|
||||
cinfo->src = (struct jpeg_source_mgr *)
|
||||
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
|
||||
sizeof(my_source_mgr));
|
||||
src = (my_source_mgr *) cinfo->src;
|
||||
}
|
||||
|
||||
src = (my_source_mgr *) cinfo->src;
|
||||
src->pub.init_source = init_source;
|
||||
src->pub.fill_input_buffer = fill_input_buffer;
|
||||
src->pub.skip_input_data = skip_input_data;
|
||||
src->pub.resync_to_restart = lib.jpeg_resync_to_restart; /* use default method */
|
||||
src->pub.term_source = term_source;
|
||||
src->ctx = ctx;
|
||||
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
|
||||
src->pub.next_input_byte = NULL; /* until buffer loaded */
|
||||
}
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr errmgr;
|
||||
jmp_buf escape;
|
||||
};
|
||||
|
||||
static void my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
struct my_error_mgr *err = (struct my_error_mgr *)cinfo->err;
|
||||
longjmp(err->escape, 1);
|
||||
}
|
||||
|
||||
static void output_no_message(j_common_ptr cinfo)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/* Load a JPEG type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
JSAMPROW rowptr[1];
|
||||
SDL_Surface *volatile surface = NULL;
|
||||
struct my_error_mgr jerr;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_JPG) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create a decompression structure and load the JPEG header */
|
||||
cinfo.err = lib.jpeg_std_error(&jerr.errmgr);
|
||||
jerr.errmgr.error_exit = my_error_exit;
|
||||
jerr.errmgr.output_message = output_no_message;
|
||||
if(setjmp(jerr.escape)) {
|
||||
/* If we get here, libjpeg found an error */
|
||||
lib.jpeg_destroy_decompress(&cinfo);
|
||||
if ( surface != NULL ) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
IMG_SetError("JPEG loading error");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lib.jpeg_create_decompress(&cinfo);
|
||||
jpeg_SDL_RW_src(&cinfo, src);
|
||||
lib.jpeg_read_header(&cinfo, TRUE);
|
||||
|
||||
if(cinfo.num_components == 4) {
|
||||
/* Set 32-bit Raw output */
|
||||
cinfo.out_color_space = JCS_CMYK;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
lib.jpeg_calc_output_dimensions(&cinfo);
|
||||
|
||||
/* Allocate an output surface to hold the image */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
cinfo.output_width, cinfo.output_height, 32,
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
|
||||
#else
|
||||
0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF);
|
||||
#endif
|
||||
} else {
|
||||
/* Set 24-bit RGB output */
|
||||
cinfo.out_color_space = JCS_RGB;
|
||||
cinfo.quantize_colors = FALSE;
|
||||
#ifdef FAST_JPEG
|
||||
cinfo.scale_num = 1;
|
||||
cinfo.scale_denom = 1;
|
||||
cinfo.dct_method = JDCT_FASTEST;
|
||||
cinfo.do_fancy_upsampling = FALSE;
|
||||
#endif
|
||||
lib.jpeg_calc_output_dimensions(&cinfo);
|
||||
|
||||
/* Allocate an output surface to hold the image */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
cinfo.output_width, cinfo.output_height, 24,
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
0x0000FF, 0x00FF00, 0xFF0000,
|
||||
#else
|
||||
0xFF0000, 0x00FF00, 0x0000FF,
|
||||
#endif
|
||||
0);
|
||||
}
|
||||
|
||||
if ( surface == NULL ) {
|
||||
lib.jpeg_destroy_decompress(&cinfo);
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
IMG_SetError("Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Decompress the image */
|
||||
lib.jpeg_start_decompress(&cinfo);
|
||||
while ( cinfo.output_scanline < cinfo.output_height ) {
|
||||
rowptr[0] = (JSAMPROW)(Uint8 *)surface->pixels +
|
||||
cinfo.output_scanline * surface->pitch;
|
||||
lib.jpeg_read_scanlines(&cinfo, rowptr, (JDIMENSION) 1);
|
||||
}
|
||||
lib.jpeg_finish_decompress(&cinfo);
|
||||
lib.jpeg_destroy_decompress(&cinfo);
|
||||
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitJPG()
|
||||
{
|
||||
IMG_SetError("JPEG images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitJPG()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isJPG(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a JPEG type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadJPG_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_JPG */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a ILBM image file loading framework
|
||||
Load IFF pictures, PBM & ILBM packing methods, with or without stencil
|
||||
Written by Daniel Morais ( Daniel AT Morais DOT com ) in September 2001.
|
||||
24 bits ILBM files support added by Marc Le Douarain (http://www.multimania.com/mavati)
|
||||
in December 2002.
|
||||
EHB and HAM (specific Amiga graphic chip modes) support added by Marc Le Douarain
|
||||
(http://www.multimania.com/mavati) in December 2003.
|
||||
Stencil and colorkey fixes by David Raulo (david.raulo AT free DOT fr) in February 2004.
|
||||
Buffer overflow fix in RLE decompression by David Raulo in January 2008.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_LBM
|
||||
|
||||
|
||||
#define MAXCOLORS 256
|
||||
|
||||
/* Structure for an IFF picture ( BMHD = Bitmap Header ) */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Uint16 w, h; /* width & height of the bitmap in pixels */
|
||||
Sint16 x, y; /* screen coordinates of the bitmap */
|
||||
Uint8 planes; /* number of planes of the bitmap */
|
||||
Uint8 mask; /* mask type ( 0 => no mask ) */
|
||||
Uint8 tcomp; /* compression type */
|
||||
Uint8 pad1; /* dummy value, for padding */
|
||||
Uint16 tcolor; /* transparent color */
|
||||
Uint8 xAspect, /* pixel aspect ratio */
|
||||
yAspect;
|
||||
Sint16 Lpage; /* width of the screen in pixels */
|
||||
Sint16 Hpage; /* height of the screen in pixels */
|
||||
} BMHD;
|
||||
|
||||
int IMG_isLBM( SDL_RWops *src )
|
||||
{
|
||||
Sint64 start;
|
||||
int is_LBM;
|
||||
Uint8 magic[4+4+4];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_LBM = 0;
|
||||
if ( SDL_RWread( src, magic, sizeof(magic), 1 ) )
|
||||
{
|
||||
if ( !SDL_memcmp( magic, "FORM", 4 ) &&
|
||||
( !SDL_memcmp( magic + 8, "PBM ", 4 ) ||
|
||||
!SDL_memcmp( magic + 8, "ILBM", 4 ) ) )
|
||||
{
|
||||
is_LBM = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return( is_LBM );
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadLBM_RW( SDL_RWops *src )
|
||||
{
|
||||
Sint64 start;
|
||||
SDL_Surface *Image;
|
||||
Uint8 id[4], pbm, colormap[MAXCOLORS*3], *MiniBuf, *ptr, count, color, msk;
|
||||
Uint32 size, bytesloaded, nbcolors;
|
||||
Uint32 i, j, bytesperline, nbplanes, stencil, plane, h;
|
||||
Uint32 remainingbytes;
|
||||
Uint32 width;
|
||||
BMHD bmhd;
|
||||
char *error;
|
||||
Uint8 flagHAM,flagEHB;
|
||||
|
||||
Image = NULL;
|
||||
error = NULL;
|
||||
MiniBuf = NULL;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !SDL_RWread( src, id, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Should be the size of the file minus 4+4 ( 'FORM'+size ) */
|
||||
if ( !SDL_RWread( src, &size, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk size";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* As size is not used here, no need to swap it */
|
||||
|
||||
if ( SDL_memcmp( id, "FORM", 4 ) != 0 )
|
||||
{
|
||||
error="not a IFF file";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !SDL_RWread( src, id, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
pbm = 0;
|
||||
|
||||
/* File format : PBM=Packed Bitmap, ILBM=Interleaved Bitmap */
|
||||
if ( !SDL_memcmp( id, "PBM ", 4 ) ) pbm = 1;
|
||||
else if ( SDL_memcmp( id, "ILBM", 4 ) )
|
||||
{
|
||||
error="not a IFF picture";
|
||||
goto done;
|
||||
}
|
||||
|
||||
nbcolors = 0;
|
||||
|
||||
SDL_memset( &bmhd, 0, sizeof( BMHD ) );
|
||||
flagHAM = 0;
|
||||
flagEHB = 0;
|
||||
|
||||
while ( SDL_memcmp( id, "BODY", 4 ) != 0 )
|
||||
{
|
||||
if ( !SDL_RWread( src, id, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( !SDL_RWread( src, &size, 4, 1 ) )
|
||||
{
|
||||
error="error reading IFF chunk size";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = 0;
|
||||
|
||||
size = SDL_SwapBE32( size );
|
||||
|
||||
if ( !SDL_memcmp( id, "BMHD", 4 ) ) /* Bitmap header */
|
||||
{
|
||||
if ( !SDL_RWread( src, &bmhd, sizeof( BMHD ), 1 ) )
|
||||
{
|
||||
error="error reading BMHD chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = sizeof( BMHD );
|
||||
|
||||
bmhd.w = SDL_SwapBE16( bmhd.w );
|
||||
bmhd.h = SDL_SwapBE16( bmhd.h );
|
||||
bmhd.x = SDL_SwapBE16( bmhd.x );
|
||||
bmhd.y = SDL_SwapBE16( bmhd.y );
|
||||
bmhd.tcolor = SDL_SwapBE16( bmhd.tcolor );
|
||||
bmhd.Lpage = SDL_SwapBE16( bmhd.Lpage );
|
||||
bmhd.Hpage = SDL_SwapBE16( bmhd.Hpage );
|
||||
}
|
||||
|
||||
if ( !SDL_memcmp( id, "CMAP", 4 ) ) /* palette ( Color Map ) */
|
||||
{
|
||||
if ( !SDL_RWread( src, &colormap, size, 1 ) )
|
||||
{
|
||||
error="error reading CMAP chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = size;
|
||||
nbcolors = size / 3;
|
||||
}
|
||||
|
||||
if ( !SDL_memcmp( id, "CAMG", 4 ) ) /* Amiga ViewMode */
|
||||
{
|
||||
Uint32 viewmodes;
|
||||
if ( !SDL_RWread( src, &viewmodes, sizeof(viewmodes), 1 ) )
|
||||
{
|
||||
error="error reading CAMG chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
bytesloaded = size;
|
||||
viewmodes = SDL_SwapBE32( viewmodes );
|
||||
if ( viewmodes & 0x0800 )
|
||||
flagHAM = 1;
|
||||
if ( viewmodes & 0x0080 )
|
||||
flagEHB = 1;
|
||||
}
|
||||
|
||||
if ( SDL_memcmp( id, "BODY", 4 ) )
|
||||
{
|
||||
if ( size & 1 ) ++size; /* padding ! */
|
||||
size -= bytesloaded;
|
||||
/* skip the remaining bytes of this chunk */
|
||||
if ( size ) SDL_RWseek( src, size, RW_SEEK_CUR );
|
||||
}
|
||||
}
|
||||
|
||||
/* compute some usefull values, based on the bitmap header */
|
||||
|
||||
width = ( bmhd.w + 15 ) & 0xFFFFFFF0; /* Width in pixels modulo 16 */
|
||||
|
||||
bytesperline = ( ( bmhd.w + 15 ) / 16 ) * 2;
|
||||
|
||||
nbplanes = bmhd.planes;
|
||||
|
||||
if ( pbm ) /* File format : 'Packed Bitmap' */
|
||||
{
|
||||
bytesperline *= 8;
|
||||
nbplanes = 1;
|
||||
}
|
||||
|
||||
stencil = (bmhd.mask & 1); /* There is a mask ( 'stencil' ) */
|
||||
|
||||
/* Allocate memory for a temporary buffer ( used for
|
||||
decompression/deinterleaving ) */
|
||||
|
||||
MiniBuf = (Uint8 *)SDL_malloc( bytesperline * (nbplanes + stencil) );
|
||||
if ( MiniBuf == NULL )
|
||||
{
|
||||
error="no enough memory for temporary buffer";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( ( Image = SDL_CreateRGBSurface( SDL_SWSURFACE, width, bmhd.h, (bmhd.planes==24 || flagHAM==1)?24:8, 0, 0, 0, 0 ) ) == NULL )
|
||||
goto done;
|
||||
|
||||
if ( bmhd.mask & 2 ) /* There is a transparent color */
|
||||
SDL_SetColorKey( Image, SDL_TRUE, bmhd.tcolor );
|
||||
|
||||
/* Update palette informations */
|
||||
|
||||
/* There is no palette in 24 bits ILBM file */
|
||||
if ( nbcolors>0 && flagHAM==0 )
|
||||
{
|
||||
/* FIXME: Should this include the stencil? See comment below */
|
||||
int nbrcolorsfinal = 1 << (nbplanes + stencil);
|
||||
ptr = &colormap[0];
|
||||
|
||||
for ( i=0; i<nbcolors; i++ )
|
||||
{
|
||||
Image->format->palette->colors[i].r = *ptr++;
|
||||
Image->format->palette->colors[i].g = *ptr++;
|
||||
Image->format->palette->colors[i].b = *ptr++;
|
||||
}
|
||||
|
||||
/* Amiga EHB mode (Extra-Half-Bright) */
|
||||
/* 6 bitplanes mode with a 32 colors palette */
|
||||
/* The 32 last colors are the same but divided by 2 */
|
||||
/* Some Amiga pictures save 64 colors with 32 last wrong colors, */
|
||||
/* they shouldn't !, and here we overwrite these 32 bad colors. */
|
||||
if ( (nbcolors==32 || flagEHB ) && (1<<bmhd.planes)==64 )
|
||||
{
|
||||
nbcolors = 64;
|
||||
ptr = &colormap[0];
|
||||
for ( i=32; i<64; i++ )
|
||||
{
|
||||
Image->format->palette->colors[i].r = (*ptr++)/2;
|
||||
Image->format->palette->colors[i].g = (*ptr++)/2;
|
||||
Image->format->palette->colors[i].b = (*ptr++)/2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If nbcolors < 2^nbplanes, repeat the colormap */
|
||||
/* This happens when pictures have a stencil mask */
|
||||
if ( nbrcolorsfinal > (1<<bmhd.planes) ) {
|
||||
nbrcolorsfinal = (1<<bmhd.planes);
|
||||
}
|
||||
for ( i=nbcolors; i < (Uint32)nbrcolorsfinal; i++ )
|
||||
{
|
||||
Image->format->palette->colors[i].r = Image->format->palette->colors[i%nbcolors].r;
|
||||
Image->format->palette->colors[i].g = Image->format->palette->colors[i%nbcolors].g;
|
||||
Image->format->palette->colors[i].b = Image->format->palette->colors[i%nbcolors].b;
|
||||
}
|
||||
if ( !pbm )
|
||||
Image->format->palette->ncolors = nbrcolorsfinal;
|
||||
}
|
||||
|
||||
/* Get the bitmap */
|
||||
|
||||
for ( h=0; h < bmhd.h; h++ )
|
||||
{
|
||||
/* uncompress the datas of each planes */
|
||||
|
||||
for ( plane=0; plane < (nbplanes+stencil); plane++ )
|
||||
{
|
||||
ptr = MiniBuf + ( plane * bytesperline );
|
||||
|
||||
remainingbytes = bytesperline;
|
||||
|
||||
if ( bmhd.tcomp == 1 ) /* Datas are compressed */
|
||||
{
|
||||
do
|
||||
{
|
||||
if ( !SDL_RWread( src, &count, 1, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
|
||||
if ( count & 0x80 )
|
||||
{
|
||||
count ^= 0xFF;
|
||||
count += 2; /* now it */
|
||||
|
||||
if ( ( count > remainingbytes ) || !SDL_RWread( src, &color, 1, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
SDL_memset( ptr, color, count );
|
||||
}
|
||||
else
|
||||
{
|
||||
++count;
|
||||
|
||||
if ( ( count > remainingbytes ) || !SDL_RWread( src, ptr, count, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ptr += count;
|
||||
remainingbytes -= count;
|
||||
|
||||
} while ( remainingbytes > 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !SDL_RWread( src, ptr, bytesperline, 1 ) )
|
||||
{
|
||||
error="error reading BODY chunk";
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* One line has been read, store it ! */
|
||||
|
||||
ptr = (Uint8 *)Image->pixels;
|
||||
if ( nbplanes==24 || flagHAM==1 )
|
||||
ptr += h * width * 3;
|
||||
else
|
||||
ptr += h * width;
|
||||
|
||||
if ( pbm ) /* File format : 'Packed Bitmap' */
|
||||
{
|
||||
SDL_memcpy( ptr, MiniBuf, width );
|
||||
}
|
||||
else /* We have to un-interlace the bits ! */
|
||||
{
|
||||
if ( nbplanes!=24 && flagHAM==0 )
|
||||
{
|
||||
size = ( width + 7 ) / 8;
|
||||
|
||||
for ( i=0; i < size; i++ )
|
||||
{
|
||||
memset( ptr, 0, 8 );
|
||||
|
||||
for ( plane=0; plane < (nbplanes + stencil); plane++ )
|
||||
{
|
||||
color = *( MiniBuf + i + ( plane * bytesperline ) );
|
||||
msk = 0x80;
|
||||
|
||||
for ( j=0; j<8; j++ )
|
||||
{
|
||||
if ( ( plane + j ) <= 7 ) ptr[j] |= (Uint8)( color & msk ) >> ( 7 - plane - j );
|
||||
else ptr[j] |= (Uint8)( color & msk ) << ( plane + j - 7 );
|
||||
|
||||
msk >>= 1;
|
||||
}
|
||||
}
|
||||
ptr += 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Uint32 finalcolor = 0;
|
||||
size = ( width + 7 ) / 8;
|
||||
/* 24 bitplanes ILBM : R0...R7,G0...G7,B0...B7 */
|
||||
/* or HAM (6 bitplanes) or HAM8 (8 bitplanes) modes */
|
||||
for ( i=0; i<width; i=i+8 )
|
||||
{
|
||||
Uint8 maskBit = 0x80;
|
||||
for ( j=0; j<8; j++ )
|
||||
{
|
||||
Uint32 pixelcolor = 0;
|
||||
Uint32 maskColor = 1;
|
||||
Uint8 dataBody;
|
||||
for ( plane=0; plane < nbplanes; plane++ )
|
||||
{
|
||||
dataBody = MiniBuf[ plane*size+i/8 ];
|
||||
if ( dataBody&maskBit )
|
||||
pixelcolor = pixelcolor | maskColor;
|
||||
maskColor = maskColor<<1;
|
||||
}
|
||||
/* HAM : 12 bits RGB image (4 bits per color component) */
|
||||
/* HAM8 : 18 bits RGB image (6 bits per color component) */
|
||||
if ( flagHAM )
|
||||
{
|
||||
switch( pixelcolor>>(nbplanes-2) )
|
||||
{
|
||||
case 0: /* take direct color from palette */
|
||||
finalcolor = colormap[ pixelcolor*3 ] + (colormap[ pixelcolor*3+1 ]<<8) + (colormap[ pixelcolor*3+2 ]<<16);
|
||||
break;
|
||||
case 1: /* modify only blue component */
|
||||
finalcolor = finalcolor&0x00FFFF;
|
||||
finalcolor = finalcolor | (pixelcolor<<(16+(10-nbplanes)));
|
||||
break;
|
||||
case 2: /* modify only red component */
|
||||
finalcolor = finalcolor&0xFFFF00;
|
||||
finalcolor = finalcolor | pixelcolor<<(10-nbplanes);
|
||||
break;
|
||||
case 3: /* modify only green component */
|
||||
finalcolor = finalcolor&0xFF00FF;
|
||||
finalcolor = finalcolor | (pixelcolor<<(8+(10-nbplanes)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
finalcolor = pixelcolor;
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
*ptr++ = (Uint8)(finalcolor>>16);
|
||||
*ptr++ = (Uint8)(finalcolor>>8);
|
||||
*ptr++ = (Uint8)(finalcolor);
|
||||
#else
|
||||
*ptr++ = (Uint8)(finalcolor);
|
||||
*ptr++ = (Uint8)(finalcolor>>8);
|
||||
*ptr++ = (Uint8)(finalcolor>>16);
|
||||
#endif
|
||||
maskBit = maskBit>>1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if ( MiniBuf ) SDL_free( MiniBuf );
|
||||
|
||||
if ( error )
|
||||
{
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( Image ) {
|
||||
SDL_FreeSurface( Image );
|
||||
Image = NULL;
|
||||
}
|
||||
IMG_SetError( error );
|
||||
}
|
||||
|
||||
return( Image );
|
||||
}
|
||||
|
||||
#else /* LOAD_LBM */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isLBM(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load an IFF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadLBM_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_LBM */
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PCX file reader:
|
||||
* Supports:
|
||||
* 1..4 bits/pixel in multiplanar format (1 bit/plane/pixel)
|
||||
* 8 bits/pixel in single-planar format (8 bits/plane/pixel)
|
||||
* 24 bits/pixel in 3-plane format (8 bits/plane/pixel)
|
||||
*
|
||||
* (The <8bpp formats are expanded to 8bpp surfaces)
|
||||
*
|
||||
* Doesn't support:
|
||||
* single-planar packed-pixel formats other than 8bpp
|
||||
* 4-plane 32bpp format with a fourth "intensity" plane
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_PCX
|
||||
|
||||
struct PCXheader {
|
||||
Uint8 Manufacturer;
|
||||
Uint8 Version;
|
||||
Uint8 Encoding;
|
||||
Uint8 BitsPerPixel;
|
||||
Sint16 Xmin, Ymin, Xmax, Ymax;
|
||||
Sint16 HDpi, VDpi;
|
||||
Uint8 Colormap[48];
|
||||
Uint8 Reserved;
|
||||
Uint8 NPlanes;
|
||||
Sint16 BytesPerLine;
|
||||
Sint16 PaletteInfo;
|
||||
Sint16 HscreenSize;
|
||||
Sint16 VscreenSize;
|
||||
Uint8 Filler[54];
|
||||
};
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPCX(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_PCX;
|
||||
const int ZSoft_Manufacturer = 10;
|
||||
const int PC_Paintbrush_Version = 5;
|
||||
const int PCX_Uncompressed_Encoding = 0;
|
||||
const int PCX_RunLength_Encoding = 1;
|
||||
struct PCXheader pcxh;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_PCX = 0;
|
||||
if ( SDL_RWread(src, &pcxh, sizeof(pcxh), 1) == 1 ) {
|
||||
if ( (pcxh.Manufacturer == ZSoft_Manufacturer) &&
|
||||
(pcxh.Version == PC_Paintbrush_Version) &&
|
||||
(pcxh.Encoding == PCX_RunLength_Encoding ||
|
||||
pcxh.Encoding == PCX_Uncompressed_Encoding) ) {
|
||||
is_PCX = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_PCX);
|
||||
}
|
||||
|
||||
/* Load a PCX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
struct PCXheader pcxh;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
SDL_Surface *surface = NULL;
|
||||
int width, height;
|
||||
int y, bpl;
|
||||
Uint8 *row, *buf = NULL;
|
||||
char *error = NULL;
|
||||
int bits, src_bits;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( ! SDL_RWread(src, &pcxh, sizeof(pcxh), 1) ) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
pcxh.Xmin = SDL_SwapLE16(pcxh.Xmin);
|
||||
pcxh.Ymin = SDL_SwapLE16(pcxh.Ymin);
|
||||
pcxh.Xmax = SDL_SwapLE16(pcxh.Xmax);
|
||||
pcxh.Ymax = SDL_SwapLE16(pcxh.Ymax);
|
||||
pcxh.BytesPerLine = SDL_SwapLE16(pcxh.BytesPerLine);
|
||||
|
||||
/* Create the surface of the appropriate type */
|
||||
width = (pcxh.Xmax - pcxh.Xmin) + 1;
|
||||
height = (pcxh.Ymax - pcxh.Ymin) + 1;
|
||||
Rmask = Gmask = Bmask = Amask = 0;
|
||||
src_bits = pcxh.BitsPerPixel * pcxh.NPlanes;
|
||||
if((pcxh.BitsPerPixel == 1 && pcxh.NPlanes >= 1 && pcxh.NPlanes <= 4)
|
||||
|| (pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 1)) {
|
||||
bits = 8;
|
||||
} else if(pcxh.BitsPerPixel == 8 && pcxh.NPlanes == 3) {
|
||||
bits = 24;
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
#else
|
||||
Rmask = 0xFF0000;
|
||||
Gmask = 0x00FF00;
|
||||
Bmask = 0x0000FF;
|
||||
#endif
|
||||
} else {
|
||||
error = "unsupported PCX format";
|
||||
goto done;
|
||||
}
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
|
||||
bits, Rmask, Gmask, Bmask, Amask);
|
||||
if ( surface == NULL )
|
||||
goto done;
|
||||
|
||||
bpl = pcxh.NPlanes * pcxh.BytesPerLine;
|
||||
if (bpl > surface->pitch) {
|
||||
error = "bytes per line is too large (corrupt?)";
|
||||
}
|
||||
buf = (Uint8 *)SDL_malloc(bpl);
|
||||
row = (Uint8 *)surface->pixels;
|
||||
for ( y=0; y<surface->h; ++y ) {
|
||||
/* decode a scan line to a temporary buffer first */
|
||||
int i, count = 0;
|
||||
Uint8 ch;
|
||||
Uint8 *dst = (src_bits == 8) ? row : buf;
|
||||
if ( pcxh.Encoding == 0 ) {
|
||||
if(!SDL_RWread(src, dst, bpl, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < bpl; i++) {
|
||||
if(!count) {
|
||||
if(!SDL_RWread(src, &ch, 1, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
if( (ch & 0xc0) == 0xc0) {
|
||||
count = ch & 0x3f;
|
||||
if(!SDL_RWread(src, &ch, 1, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
} else
|
||||
count = 1;
|
||||
}
|
||||
dst[i] = ch;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
if(src_bits <= 4) {
|
||||
/* expand planes to 1 byte/pixel */
|
||||
Uint8 *innerSrc = buf;
|
||||
int plane;
|
||||
for(plane = 0; plane < pcxh.NPlanes; plane++) {
|
||||
int j, k, x = 0;
|
||||
for(j = 0; j < pcxh.BytesPerLine; j++) {
|
||||
Uint8 byte = *innerSrc++;
|
||||
for(k = 7; k >= 0; k--) {
|
||||
unsigned bit = (byte >> k) & 1;
|
||||
/* skip padding bits */
|
||||
if (j * 8 + k >= width)
|
||||
continue;
|
||||
row[x++] |= bit << plane;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(src_bits == 24) {
|
||||
/* de-interlace planes */
|
||||
Uint8 *innerSrc = buf;
|
||||
int plane;
|
||||
for(plane = 0; plane < pcxh.NPlanes; plane++) {
|
||||
int x;
|
||||
dst = row + plane;
|
||||
for(x = 0; x < width; x++) {
|
||||
*dst = *innerSrc++;
|
||||
dst += pcxh.NPlanes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
row += surface->pitch;
|
||||
}
|
||||
|
||||
if(bits == 8) {
|
||||
SDL_Color *colors = surface->format->palette->colors;
|
||||
int nc = 1 << src_bits;
|
||||
int i;
|
||||
|
||||
surface->format->palette->ncolors = nc;
|
||||
if(src_bits == 8) {
|
||||
Uint8 ch;
|
||||
/* look for a 256-colour palette */
|
||||
do {
|
||||
if ( !SDL_RWread(src, &ch, 1, 1)) {
|
||||
error = "file truncated";
|
||||
goto done;
|
||||
}
|
||||
} while ( ch != 12 );
|
||||
|
||||
for(i = 0; i < 256; i++) {
|
||||
SDL_RWread(src, &colors[i].r, 1, 1);
|
||||
SDL_RWread(src, &colors[i].g, 1, 1);
|
||||
SDL_RWread(src, &colors[i].b, 1, 1);
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < nc; i++) {
|
||||
colors[i].r = pcxh.Colormap[i * 3];
|
||||
colors[i].g = pcxh.Colormap[i * 3 + 1];
|
||||
colors[i].b = pcxh.Colormap[i * 3 + 2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
SDL_free(buf);
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPCX(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a PCX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPCX_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_PCX */
|
||||
@@ -0,0 +1,646 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a PNG image file loading framework */
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
#ifdef LOAD_PNG
|
||||
|
||||
/*=============================================================================
|
||||
File: SDL_png.c
|
||||
Purpose: A PNG loader and saver for the SDL library
|
||||
Revision:
|
||||
Created by: Philippe Lavoie (2 November 1998)
|
||||
lavoie@zeus.genie.uottawa.ca
|
||||
Modified by:
|
||||
|
||||
Copyright notice:
|
||||
Copyright (C) 1998 Philippe Lavoie
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Comments: The load and save routine are basically the ones you can find
|
||||
in the example.c file from the libpng distribution.
|
||||
|
||||
Changes:
|
||||
5/17/99 - Modified to use the new SDL data sources - Sam Lantinga
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#ifdef macintosh
|
||||
#define MACOS
|
||||
#endif
|
||||
#include <png.h>
|
||||
|
||||
/* Check for the older version of libpng */
|
||||
#if (PNG_LIBPNG_VER_MAJOR == 1)
|
||||
#if (PNG_LIBPNG_VER_MINOR < 4)
|
||||
#define LIBPNG_VERSION_12
|
||||
typedef png_bytep png_const_bytep;
|
||||
#endif
|
||||
#if (PNG_LIBPNG_VER_MINOR < 6)
|
||||
typedef png_structp png_const_structrp;
|
||||
typedef png_infop png_const_inforp;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
png_infop (*png_create_info_struct) (png_const_structrp png_ptr);
|
||||
png_structp (*png_create_read_struct) (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn);
|
||||
void (*png_destroy_read_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr);
|
||||
png_uint_32 (*png_get_IHDR) (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_method, int *compression_method, int *filter_method);
|
||||
png_voidp (*png_get_io_ptr) (png_const_structrp png_ptr);
|
||||
png_byte (*png_get_channels) (png_const_structrp png_ptr, png_const_inforp info_ptr);
|
||||
png_uint_32 (*png_get_PLTE) (png_const_structrp png_ptr, png_infop info_ptr, png_colorp *palette, int *num_palette);
|
||||
png_uint_32 (*png_get_tRNS) (png_const_structrp png_ptr, png_infop info_ptr, png_bytep *trans, int *num_trans, png_color_16p *trans_values);
|
||||
png_uint_32 (*png_get_valid) (png_const_structrp png_ptr, png_const_inforp info_ptr, png_uint_32 flag);
|
||||
void (*png_read_image) (png_structp png_ptr, png_bytepp image);
|
||||
void (*png_read_info) (png_structp png_ptr, png_infop info_ptr);
|
||||
void (*png_read_update_info) (png_structp png_ptr, png_infop info_ptr);
|
||||
void (*png_set_expand) (png_structp png_ptr);
|
||||
void (*png_set_gray_to_rgb) (png_structp png_ptr);
|
||||
void (*png_set_packing) (png_structp png_ptr);
|
||||
void (*png_set_read_fn) (png_structp png_ptr, png_voidp io_ptr, png_rw_ptr read_data_fn);
|
||||
void (*png_set_strip_16) (png_structp png_ptr);
|
||||
int (*png_sig_cmp) (png_const_bytep sig, png_size_t start, png_size_t num_to_check);
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
jmp_buf* (*png_set_longjmp_fn) (png_structp, png_longjmp_ptr, size_t);
|
||||
#endif
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_PNG_DYNAMIC
|
||||
int IMG_InitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_PNG_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.png_create_info_struct =
|
||||
(png_infop (*) (png_const_structrp))
|
||||
SDL_LoadFunction(lib.handle, "png_create_info_struct");
|
||||
if ( lib.png_create_info_struct == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_create_read_struct =
|
||||
(png_structp (*) (png_const_charp, png_voidp, png_error_ptr, png_error_ptr))
|
||||
SDL_LoadFunction(lib.handle, "png_create_read_struct");
|
||||
if ( lib.png_create_read_struct == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_destroy_read_struct =
|
||||
(void (*) (png_structpp, png_infopp, png_infopp))
|
||||
SDL_LoadFunction(lib.handle, "png_destroy_read_struct");
|
||||
if ( lib.png_destroy_read_struct == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_IHDR =
|
||||
(png_uint_32 (*) (png_const_structrp, png_const_inforp, png_uint_32 *, png_uint_32 *, int *, int *, int *, int *, int *))
|
||||
SDL_LoadFunction(lib.handle, "png_get_IHDR");
|
||||
if ( lib.png_get_IHDR == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_channels =
|
||||
(png_byte (*) (png_const_structrp, png_const_inforp))
|
||||
SDL_LoadFunction(lib.handle, "png_get_channels");
|
||||
if ( lib.png_get_channels == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_io_ptr =
|
||||
(png_voidp (*) (png_const_structrp))
|
||||
SDL_LoadFunction(lib.handle, "png_get_io_ptr");
|
||||
if ( lib.png_get_io_ptr == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_PLTE =
|
||||
(png_uint_32 (*) (png_const_structrp, png_infop, png_colorp *, int *))
|
||||
SDL_LoadFunction(lib.handle, "png_get_PLTE");
|
||||
if ( lib.png_get_PLTE == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_tRNS =
|
||||
(png_uint_32 (*) (png_const_structrp, png_infop, png_bytep *, int *, png_color_16p *))
|
||||
SDL_LoadFunction(lib.handle, "png_get_tRNS");
|
||||
if ( lib.png_get_tRNS == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_get_valid =
|
||||
(png_uint_32 (*) (png_const_structrp, png_const_inforp, png_uint_32))
|
||||
SDL_LoadFunction(lib.handle, "png_get_valid");
|
||||
if ( lib.png_get_valid == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_read_image =
|
||||
(void (*) (png_structp, png_bytepp))
|
||||
SDL_LoadFunction(lib.handle, "png_read_image");
|
||||
if ( lib.png_read_image == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_read_info =
|
||||
(void (*) (png_structp, png_infop))
|
||||
SDL_LoadFunction(lib.handle, "png_read_info");
|
||||
if ( lib.png_read_info == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_read_update_info =
|
||||
(void (*) (png_structp, png_infop))
|
||||
SDL_LoadFunction(lib.handle, "png_read_update_info");
|
||||
if ( lib.png_read_update_info == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_expand =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_expand");
|
||||
if ( lib.png_set_expand == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_gray_to_rgb =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_gray_to_rgb");
|
||||
if ( lib.png_set_gray_to_rgb == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_packing =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_packing");
|
||||
if ( lib.png_set_packing == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_read_fn =
|
||||
(void (*) (png_structp, png_voidp, png_rw_ptr))
|
||||
SDL_LoadFunction(lib.handle, "png_set_read_fn");
|
||||
if ( lib.png_set_read_fn == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_set_strip_16 =
|
||||
(void (*) (png_structp))
|
||||
SDL_LoadFunction(lib.handle, "png_set_strip_16");
|
||||
if ( lib.png_set_strip_16 == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.png_sig_cmp =
|
||||
(int (*) (png_const_bytep, png_size_t, png_size_t))
|
||||
SDL_LoadFunction(lib.handle, "png_sig_cmp");
|
||||
if ( lib.png_sig_cmp == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
lib.png_set_longjmp_fn =
|
||||
(jmp_buf * (*) (png_structp, png_longjmp_ptr, size_t))
|
||||
SDL_LoadFunction(lib.handle, "png_set_longjmp_fn");
|
||||
if ( lib.png_set_longjmp_fn == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.png_create_info_struct = png_create_info_struct;
|
||||
lib.png_create_read_struct = png_create_read_struct;
|
||||
lib.png_destroy_read_struct = png_destroy_read_struct;
|
||||
lib.png_get_IHDR = png_get_IHDR;
|
||||
lib.png_get_channels = png_get_channels;
|
||||
lib.png_get_io_ptr = png_get_io_ptr;
|
||||
lib.png_get_PLTE = png_get_PLTE;
|
||||
lib.png_get_tRNS = png_get_tRNS;
|
||||
lib.png_get_valid = png_get_valid;
|
||||
lib.png_read_image = png_read_image;
|
||||
lib.png_read_info = png_read_info;
|
||||
lib.png_read_update_info = png_read_update_info;
|
||||
lib.png_set_expand = png_set_expand;
|
||||
lib.png_set_gray_to_rgb = png_set_gray_to_rgb;
|
||||
lib.png_set_packing = png_set_packing;
|
||||
lib.png_set_read_fn = png_set_read_fn;
|
||||
lib.png_set_strip_16 = png_set_strip_16;
|
||||
lib.png_sig_cmp = png_sig_cmp;
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
lib.png_set_longjmp_fn = png_set_longjmp_fn;
|
||||
#endif
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitPNG()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_PNG_DYNAMIC */
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNG(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_PNG;
|
||||
Uint8 magic[4];
|
||||
|
||||
if ( !src ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
start = SDL_RWtell(src);
|
||||
is_PNG = 0;
|
||||
if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
|
||||
if ( magic[0] == 0x89 &&
|
||||
magic[1] == 'P' &&
|
||||
magic[2] == 'N' &&
|
||||
magic[3] == 'G' ) {
|
||||
is_PNG = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_PNG);
|
||||
}
|
||||
|
||||
/* Load a PNG type image from an SDL datasource */
|
||||
static void png_read_data(png_structp ctx, png_bytep area, png_size_t size)
|
||||
{
|
||||
SDL_RWops *src;
|
||||
|
||||
src = (SDL_RWops *)lib.png_get_io_ptr(ctx);
|
||||
SDL_RWread(src, area, size, 1);
|
||||
}
|
||||
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
const char *error;
|
||||
SDL_Surface *volatile surface;
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, num_channels;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
SDL_Palette *palette;
|
||||
png_bytep *volatile row_pointers;
|
||||
int row, i;
|
||||
int ckey = -1;
|
||||
png_color_16 *transv;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_PNG) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the data we will clean up when we're done */
|
||||
error = NULL;
|
||||
png_ptr = NULL; info_ptr = NULL; row_pointers = NULL; surface = NULL;
|
||||
|
||||
/* Create the PNG loading context structure */
|
||||
png_ptr = lib.png_create_read_struct(PNG_LIBPNG_VER_STRING,
|
||||
NULL,NULL,NULL);
|
||||
if (png_ptr == NULL){
|
||||
error = "Couldn't allocate memory for PNG file or incompatible PNG dll";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Allocate/initialize the memory for image information. REQUIRED. */
|
||||
info_ptr = lib.png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL) {
|
||||
error = "Couldn't create image information for PNG file";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set error handling if you are using setjmp/longjmp method (this is
|
||||
* the normal method of doing things with libpng). REQUIRED unless you
|
||||
* set up your own error handlers in png_create_read_struct() earlier.
|
||||
*/
|
||||
#ifndef LIBPNG_VERSION_12
|
||||
if ( setjmp(*lib.png_set_longjmp_fn(png_ptr, longjmp, sizeof (jmp_buf))) )
|
||||
#else
|
||||
if ( setjmp(png_ptr->jmpbuf) )
|
||||
#endif
|
||||
{
|
||||
error = "Error reading the PNG file.";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set up the input control */
|
||||
lib.png_set_read_fn(png_ptr, src, png_read_data);
|
||||
|
||||
/* Read PNG header info */
|
||||
lib.png_read_info(png_ptr, info_ptr);
|
||||
lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
|
||||
&color_type, &interlace_type, NULL, NULL);
|
||||
|
||||
/* tell libpng to strip 16 bit/color files down to 8 bits/color */
|
||||
lib.png_set_strip_16(png_ptr) ;
|
||||
|
||||
/* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
|
||||
* byte into separate bytes (useful for paletted and grayscale images).
|
||||
*/
|
||||
lib.png_set_packing(png_ptr);
|
||||
|
||||
/* scale greyscale values to the range 0..255 */
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY)
|
||||
lib.png_set_expand(png_ptr);
|
||||
|
||||
/* For images with a single "transparent colour", set colour key;
|
||||
if more than one index has transparency, or if partially transparent
|
||||
entries exist, use full alpha channel */
|
||||
if (lib.png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
|
||||
int num_trans;
|
||||
Uint8 *trans;
|
||||
lib.png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &transv);
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
/* Check if all tRNS entries are opaque except one */
|
||||
int j, t = -1;
|
||||
for (j = 0; j < num_trans; j++) {
|
||||
if (trans[j] == 0) {
|
||||
if (t >= 0) {
|
||||
break;
|
||||
}
|
||||
t = j;
|
||||
} else if (trans[j] != 255) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (j == num_trans) {
|
||||
/* exactly one transparent index */
|
||||
ckey = t;
|
||||
} else {
|
||||
/* more than one transparent index, or translucency */
|
||||
lib.png_set_expand(png_ptr);
|
||||
}
|
||||
} else {
|
||||
ckey = 0; /* actual value will be set later */
|
||||
}
|
||||
}
|
||||
|
||||
if ( color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
|
||||
lib.png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
lib.png_read_update_info(png_ptr, info_ptr);
|
||||
|
||||
lib.png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
|
||||
&color_type, &interlace_type, NULL, NULL);
|
||||
|
||||
/* Allocate the SDL surface to hold the image */
|
||||
Rmask = Gmask = Bmask = Amask = 0 ;
|
||||
num_channels = lib.png_get_channels(png_ptr, info_ptr);
|
||||
if ( num_channels >= 3 ) {
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
Amask = (num_channels == 4) ? 0xFF000000 : 0;
|
||||
#else
|
||||
int s = (num_channels == 4) ? 0 : 8;
|
||||
Rmask = 0xFF000000 >> s;
|
||||
Gmask = 0x00FF0000 >> s;
|
||||
Bmask = 0x0000FF00 >> s;
|
||||
Amask = 0x000000FF >> s;
|
||||
#endif
|
||||
}
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height,
|
||||
bit_depth*num_channels, Rmask,Gmask,Bmask,Amask);
|
||||
if ( surface == NULL ) {
|
||||
error = SDL_GetError();
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ckey != -1) {
|
||||
if (color_type != PNG_COLOR_TYPE_PALETTE) {
|
||||
/* FIXME: Should these be truncated or shifted down? */
|
||||
ckey = SDL_MapRGB(surface->format,
|
||||
(Uint8)transv->red,
|
||||
(Uint8)transv->green,
|
||||
(Uint8)transv->blue);
|
||||
}
|
||||
SDL_SetColorKey(surface, SDL_TRUE, ckey);
|
||||
}
|
||||
|
||||
/* Create the array of pointers to image data */
|
||||
row_pointers = (png_bytep*) SDL_malloc(sizeof(png_bytep)*height);
|
||||
if ( (row_pointers == NULL) ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
for (row = 0; row < (int)height; row++) {
|
||||
row_pointers[row] = (png_bytep)
|
||||
(Uint8 *)surface->pixels + row*surface->pitch;
|
||||
}
|
||||
|
||||
/* Read the entire image in one go */
|
||||
lib.png_read_image(png_ptr, row_pointers);
|
||||
|
||||
/* and we're done! (png_read_end() can be omitted if no processing of
|
||||
* post-IDAT text/time/etc. is desired)
|
||||
* In some cases it can't read PNG's created by some popular programs (ACDSEE),
|
||||
* we do not want to process comments, so we omit png_read_end
|
||||
|
||||
lib.png_read_end(png_ptr, info_ptr);
|
||||
*/
|
||||
|
||||
/* Load the palette, if any */
|
||||
palette = surface->format->palette;
|
||||
if ( palette ) {
|
||||
int png_num_palette;
|
||||
png_colorp png_palette;
|
||||
lib.png_get_PLTE(png_ptr, info_ptr, &png_palette, &png_num_palette);
|
||||
if (color_type == PNG_COLOR_TYPE_GRAY) {
|
||||
palette->ncolors = 256;
|
||||
for (i = 0; i < 256; i++) {
|
||||
palette->colors[i].r = i;
|
||||
palette->colors[i].g = i;
|
||||
palette->colors[i].b = i;
|
||||
}
|
||||
} else if (png_num_palette > 0 ) {
|
||||
palette->ncolors = png_num_palette;
|
||||
for ( i=0; i<png_num_palette; ++i ) {
|
||||
palette->colors[i].b = png_palette[i].blue;
|
||||
palette->colors[i].g = png_palette[i].green;
|
||||
palette->colors[i].r = png_palette[i].red;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done: /* Clean up and return */
|
||||
if ( png_ptr ) {
|
||||
lib.png_destroy_read_struct(&png_ptr,
|
||||
info_ptr ? &info_ptr : (png_infopp)0,
|
||||
(png_infopp)0);
|
||||
}
|
||||
if ( row_pointers ) {
|
||||
SDL_free(row_pointers);
|
||||
}
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitPNG()
|
||||
{
|
||||
IMG_SetError("PNG images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitPNG()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNG(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a PNG type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPNG_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_PNG */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
|
||||
/* We'll always have PNG save support */
|
||||
#define SAVE_PNG
|
||||
|
||||
#ifdef SAVE_PNG
|
||||
|
||||
#include "miniz.h"
|
||||
|
||||
int IMG_SavePNG(SDL_Surface *surface, const char *file)
|
||||
{
|
||||
SDL_RWops *dst = SDL_RWFromFile(file, "wb");
|
||||
if (dst) {
|
||||
return IMG_SavePNG_RW(surface, dst, 1);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
if (dst) {
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
static const Uint32 png_format = SDL_PIXELFORMAT_ABGR8888;
|
||||
#else
|
||||
static const Uint32 png_format = SDL_PIXELFORMAT_RGBA8888;
|
||||
#endif
|
||||
size_t size;
|
||||
void *png;
|
||||
|
||||
if (surface->format->format == png_format) {
|
||||
png = tdefl_write_image_to_png_file_in_memory(surface->pixels, surface->w, surface->h, surface->pitch, surface->format->BytesPerPixel, &size);
|
||||
} else {
|
||||
SDL_Surface *cvt = SDL_ConvertSurfaceFormat(surface, png_format, 0);
|
||||
if (cvt) {
|
||||
png = tdefl_write_image_to_png_file_in_memory(cvt->pixels, cvt->w, cvt->h, cvt->pitch, cvt->format->BytesPerPixel, &size);
|
||||
SDL_FreeSurface(cvt);
|
||||
}
|
||||
}
|
||||
if (png) {
|
||||
if (SDL_RWwrite(dst, png, size, 1)) {
|
||||
result = 0;
|
||||
}
|
||||
SDL_free(png);
|
||||
} else {
|
||||
SDL_SetError("Failed to convert and save image");
|
||||
}
|
||||
if (freedst) {
|
||||
SDL_RWclose(dst);
|
||||
}
|
||||
} else {
|
||||
SDL_SetError("Passed NULL dst");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif /* SAVE_PNG */
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/*
|
||||
* PNM (portable anymap) image loader:
|
||||
*
|
||||
* Supports: PBM, PGM and PPM, ASCII and binary formats
|
||||
* (PBM and PGM are loaded as 8bpp surfaces)
|
||||
* Does not support: maximum component value > 255
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_PNM
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNM(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_PNM;
|
||||
char magic[2];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_PNM = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
/*
|
||||
* PNM magic signatures:
|
||||
* P1 PBM, ascii format
|
||||
* P2 PGM, ascii format
|
||||
* P3 PPM, ascii format
|
||||
* P4 PBM, binary format
|
||||
* P5 PGM, binary format
|
||||
* P6 PPM, binary format
|
||||
* P7 PAM, a general wrapper for PNM data
|
||||
*/
|
||||
if ( magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6' ) {
|
||||
is_PNM = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_PNM);
|
||||
}
|
||||
|
||||
/* read a non-negative integer from the source. return -1 upon error */
|
||||
static int ReadNumber(SDL_RWops *src)
|
||||
{
|
||||
int number;
|
||||
unsigned char ch;
|
||||
|
||||
/* Initialize return value */
|
||||
number = 0;
|
||||
|
||||
/* Skip leading whitespace */
|
||||
do {
|
||||
if ( ! SDL_RWread(src, &ch, 1, 1) ) {
|
||||
return(0);
|
||||
}
|
||||
/* Eat comments as whitespace */
|
||||
if ( ch == '#' ) { /* Comment is '#' to end of line */
|
||||
do {
|
||||
if ( ! SDL_RWread(src, &ch, 1, 1) ) {
|
||||
return -1;
|
||||
}
|
||||
} while ( (ch != '\r') && (ch != '\n') );
|
||||
}
|
||||
} while ( isspace(ch) );
|
||||
|
||||
/* Add up the number */
|
||||
do {
|
||||
number *= 10;
|
||||
number += ch-'0';
|
||||
|
||||
if ( !SDL_RWread(src, &ch, 1, 1) ) {
|
||||
return -1;
|
||||
}
|
||||
} while ( isdigit(ch) );
|
||||
|
||||
return(number);
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
SDL_Surface *surface = NULL;
|
||||
int width, height;
|
||||
int maxval, y, bpl;
|
||||
Uint8 *row;
|
||||
Uint8 *buf = NULL;
|
||||
char *error = NULL;
|
||||
Uint8 magic[2];
|
||||
int ascii;
|
||||
enum { PBM, PGM, PPM, PAM } kind;
|
||||
|
||||
#define ERROR(s) do { error = (s); goto done; } while(0)
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
SDL_RWread(src, magic, 2, 1);
|
||||
kind = magic[1] - '1';
|
||||
ascii = 1;
|
||||
if(kind >= 3) {
|
||||
ascii = 0;
|
||||
kind -= 3;
|
||||
}
|
||||
|
||||
width = ReadNumber(src);
|
||||
height = ReadNumber(src);
|
||||
if(width <= 0 || height <= 0)
|
||||
ERROR("Unable to read image width and height");
|
||||
|
||||
if(kind != PBM) {
|
||||
maxval = ReadNumber(src);
|
||||
if(maxval <= 0 || maxval > 255)
|
||||
ERROR("unsupported PNM format");
|
||||
} else
|
||||
maxval = 255; /* never scale PBMs */
|
||||
|
||||
/* binary PNM allows just a single character of whitespace after
|
||||
the last parameter, and we've already consumed it */
|
||||
|
||||
if(kind == PPM) {
|
||||
/* 24-bit surface in R,G,B byte order */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24,
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
0x000000ff, 0x0000ff00, 0x00ff0000,
|
||||
#else
|
||||
0x00ff0000, 0x0000ff00, 0x000000ff,
|
||||
#endif
|
||||
0);
|
||||
} else {
|
||||
/* load PBM/PGM as 8-bit indexed images */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8,
|
||||
0, 0, 0, 0);
|
||||
}
|
||||
if ( surface == NULL )
|
||||
ERROR("Out of memory");
|
||||
bpl = width * surface->format->BytesPerPixel;
|
||||
if(kind == PGM) {
|
||||
SDL_Color *c = surface->format->palette->colors;
|
||||
int i;
|
||||
for(i = 0; i < 256; i++)
|
||||
c[i].r = c[i].g = c[i].b = i;
|
||||
surface->format->palette->ncolors = 256;
|
||||
} else if(kind == PBM) {
|
||||
/* for some reason PBM has 1=black, 0=white */
|
||||
SDL_Color *c = surface->format->palette->colors;
|
||||
c[0].r = c[0].g = c[0].b = 255;
|
||||
c[1].r = c[1].g = c[1].b = 0;
|
||||
surface->format->palette->ncolors = 2;
|
||||
bpl = (width + 7) >> 3;
|
||||
buf = (Uint8 *)SDL_malloc(bpl);
|
||||
if(buf == NULL)
|
||||
ERROR("Out of memory");
|
||||
}
|
||||
|
||||
/* Read the image into the surface */
|
||||
row = (Uint8 *)surface->pixels;
|
||||
for(y = 0; y < height; y++) {
|
||||
if(ascii) {
|
||||
int i;
|
||||
if(kind == PBM) {
|
||||
for(i = 0; i < width; i++) {
|
||||
Uint8 ch;
|
||||
do {
|
||||
if(!SDL_RWread(src, &ch,
|
||||
1, 1))
|
||||
ERROR("file truncated");
|
||||
ch -= '0';
|
||||
} while(ch > 1);
|
||||
row[i] = ch;
|
||||
}
|
||||
} else {
|
||||
for(i = 0; i < bpl; i++) {
|
||||
int c;
|
||||
c = ReadNumber(src);
|
||||
if(c < 0)
|
||||
ERROR("file truncated");
|
||||
row[i] = c;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Uint8 *dst = (kind == PBM) ? buf : row;
|
||||
if(!SDL_RWread(src, dst, bpl, 1))
|
||||
ERROR("file truncated");
|
||||
if(kind == PBM) {
|
||||
/* expand bitmap to 8bpp */
|
||||
int i;
|
||||
for(i = 0; i < width; i++) {
|
||||
int bit = 7 - (i & 7);
|
||||
row[i] = (buf[i >> 3] >> bit) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(maxval < 255) {
|
||||
/* scale up to full dynamic range (slow) */
|
||||
int i;
|
||||
for(i = 0; i < bpl; i++)
|
||||
row[i] = row[i] * 255 / maxval;
|
||||
}
|
||||
row += surface->pitch;
|
||||
}
|
||||
done:
|
||||
SDL_free(buf);
|
||||
if(error) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isPNM(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a PNM type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadPNM_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_PNM */
|
||||
@@ -0,0 +1,340 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a Targa image file loading framework */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_TGA
|
||||
|
||||
/*
|
||||
* A TGA loader for the SDL library
|
||||
* Supports: Reading 8, 15, 16, 24 and 32bpp images, with alpha or colourkey,
|
||||
* uncompressed or RLE encoded.
|
||||
*
|
||||
* 2000-06-10 Mattias Engdegård <f91-men@nada.kth.se>: initial version
|
||||
* 2000-06-26 Mattias Engdegård <f91-men@nada.kth.se>: read greyscale TGAs
|
||||
* 2000-08-09 Mattias Engdegård <f91-men@nada.kth.se>: alpha inversion removed
|
||||
*/
|
||||
|
||||
struct TGAheader {
|
||||
Uint8 infolen; /* length of info field */
|
||||
Uint8 has_cmap; /* 1 if image has colormap, 0 otherwise */
|
||||
Uint8 type;
|
||||
|
||||
Uint8 cmap_start[2]; /* index of first colormap entry */
|
||||
Uint8 cmap_len[2]; /* number of entries in colormap */
|
||||
Uint8 cmap_bits; /* bits per colormap entry */
|
||||
|
||||
Uint8 yorigin[2]; /* image origin (ignored here) */
|
||||
Uint8 xorigin[2];
|
||||
Uint8 width[2]; /* image size */
|
||||
Uint8 height[2];
|
||||
Uint8 pixel_bits; /* bits/pixel */
|
||||
Uint8 flags;
|
||||
};
|
||||
|
||||
enum tga_type {
|
||||
TGA_TYPE_INDEXED = 1,
|
||||
TGA_TYPE_RGB = 2,
|
||||
TGA_TYPE_BW = 3,
|
||||
TGA_TYPE_RLE_INDEXED = 9,
|
||||
TGA_TYPE_RLE_RGB = 10,
|
||||
TGA_TYPE_RLE_BW = 11
|
||||
};
|
||||
|
||||
#define TGA_INTERLEAVE_MASK 0xc0
|
||||
#define TGA_INTERLEAVE_NONE 0x00
|
||||
#define TGA_INTERLEAVE_2WAY 0x40
|
||||
#define TGA_INTERLEAVE_4WAY 0x80
|
||||
|
||||
#define TGA_ORIGIN_MASK 0x30
|
||||
#define TGA_ORIGIN_LEFT 0x00
|
||||
#define TGA_ORIGIN_RIGHT 0x10
|
||||
#define TGA_ORIGIN_LOWER 0x00
|
||||
#define TGA_ORIGIN_UPPER 0x20
|
||||
|
||||
/* read/write unaligned little-endian 16-bit ints */
|
||||
#define LE16(p) ((p)[0] + ((p)[1] << 8))
|
||||
#define SETLE16(p, v) ((p)[0] = (v), (p)[1] = (v) >> 8)
|
||||
|
||||
/* Load a TGA type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
const char *error = NULL;
|
||||
struct TGAheader hdr;
|
||||
int rle = 0;
|
||||
int alpha = 0;
|
||||
int indexed = 0;
|
||||
int grey = 0;
|
||||
int ckey = -1;
|
||||
int ncols, w, h;
|
||||
SDL_Surface *img = NULL;
|
||||
Uint32 rmask, gmask, bmask, amask;
|
||||
Uint8 *dst;
|
||||
int i;
|
||||
int bpp;
|
||||
int lstep;
|
||||
Uint32 pixel;
|
||||
int count, rep;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if(!SDL_RWread(src, &hdr, sizeof(hdr), 1)) {
|
||||
error = "Error reading TGA data";
|
||||
goto error;
|
||||
}
|
||||
ncols = LE16(hdr.cmap_len);
|
||||
switch(hdr.type) {
|
||||
case TGA_TYPE_RLE_INDEXED:
|
||||
rle = 1;
|
||||
/* fallthrough */
|
||||
case TGA_TYPE_INDEXED:
|
||||
if(!hdr.has_cmap || hdr.pixel_bits != 8 || ncols > 256)
|
||||
goto unsupported;
|
||||
indexed = 1;
|
||||
break;
|
||||
|
||||
case TGA_TYPE_RLE_RGB:
|
||||
rle = 1;
|
||||
/* fallthrough */
|
||||
case TGA_TYPE_RGB:
|
||||
indexed = 0;
|
||||
break;
|
||||
|
||||
case TGA_TYPE_RLE_BW:
|
||||
rle = 1;
|
||||
/* fallthrough */
|
||||
case TGA_TYPE_BW:
|
||||
if(hdr.pixel_bits != 8)
|
||||
goto unsupported;
|
||||
/* Treat greyscale as 8bpp indexed images */
|
||||
indexed = grey = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
bpp = (hdr.pixel_bits + 7) >> 3;
|
||||
rmask = gmask = bmask = amask = 0;
|
||||
switch(hdr.pixel_bits) {
|
||||
case 8:
|
||||
if(!indexed) {
|
||||
goto unsupported;
|
||||
}
|
||||
break;
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
/* 15 and 16bpp both seem to use 5 bits/plane. The extra alpha bit
|
||||
is ignored for now. */
|
||||
rmask = 0x7c00;
|
||||
gmask = 0x03e0;
|
||||
bmask = 0x001f;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
alpha = 1;
|
||||
/* fallthrough */
|
||||
case 24:
|
||||
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
||||
{
|
||||
int s = alpha ? 0 : 8;
|
||||
amask = 0x000000ff >> s;
|
||||
rmask = 0x0000ff00 >> s;
|
||||
gmask = 0x00ff0000 >> s;
|
||||
bmask = 0xff000000 >> s;
|
||||
}
|
||||
#else
|
||||
amask = alpha ? 0xff000000 : 0;
|
||||
rmask = 0x00ff0000;
|
||||
gmask = 0x0000ff00;
|
||||
bmask = 0x000000ff;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
if((hdr.flags & TGA_INTERLEAVE_MASK) != TGA_INTERLEAVE_NONE
|
||||
|| hdr.flags & TGA_ORIGIN_RIGHT) {
|
||||
goto unsupported;
|
||||
}
|
||||
|
||||
SDL_RWseek(src, hdr.infolen, RW_SEEK_CUR); /* skip info field */
|
||||
|
||||
w = LE16(hdr.width);
|
||||
h = LE16(hdr.height);
|
||||
img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h,
|
||||
bpp * 8,
|
||||
rmask, gmask, bmask, amask);
|
||||
if(img == NULL) {
|
||||
error = "Out of memory";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(hdr.has_cmap) {
|
||||
int palsiz = ncols * ((hdr.cmap_bits + 7) >> 3);
|
||||
if(indexed && !grey) {
|
||||
Uint8 *pal = (Uint8 *)SDL_malloc(palsiz), *p = pal;
|
||||
SDL_Color *colors = img->format->palette->colors;
|
||||
img->format->palette->ncolors = ncols;
|
||||
SDL_RWread(src, pal, palsiz, 1);
|
||||
for(i = 0; i < ncols; i++) {
|
||||
switch(hdr.cmap_bits) {
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
Uint16 c = p[0] + (p[1] << 8);
|
||||
p += 2;
|
||||
colors[i].r = (c >> 7) & 0xf8;
|
||||
colors[i].g = (c >> 2) & 0xf8;
|
||||
colors[i].b = c << 3;
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
colors[i].b = *p++;
|
||||
colors[i].g = *p++;
|
||||
colors[i].r = *p++;
|
||||
if(hdr.cmap_bits == 32 && *p++ < 128)
|
||||
ckey = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
SDL_free(pal);
|
||||
if(ckey >= 0)
|
||||
SDL_SetColorKey(img, SDL_TRUE, ckey);
|
||||
} else {
|
||||
/* skip unneeded colormap */
|
||||
SDL_RWseek(src, palsiz, RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
if(grey) {
|
||||
SDL_Color *colors = img->format->palette->colors;
|
||||
for(i = 0; i < 256; i++)
|
||||
colors[i].r = colors[i].g = colors[i].b = i;
|
||||
img->format->palette->ncolors = 256;
|
||||
}
|
||||
|
||||
if(hdr.flags & TGA_ORIGIN_UPPER) {
|
||||
lstep = img->pitch;
|
||||
dst = (Uint8 *)img->pixels;
|
||||
} else {
|
||||
lstep = -img->pitch;
|
||||
dst = (Uint8 *)img->pixels + (h - 1) * img->pitch;
|
||||
}
|
||||
|
||||
/* The RLE decoding code is slightly convoluted since we can't rely on
|
||||
spans not to wrap across scan lines */
|
||||
count = rep = 0;
|
||||
for(i = 0; i < h; i++) {
|
||||
if(rle) {
|
||||
int x = 0;
|
||||
for(;;) {
|
||||
Uint8 c;
|
||||
|
||||
if(count) {
|
||||
int n = count;
|
||||
if(n > w - x)
|
||||
n = w - x;
|
||||
SDL_RWread(src, dst + x * bpp, n * bpp, 1);
|
||||
count -= n;
|
||||
x += n;
|
||||
if(x == w)
|
||||
break;
|
||||
} else if(rep) {
|
||||
int n = rep;
|
||||
if(n > w - x)
|
||||
n = w - x;
|
||||
rep -= n;
|
||||
while(n--) {
|
||||
SDL_memcpy(dst + x * bpp, &pixel, bpp);
|
||||
x++;
|
||||
}
|
||||
if(x == w)
|
||||
break;
|
||||
}
|
||||
|
||||
SDL_RWread(src, &c, 1, 1);
|
||||
if(c & 0x80) {
|
||||
SDL_RWread(src, &pixel, bpp, 1);
|
||||
rep = (c & 0x7f) + 1;
|
||||
} else {
|
||||
count = c + 1;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
SDL_RWread(src, dst, w * bpp, 1);
|
||||
}
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
if (bpp == 2) {
|
||||
/* swap byte order */
|
||||
int x;
|
||||
Uint16 *p = (Uint16 *)dst;
|
||||
for(x = 0; x < w; x++)
|
||||
p[x] = SDL_Swap16(p[x]);
|
||||
}
|
||||
#endif
|
||||
dst += lstep;
|
||||
}
|
||||
return img;
|
||||
|
||||
unsupported:
|
||||
error = "Unsupported TGA format";
|
||||
|
||||
error:
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( img ) {
|
||||
SDL_FreeSurface(img);
|
||||
}
|
||||
IMG_SetError(error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* dummy TGA load routine */
|
||||
SDL_Surface *IMG_LoadTGA_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_TGA */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#if !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND)
|
||||
|
||||
/* This is a TIFF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_TIF
|
||||
|
||||
#include <tiffio.h>
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
TIFF* (*TIFFClientOpen)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc);
|
||||
void (*TIFFClose)(TIFF*);
|
||||
int (*TIFFGetField)(TIFF*, ttag_t, ...);
|
||||
int (*TIFFReadRGBAImage)(TIFF*, uint32, uint32, uint32*, int);
|
||||
TIFFErrorHandler (*TIFFSetErrorHandler)(TIFFErrorHandler);
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_TIF_DYNAMIC
|
||||
int IMG_InitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_TIF_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFClientOpen =
|
||||
(TIFF* (*)(const char*, const char*, thandle_t, TIFFReadWriteProc, TIFFReadWriteProc, TIFFSeekProc, TIFFCloseProc, TIFFSizeProc, TIFFMapFileProc, TIFFUnmapFileProc))
|
||||
SDL_LoadFunction(lib.handle, "TIFFClientOpen");
|
||||
if ( lib.TIFFClientOpen == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFClose =
|
||||
(void (*)(TIFF*))
|
||||
SDL_LoadFunction(lib.handle, "TIFFClose");
|
||||
if ( lib.TIFFClose == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFGetField =
|
||||
(int (*)(TIFF*, ttag_t, ...))
|
||||
SDL_LoadFunction(lib.handle, "TIFFGetField");
|
||||
if ( lib.TIFFGetField == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFReadRGBAImage =
|
||||
(int (*)(TIFF*, uint32, uint32, uint32*, int))
|
||||
SDL_LoadFunction(lib.handle, "TIFFReadRGBAImage");
|
||||
if ( lib.TIFFReadRGBAImage == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
lib.TIFFSetErrorHandler =
|
||||
(TIFFErrorHandler (*)(TIFFErrorHandler))
|
||||
SDL_LoadFunction(lib.handle, "TIFFSetErrorHandler");
|
||||
if ( lib.TIFFSetErrorHandler == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.TIFFClientOpen = TIFFClientOpen;
|
||||
lib.TIFFClose = TIFFClose;
|
||||
lib.TIFFGetField = TIFFGetField;
|
||||
lib.TIFFReadRGBAImage = TIFFReadRGBAImage;
|
||||
lib.TIFFSetErrorHandler = TIFFSetErrorHandler;
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitTIF()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_TIF_DYNAMIC */
|
||||
|
||||
/*
|
||||
* These are the thunking routine to use the SDL_RWops* routines from
|
||||
* libtiff's internals.
|
||||
*/
|
||||
|
||||
static tsize_t tiff_read(thandle_t fd, tdata_t buf, tsize_t size)
|
||||
{
|
||||
return SDL_RWread((SDL_RWops*)fd, buf, 1, size);
|
||||
}
|
||||
|
||||
static toff_t tiff_seek(thandle_t fd, toff_t offset, int origin)
|
||||
{
|
||||
return SDL_RWseek((SDL_RWops*)fd, offset, origin);
|
||||
}
|
||||
|
||||
static tsize_t tiff_write(thandle_t fd, tdata_t buf, tsize_t size)
|
||||
{
|
||||
return SDL_RWwrite((SDL_RWops*)fd, buf, 1, size);
|
||||
}
|
||||
|
||||
static int tiff_close(thandle_t fd)
|
||||
{
|
||||
/*
|
||||
* We don't want libtiff closing our SDL_RWops*, but if it's not given
|
||||
* a routine to try, and if the image isn't a TIFF, it'll segfault.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tiff_map(thandle_t fd, tdata_t* pbase, toff_t* psize)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void tiff_unmap(thandle_t fd, tdata_t base, toff_t size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static toff_t tiff_size(thandle_t fd)
|
||||
{
|
||||
Sint64 save_pos;
|
||||
toff_t size;
|
||||
|
||||
save_pos = SDL_RWtell((SDL_RWops*)fd);
|
||||
SDL_RWseek((SDL_RWops*)fd, 0, RW_SEEK_END);
|
||||
size = SDL_RWtell((SDL_RWops*)fd);
|
||||
SDL_RWseek((SDL_RWops*)fd, save_pos, RW_SEEK_SET);
|
||||
return size;
|
||||
}
|
||||
|
||||
int IMG_isTIF(SDL_RWops* src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_TIF;
|
||||
Uint8 magic[4];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_TIF = 0;
|
||||
if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
|
||||
if ( (magic[0] == 'I' &&
|
||||
magic[1] == 'I' &&
|
||||
magic[2] == 0x2a &&
|
||||
magic[3] == 0x00) ||
|
||||
(magic[0] == 'M' &&
|
||||
magic[1] == 'M' &&
|
||||
magic[2] == 0x00 &&
|
||||
magic[3] == 0x2a) ) {
|
||||
is_TIF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_TIF);
|
||||
}
|
||||
|
||||
SDL_Surface* IMG_LoadTIF_RW(SDL_RWops* src)
|
||||
{
|
||||
Sint64 start;
|
||||
TIFF* tiff;
|
||||
SDL_Surface* surface = NULL;
|
||||
Uint32 img_width, img_height;
|
||||
Uint32 Rmask, Gmask, Bmask, Amask;
|
||||
Uint32 x, y;
|
||||
Uint32 half;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_TIF) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* turn off memory mapped access with the m flag */
|
||||
tiff = lib.TIFFClientOpen("SDL_image", "rm", (thandle_t)src,
|
||||
tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_map, tiff_unmap);
|
||||
if(!tiff)
|
||||
goto error;
|
||||
|
||||
/* Retrieve the dimensions of the image from the TIFF tags */
|
||||
lib.TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &img_width);
|
||||
lib.TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &img_height);
|
||||
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
Amask = 0xFF000000;
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, img_width, img_height, 32,
|
||||
Rmask, Gmask, Bmask, Amask);
|
||||
if(!surface)
|
||||
goto error;
|
||||
|
||||
if(!lib.TIFFReadRGBAImage(tiff, img_width, img_height, (uint32 *)surface->pixels, 0))
|
||||
goto error;
|
||||
|
||||
/* libtiff loads the image upside-down, flip it back */
|
||||
half = img_height / 2;
|
||||
for(y = 0; y < half; y++)
|
||||
{
|
||||
Uint32 *top = (Uint32 *)surface->pixels + y * surface->pitch/4;
|
||||
Uint32 *bot = (Uint32 *)surface->pixels
|
||||
+ (img_height - y - 1) * surface->pitch/4;
|
||||
for(x = 0; x < img_width; x++)
|
||||
{
|
||||
Uint32 tmp = top[x];
|
||||
top[x] = bot[x];
|
||||
bot[x] = tmp;
|
||||
}
|
||||
}
|
||||
lib.TIFFClose(tiff);
|
||||
|
||||
return surface;
|
||||
|
||||
error:
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitTIF()
|
||||
{
|
||||
IMG_SetError("TIFF images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitTIF()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isTIF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a TIFF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadTIF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_TIF */
|
||||
|
||||
#endif /* !defined(__APPLE__) || defined(SDL_IMAGE_USE_COMMON_BACKEND) */
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a WEBP image file loading framework */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_WEBP
|
||||
|
||||
/*=============================================================================
|
||||
File: SDL_webp.c
|
||||
Purpose: A WEBP loader for the SDL library
|
||||
Revision:
|
||||
Created by: Michael Bonfils (Murlock) (26 November 2011)
|
||||
murlock42@gmail.com
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#include "SDL_endian.h"
|
||||
|
||||
#ifdef macintosh
|
||||
#define MACOS
|
||||
#endif
|
||||
#include <webp/decode.h>
|
||||
|
||||
static struct {
|
||||
int loaded;
|
||||
void *handle;
|
||||
VP8StatusCode (*webp_get_features_internal) (const uint8_t *data, size_t data_size, WebPBitstreamFeatures* features, int decoder_abi_version);
|
||||
uint8_t* (*webp_decode_rgb_into) (const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
|
||||
uint8_t* (*webp_decode_rgba_into) (const uint8_t* data, size_t data_size, uint8_t* output_buffer, size_t output_buffer_size, int output_stride);
|
||||
} lib;
|
||||
|
||||
#ifdef LOAD_WEBP_DYNAMIC
|
||||
int IMG_InitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
lib.handle = SDL_LoadObject(LOAD_WEBP_DYNAMIC);
|
||||
if ( lib.handle == NULL ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lib.webp_get_features_internal =
|
||||
( VP8StatusCode (*) (const uint8_t *, size_t, WebPBitstreamFeatures*, int) )
|
||||
SDL_LoadFunction(lib.handle, "WebPGetFeaturesInternal" );
|
||||
if ( lib.webp_get_features_internal == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lib.webp_decode_rgb_into =
|
||||
( uint8_t* (*) (const uint8_t*, size_t, uint8_t*, size_t, int ) )
|
||||
SDL_LoadFunction(lib.handle, "WebPDecodeRGBInto" );
|
||||
if ( lib.webp_decode_rgb_into == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lib.webp_decode_rgba_into =
|
||||
( uint8_t* (*) (const uint8_t*, size_t, uint8_t*, size_t, int ) )
|
||||
SDL_LoadFunction(lib.handle, "WebPDecodeRGBAInto" );
|
||||
if ( lib.webp_decode_rgba_into == NULL ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
SDL_UnloadObject(lib.handle);
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#else
|
||||
int IMG_InitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
#ifdef __MACOSX__
|
||||
extern VP8StatusCode WebPGetFeaturesInternal(const uint8_t*, size_t, WebPBitstreamFeatures*, int) __attribute__((weak_import));
|
||||
if ( WebPGetFeaturesInternal == NULL )
|
||||
{
|
||||
/* Missing weakly linked framework */
|
||||
IMG_SetError("Missing webp.framework");
|
||||
return -1;
|
||||
}
|
||||
#endif // __MACOSX__
|
||||
|
||||
lib.webp_get_features_internal = WebPGetFeaturesInternal;
|
||||
lib.webp_decode_rgb_into = WebPDecodeRGBInto;
|
||||
lib.webp_decode_rgba_into = WebPDecodeRGBAInto;
|
||||
}
|
||||
++lib.loaded;
|
||||
|
||||
return 0;
|
||||
}
|
||||
void IMG_QuitWEBP()
|
||||
{
|
||||
if ( lib.loaded == 0 ) {
|
||||
return;
|
||||
}
|
||||
if ( lib.loaded == 1 ) {
|
||||
}
|
||||
--lib.loaded;
|
||||
}
|
||||
#endif /* LOAD_WEBP_DYNAMIC */
|
||||
|
||||
static int webp_getinfo( SDL_RWops *src, int *datasize ) {
|
||||
Sint64 start;
|
||||
int is_WEBP;
|
||||
Uint8 magic[20];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_WEBP = 0;
|
||||
if ( SDL_RWread(src, magic, 1, sizeof(magic)) == sizeof(magic) ) {
|
||||
if ( magic[ 0] == 'R' &&
|
||||
magic[ 1] == 'I' &&
|
||||
magic[ 2] == 'F' &&
|
||||
magic[ 3] == 'F' &&
|
||||
magic[ 8] == 'W' &&
|
||||
magic[ 9] == 'E' &&
|
||||
magic[10] == 'B' &&
|
||||
magic[11] == 'P' &&
|
||||
magic[12] == 'V' &&
|
||||
magic[13] == 'P' &&
|
||||
magic[14] == '8' &&
|
||||
#if WEBP_DECODER_ABI_VERSION < 0x0003 /* old versions don't support WEBPVP8X and WEBPVP8L */
|
||||
magic[15] == ' ') {
|
||||
#else
|
||||
(magic[15] == ' ' || magic[15] == 'X' || magic[15] == 'L')) {
|
||||
#endif
|
||||
is_WEBP = 1;
|
||||
if ( datasize ) {
|
||||
*datasize = (int)SDL_RWseek(src, 0, SEEK_END);
|
||||
}
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_WEBP);
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isWEBP(SDL_RWops *src)
|
||||
{
|
||||
return webp_getinfo( src, NULL );
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *volatile surface = NULL;
|
||||
Uint32 Rmask;
|
||||
Uint32 Gmask;
|
||||
Uint32 Bmask;
|
||||
Uint32 Amask;
|
||||
WebPBitstreamFeatures features;
|
||||
int raw_data_size;
|
||||
uint8_t *raw_data = NULL;
|
||||
int r;
|
||||
uint8_t *ret;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
if ( !IMG_Init(IMG_INIT_WEBP) ) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
raw_data_size = -1;
|
||||
if ( !webp_getinfo( src, &raw_data_size ) ) {
|
||||
error = "Invalid WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
// seek to start of file
|
||||
SDL_RWseek(src, 0, RW_SEEK_SET );
|
||||
|
||||
raw_data = (uint8_t*) SDL_malloc( raw_data_size );
|
||||
if ( raw_data == NULL ) {
|
||||
error = "Failed to allocate enought buffer for WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = SDL_RWread(src, raw_data, 1, raw_data_size );
|
||||
if ( r != raw_data_size ) {
|
||||
error = "Failed to read WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// extract size of picture, not interesting since we don't know about alpha channel
|
||||
int width = -1, height = -1;
|
||||
if ( !WebPGetInfo( raw_data, raw_data_size, &width, &height ) ) {
|
||||
printf("WebPGetInfo has failed\n" );
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( lib.webp_get_features_internal( raw_data, raw_data_size, &features, WEBP_DECODER_ABI_VERSION ) != VP8_STATUS_OK ) {
|
||||
error = "WebPGetFeatures has failed";
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check if it's ok !*/
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
Rmask = 0x000000FF;
|
||||
Gmask = 0x0000FF00;
|
||||
Bmask = 0x00FF0000;
|
||||
Amask = (features.has_alpha) ? 0xFF000000 : 0;
|
||||
#else
|
||||
s = (features.has_alpha) ? 0 : 8;
|
||||
Rmask = 0xFF000000 >> s;
|
||||
Gmask = 0x00FF0000 >> s;
|
||||
Bmask = 0x0000FF00 >> s;
|
||||
Amask = 0x000000FF >> s;
|
||||
#endif
|
||||
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
|
||||
features.width, features.height,
|
||||
features.has_alpha?32:24, Rmask,Gmask,Bmask,Amask);
|
||||
|
||||
if ( surface == NULL ) {
|
||||
error = "Failed to allocate SDL_Surface";
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ( features.has_alpha ) {
|
||||
ret = lib.webp_decode_rgba_into( raw_data, raw_data_size, (uint8_t *)surface->pixels, surface->pitch * surface->h, surface->pitch );
|
||||
} else {
|
||||
ret = lib.webp_decode_rgb_into( raw_data, raw_data_size, (uint8_t *)surface->pixels, surface->pitch * surface->h, surface->pitch );
|
||||
}
|
||||
|
||||
if ( !ret ) {
|
||||
error = "Failed to decode WEBP";
|
||||
goto error;
|
||||
}
|
||||
|
||||
return surface;
|
||||
|
||||
|
||||
error:
|
||||
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface( surface );
|
||||
}
|
||||
|
||||
if ( raw_data ) {
|
||||
SDL_free( raw_data );
|
||||
}
|
||||
|
||||
if ( error ) {
|
||||
IMG_SetError( error );
|
||||
}
|
||||
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int IMG_InitWEBP()
|
||||
{
|
||||
IMG_SetError("WEBP images are not supported");
|
||||
return(-1);
|
||||
}
|
||||
|
||||
void IMG_QuitWEBP()
|
||||
{
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isWEBP(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a WEBP type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadWEBP_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_WEBP */
|
||||
@@ -0,0 +1,841 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a XCF image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "SDL_endian.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XCF
|
||||
|
||||
#if DEBUG
|
||||
static char prop_names [][30] = {
|
||||
"end",
|
||||
"colormap",
|
||||
"active_layer",
|
||||
"active_channel",
|
||||
"selection",
|
||||
"floating_selection",
|
||||
"opacity",
|
||||
"mode",
|
||||
"visible",
|
||||
"linked",
|
||||
"preserve_transparency",
|
||||
"apply_mask",
|
||||
"edit_mask",
|
||||
"show_mask",
|
||||
"show_masked",
|
||||
"offsets",
|
||||
"color",
|
||||
"compression",
|
||||
"guides",
|
||||
"resolution",
|
||||
"tattoo",
|
||||
"parasites",
|
||||
"unit",
|
||||
"paths",
|
||||
"user_unit"
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PROP_END = 0,
|
||||
PROP_COLORMAP = 1,
|
||||
PROP_ACTIVE_LAYER = 2,
|
||||
PROP_ACTIVE_CHANNEL = 3,
|
||||
PROP_SELECTION = 4,
|
||||
PROP_FLOATING_SELECTION = 5,
|
||||
PROP_OPACITY = 6,
|
||||
PROP_MODE = 7,
|
||||
PROP_VISIBLE = 8,
|
||||
PROP_LINKED = 9,
|
||||
PROP_PRESERVE_TRANSPARENCY = 10,
|
||||
PROP_APPLY_MASK = 11,
|
||||
PROP_EDIT_MASK = 12,
|
||||
PROP_SHOW_MASK = 13,
|
||||
PROP_SHOW_MASKED = 14,
|
||||
PROP_OFFSETS = 15,
|
||||
PROP_COLOR = 16,
|
||||
PROP_COMPRESSION = 17,
|
||||
PROP_GUIDES = 18,
|
||||
PROP_RESOLUTION = 19,
|
||||
PROP_TATTOO = 20,
|
||||
PROP_PARASITES = 21,
|
||||
PROP_UNIT = 22,
|
||||
PROP_PATHS = 23,
|
||||
PROP_USER_UNIT = 24
|
||||
} xcf_prop_type;
|
||||
|
||||
typedef enum {
|
||||
COMPR_NONE = 0,
|
||||
COMPR_RLE = 1,
|
||||
COMPR_ZLIB = 2,
|
||||
COMPR_FRACTAL = 3
|
||||
} xcf_compr_type;
|
||||
|
||||
typedef enum {
|
||||
IMAGE_RGB = 0,
|
||||
IMAGE_GREYSCALE = 1,
|
||||
IMAGE_INDEXED = 2
|
||||
} xcf_image_type;
|
||||
|
||||
typedef struct {
|
||||
Uint32 id;
|
||||
Uint32 length;
|
||||
union {
|
||||
struct {
|
||||
Uint32 num;
|
||||
char * cmap;
|
||||
} colormap; // 1
|
||||
struct {
|
||||
Uint32 drawable_offset;
|
||||
} floating_selection; // 5
|
||||
Sint32 opacity;
|
||||
Sint32 mode;
|
||||
int visible;
|
||||
int linked;
|
||||
int preserve_transparency;
|
||||
int apply_mask;
|
||||
int show_mask;
|
||||
struct {
|
||||
Sint32 x;
|
||||
Sint32 y;
|
||||
} offset;
|
||||
unsigned char color [3];
|
||||
Uint8 compression;
|
||||
struct {
|
||||
Sint32 x;
|
||||
Sint32 y;
|
||||
} resolution;
|
||||
struct {
|
||||
char * name;
|
||||
Uint32 flags;
|
||||
Uint32 size;
|
||||
char * data;
|
||||
} parasite;
|
||||
} data;
|
||||
} xcf_prop;
|
||||
|
||||
typedef struct {
|
||||
char sign [14];
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Sint32 image_type;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 * layer_file_offsets;
|
||||
Uint32 * channel_file_offsets;
|
||||
|
||||
xcf_compr_type compr;
|
||||
Uint32 cm_num;
|
||||
unsigned char * cm_map;
|
||||
} xcf_header;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Sint32 layer_type;
|
||||
char * name;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 hierarchy_file_offset;
|
||||
Uint32 layer_mask_offset;
|
||||
|
||||
Uint32 offset_x;
|
||||
Uint32 offset_y;
|
||||
int visible;
|
||||
} xcf_layer;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
char * name;
|
||||
xcf_prop * properties;
|
||||
|
||||
Uint32 hierarchy_file_offset;
|
||||
|
||||
Uint32 color;
|
||||
Uint32 opacity;
|
||||
int selection;
|
||||
int visible;
|
||||
} xcf_channel;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
Uint32 bpp;
|
||||
|
||||
Uint32 * level_file_offsets;
|
||||
} xcf_hierarchy;
|
||||
|
||||
typedef struct {
|
||||
Uint32 width;
|
||||
Uint32 height;
|
||||
|
||||
Uint32 * tile_file_offsets;
|
||||
} xcf_level;
|
||||
|
||||
typedef unsigned char * xcf_tile;
|
||||
|
||||
typedef unsigned char * (* load_tile_type) (SDL_RWops *, Uint32, int, int, int);
|
||||
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXCF(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_XCF;
|
||||
char magic[14];
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XCF = 0;
|
||||
if ( SDL_RWread(src, magic, sizeof(magic), 1) ) {
|
||||
if (SDL_strncmp(magic, "gimp xcf ", 9) == 0) {
|
||||
is_XCF = 1;
|
||||
}
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XCF);
|
||||
}
|
||||
|
||||
static char * read_string (SDL_RWops * src) {
|
||||
Uint32 tmp;
|
||||
char * data;
|
||||
|
||||
tmp = SDL_ReadBE32 (src);
|
||||
if (tmp > 0) {
|
||||
data = (char *) SDL_malloc (sizeof (char) * tmp);
|
||||
SDL_RWread (src, data, tmp, 1);
|
||||
}
|
||||
else {
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
static Uint32 Swap32 (Uint32 v) {
|
||||
return
|
||||
((v & 0x000000FF) << 16)
|
||||
| ((v & 0x0000FF00))
|
||||
| ((v & 0x00FF0000) >> 16)
|
||||
| ((v & 0xFF000000));
|
||||
}
|
||||
|
||||
static void xcf_read_property (SDL_RWops * src, xcf_prop * prop) {
|
||||
prop->id = SDL_ReadBE32 (src);
|
||||
prop->length = SDL_ReadBE32 (src);
|
||||
|
||||
#if DEBUG
|
||||
printf ("%.8X: %s: %d\n", SDL_RWtell (src), prop->id < 25 ? prop_names [prop->id] : "unknown", prop->length);
|
||||
#endif
|
||||
|
||||
switch (prop->id) {
|
||||
case PROP_COLORMAP:
|
||||
prop->data.colormap.num = SDL_ReadBE32 (src);
|
||||
prop->data.colormap.cmap = (char *) SDL_malloc (sizeof (char) * prop->data.colormap.num * 3);
|
||||
SDL_RWread (src, prop->data.colormap.cmap, prop->data.colormap.num*3, 1);
|
||||
break;
|
||||
|
||||
case PROP_OFFSETS:
|
||||
prop->data.offset.x = SDL_ReadBE32 (src);
|
||||
prop->data.offset.y = SDL_ReadBE32 (src);
|
||||
break;
|
||||
case PROP_OPACITY:
|
||||
prop->data.opacity = SDL_ReadBE32 (src);
|
||||
break;
|
||||
case PROP_COMPRESSION:
|
||||
case PROP_COLOR:
|
||||
SDL_RWread (src, &prop->data, prop->length, 1);
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
prop->data.visible = SDL_ReadBE32 (src);
|
||||
break;
|
||||
default:
|
||||
// SDL_RWread (src, &prop->data, prop->length, 1);
|
||||
SDL_RWseek (src, prop->length, RW_SEEK_CUR);
|
||||
}
|
||||
}
|
||||
|
||||
static void free_xcf_header (xcf_header * h) {
|
||||
if (h->cm_num)
|
||||
SDL_free (h->cm_map);
|
||||
if (h->layer_file_offsets)
|
||||
SDL_free (h->layer_file_offsets);
|
||||
SDL_free (h);
|
||||
}
|
||||
|
||||
static xcf_header * read_xcf_header (SDL_RWops * src) {
|
||||
xcf_header * h;
|
||||
xcf_prop prop;
|
||||
|
||||
h = (xcf_header *) SDL_malloc (sizeof (xcf_header));
|
||||
SDL_RWread (src, h->sign, 14, 1);
|
||||
h->width = SDL_ReadBE32 (src);
|
||||
h->height = SDL_ReadBE32 (src);
|
||||
h->image_type = SDL_ReadBE32 (src);
|
||||
|
||||
h->properties = NULL;
|
||||
h->layer_file_offsets = NULL;
|
||||
h->compr = COMPR_NONE;
|
||||
h->cm_num = 0;
|
||||
h->cm_map = NULL;
|
||||
|
||||
// Just read, don't save
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
if (prop.id == PROP_COMPRESSION)
|
||||
h->compr = (xcf_compr_type)prop.data.compression;
|
||||
else if (prop.id == PROP_COLORMAP) {
|
||||
// unused var: int i;
|
||||
|
||||
h->cm_num = prop.data.colormap.num;
|
||||
h->cm_map = (unsigned char *) SDL_malloc (sizeof (unsigned char) * 3 * h->cm_num);
|
||||
SDL_memcpy (h->cm_map, prop.data.colormap.cmap, 3*sizeof (char)*h->cm_num);
|
||||
SDL_free (prop.data.colormap.cmap);
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void free_xcf_layer (xcf_layer * l) {
|
||||
SDL_free (l->name);
|
||||
SDL_free (l);
|
||||
}
|
||||
|
||||
static xcf_layer * read_xcf_layer (SDL_RWops * src) {
|
||||
xcf_layer * l;
|
||||
xcf_prop prop;
|
||||
|
||||
l = (xcf_layer *) SDL_malloc (sizeof (xcf_layer));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
l->layer_type = SDL_ReadBE32 (src);
|
||||
|
||||
l->name = read_string (src);
|
||||
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
if (prop.id == PROP_OFFSETS) {
|
||||
l->offset_x = prop.data.offset.x;
|
||||
l->offset_y = prop.data.offset.y;
|
||||
} else if (prop.id == PROP_VISIBLE) {
|
||||
l->visible = prop.data.visible ? 1 : 0;
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
l->hierarchy_file_offset = SDL_ReadBE32 (src);
|
||||
l->layer_mask_offset = SDL_ReadBE32 (src);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_channel (xcf_channel * c) {
|
||||
SDL_free (c->name);
|
||||
SDL_free (c);
|
||||
}
|
||||
|
||||
static xcf_channel * read_xcf_channel (SDL_RWops * src) {
|
||||
xcf_channel * l;
|
||||
xcf_prop prop;
|
||||
|
||||
l = (xcf_channel *) SDL_malloc (sizeof (xcf_channel));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
|
||||
l->name = read_string (src);
|
||||
|
||||
l->selection = 0;
|
||||
do {
|
||||
xcf_read_property (src, &prop);
|
||||
switch (prop.id) {
|
||||
case PROP_OPACITY:
|
||||
l->opacity = prop.data.opacity << 24;
|
||||
break;
|
||||
case PROP_COLOR:
|
||||
l->color = ((Uint32) prop.data.color[0] << 16)
|
||||
| ((Uint32) prop.data.color[1] << 8)
|
||||
| ((Uint32) prop.data.color[2]);
|
||||
break;
|
||||
case PROP_SELECTION:
|
||||
l->selection = 1;
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
l->visible = prop.data.visible ? 1 : 0;
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
} while (prop.id != PROP_END);
|
||||
|
||||
l->hierarchy_file_offset = SDL_ReadBE32 (src);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_hierarchy (xcf_hierarchy * h) {
|
||||
SDL_free (h->level_file_offsets);
|
||||
SDL_free (h);
|
||||
}
|
||||
|
||||
static xcf_hierarchy * read_xcf_hierarchy (SDL_RWops * src) {
|
||||
xcf_hierarchy * h;
|
||||
int i;
|
||||
|
||||
h = (xcf_hierarchy *) SDL_malloc (sizeof (xcf_hierarchy));
|
||||
h->width = SDL_ReadBE32 (src);
|
||||
h->height = SDL_ReadBE32 (src);
|
||||
h->bpp = SDL_ReadBE32 (src);
|
||||
|
||||
h->level_file_offsets = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
h->level_file_offsets = (Uint32 *) SDL_realloc (h->level_file_offsets, sizeof (Uint32) * (i+1));
|
||||
h->level_file_offsets [i] = SDL_ReadBE32 (src);
|
||||
} while (h->level_file_offsets [i++]);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
static void free_xcf_level (xcf_level * l) {
|
||||
SDL_free (l->tile_file_offsets);
|
||||
SDL_free (l);
|
||||
}
|
||||
|
||||
static xcf_level * read_xcf_level (SDL_RWops * src) {
|
||||
xcf_level * l;
|
||||
int i;
|
||||
|
||||
l = (xcf_level *) SDL_malloc (sizeof (xcf_level));
|
||||
l->width = SDL_ReadBE32 (src);
|
||||
l->height = SDL_ReadBE32 (src);
|
||||
|
||||
l->tile_file_offsets = NULL;
|
||||
i = 0;
|
||||
do {
|
||||
l->tile_file_offsets = (Uint32 *) SDL_realloc (l->tile_file_offsets, sizeof (Uint32) * (i+1));
|
||||
l->tile_file_offsets [i] = SDL_ReadBE32 (src);
|
||||
} while (l->tile_file_offsets [i++]);
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
static void free_xcf_tile (unsigned char * t) {
|
||||
SDL_free (t);
|
||||
}
|
||||
|
||||
static unsigned char * load_xcf_tile_none (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
|
||||
unsigned char * load;
|
||||
|
||||
load = (unsigned char *) SDL_malloc (len); // expect this is okay
|
||||
SDL_RWread (src, load, len, 1);
|
||||
|
||||
return load;
|
||||
}
|
||||
|
||||
static unsigned char * load_xcf_tile_rle (SDL_RWops * src, Uint32 len, int bpp, int x, int y) {
|
||||
unsigned char * load, * t, * data, * d;
|
||||
Uint32 reallen;
|
||||
int i, size, count, j, length;
|
||||
unsigned char val;
|
||||
|
||||
t = load = (unsigned char *) SDL_malloc (len);
|
||||
reallen = SDL_RWread (src, t, 1, len);
|
||||
|
||||
data = (unsigned char *) SDL_malloc (x*y*bpp);
|
||||
for (i = 0; i < bpp; i++) {
|
||||
d = data + i;
|
||||
size = x*y;
|
||||
count = 0;
|
||||
|
||||
while (size > 0) {
|
||||
val = *t++;
|
||||
|
||||
length = val;
|
||||
if (length >= 128) {
|
||||
length = 255 - (length - 1);
|
||||
if (length == 128) {
|
||||
length = (*t << 8) + t[1];
|
||||
t += 2;
|
||||
}
|
||||
|
||||
count += length;
|
||||
size -= length;
|
||||
|
||||
while (length-- > 0) {
|
||||
*d = *t++;
|
||||
d += bpp;
|
||||
}
|
||||
}
|
||||
else {
|
||||
length += 1;
|
||||
if (length == 128) {
|
||||
length = (*t << 8) + t[1];
|
||||
t += 2;
|
||||
}
|
||||
|
||||
count += length;
|
||||
size -= length;
|
||||
|
||||
val = *t++;
|
||||
|
||||
for (j = 0; j < length; j++) {
|
||||
*d = val;
|
||||
d += bpp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free (load);
|
||||
return (data);
|
||||
}
|
||||
|
||||
static Uint32 rgb2grey (Uint32 a) {
|
||||
Uint8 l;
|
||||
l = (Uint8)(0.2990 * ((a & 0x00FF0000) >> 16)
|
||||
+ 0.5870 * ((a & 0x0000FF00) >> 8)
|
||||
+ 0.1140 * ((a & 0x000000FF)));
|
||||
|
||||
return (l << 16) | (l << 8) | l;
|
||||
}
|
||||
|
||||
static void create_channel_surface (SDL_Surface * surf, xcf_image_type itype, Uint32 color, Uint32 opacity) {
|
||||
Uint32 c = 0;
|
||||
|
||||
switch (itype) {
|
||||
case IMAGE_RGB:
|
||||
case IMAGE_INDEXED:
|
||||
c = opacity | color;
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
c = opacity | rgb2grey (color);
|
||||
break;
|
||||
}
|
||||
SDL_FillRect (surf, NULL, c);
|
||||
}
|
||||
|
||||
static int do_layer_surface (SDL_Surface * surface, SDL_RWops * src, xcf_header * head, xcf_layer * layer, load_tile_type load_tile) {
|
||||
xcf_hierarchy * hierarchy;
|
||||
xcf_level * level;
|
||||
unsigned char * tile;
|
||||
Uint8 * p8;
|
||||
Uint16 * p16;
|
||||
Uint32 * p;
|
||||
int i, j;
|
||||
Uint32 x, y, tx, ty, ox, oy;
|
||||
Uint32 *row;
|
||||
|
||||
SDL_RWseek (src, layer->hierarchy_file_offset, RW_SEEK_SET);
|
||||
hierarchy = read_xcf_hierarchy (src);
|
||||
|
||||
level = NULL;
|
||||
for (i = 0; hierarchy->level_file_offsets [i]; i++) {
|
||||
SDL_RWseek (src, hierarchy->level_file_offsets [i], RW_SEEK_SET);
|
||||
level = read_xcf_level (src);
|
||||
|
||||
ty = tx = 0;
|
||||
for (j = 0; level->tile_file_offsets [j]; j++) {
|
||||
SDL_RWseek (src, level->tile_file_offsets [j], RW_SEEK_SET);
|
||||
ox = tx+64 > level->width ? level->width % 64 : 64;
|
||||
oy = ty+64 > level->height ? level->height % 64 : 64;
|
||||
|
||||
if (level->tile_file_offsets [j+1]) {
|
||||
tile = load_tile
|
||||
(src,
|
||||
level->tile_file_offsets [j+1] - level->tile_file_offsets [j],
|
||||
hierarchy->bpp,
|
||||
ox, oy);
|
||||
}
|
||||
else {
|
||||
tile = load_tile
|
||||
(src,
|
||||
ox*oy*6,
|
||||
hierarchy->bpp,
|
||||
ox, oy);
|
||||
}
|
||||
|
||||
p8 = tile;
|
||||
p16 = (Uint16 *) p8;
|
||||
p = (Uint32 *) p8;
|
||||
for (y=ty; y < ty+oy; y++) {
|
||||
row = (Uint32 *)((Uint8 *)surface->pixels + y*surface->pitch + tx*4);
|
||||
switch (hierarchy->bpp) {
|
||||
case 4:
|
||||
for (x=tx; x < tx+ox; x++)
|
||||
*row++ = Swap32 (*p++);
|
||||
break;
|
||||
case 3:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = 0xFF000000;
|
||||
*row |= ((Uint32) *(p8++) << 16);
|
||||
*row |= ((Uint32) *(p8++) << 8);
|
||||
*row |= ((Uint32) *(p8++) << 0);
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
case 2: // Indexed/Greyscale + Alpha
|
||||
switch (head->image_type) {
|
||||
case IMAGE_INDEXED:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = ((Uint32) (head->cm_map [*p8*3]) << 16);
|
||||
*row |= ((Uint32) (head->cm_map [*p8*3+1]) << 8);
|
||||
*row |= ((Uint32) (head->cm_map [*p8++*3+2]) << 0);
|
||||
*row |= ((Uint32) *p8++ << 24);;
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row = ((Uint32) *p8 << 16);
|
||||
*row |= ((Uint32) *p8 << 8);
|
||||
*row |= ((Uint32) *p8++ << 0);
|
||||
*row |= ((Uint32) *p8++ << 24);;
|
||||
row++;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
|
||||
if (hierarchy)
|
||||
{
|
||||
if (hierarchy->level_file_offsets)
|
||||
SDL_free(hierarchy->level_file_offsets);
|
||||
|
||||
free_xcf_hierarchy(hierarchy);
|
||||
}
|
||||
if (level)
|
||||
free_xcf_level (level);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 1: // Indexed/Greyscale
|
||||
switch (head->image_type) {
|
||||
case IMAGE_INDEXED:
|
||||
for (x = tx; x < tx+ox; x++) {
|
||||
*row++ = 0xFF000000
|
||||
| ((Uint32) (head->cm_map [*p8*3]) << 16)
|
||||
| ((Uint32) (head->cm_map [*p8*3+1]) << 8)
|
||||
| ((Uint32) (head->cm_map [*p8*3+2]) << 0);
|
||||
p8++;
|
||||
}
|
||||
break;
|
||||
case IMAGE_GREYSCALE:
|
||||
for (x=tx; x < tx+ox; x++) {
|
||||
*row++ = 0xFF000000
|
||||
| (((Uint32) (*p8)) << 16)
|
||||
| (((Uint32) (*p8)) << 8)
|
||||
| (((Uint32) (*p8)) << 0);
|
||||
++p8;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unknown Gimp image type (%d)\n", head->image_type);
|
||||
if (tile)
|
||||
free_xcf_tile (tile);
|
||||
if (level)
|
||||
free_xcf_level (level);
|
||||
if (hierarchy)
|
||||
free_xcf_hierarchy (hierarchy);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
tx += 64;
|
||||
if (tx >= level->width) {
|
||||
tx = 0;
|
||||
ty += 64;
|
||||
}
|
||||
if (ty >= level->height) {
|
||||
break;
|
||||
}
|
||||
|
||||
free_xcf_tile (tile);
|
||||
}
|
||||
free_xcf_level (level);
|
||||
}
|
||||
|
||||
free_xcf_hierarchy (hierarchy);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface, *lays;
|
||||
xcf_header * head;
|
||||
xcf_layer * layer;
|
||||
xcf_channel ** channel;
|
||||
int chnls, i, offsets;
|
||||
Sint64 offset, fp;
|
||||
|
||||
unsigned char * (* load_tile) (SDL_RWops *, Uint32, int, int, int);
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Initialize the data we will clean up when we're done */
|
||||
surface = NULL;
|
||||
|
||||
head = read_xcf_header (src);
|
||||
|
||||
switch (head->compr) {
|
||||
case COMPR_NONE:
|
||||
load_tile = load_xcf_tile_none;
|
||||
break;
|
||||
case COMPR_RLE:
|
||||
load_tile = load_xcf_tile_rle;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr, "Unsupported Compression.\n");
|
||||
free_xcf_header (head);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the surface of the appropriate type */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if ( surface == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
offsets = 0;
|
||||
|
||||
while ((offset = SDL_ReadBE32 (src))) {
|
||||
head->layer_file_offsets = (Uint32 *) SDL_realloc (head->layer_file_offsets, sizeof (Uint32) * (offsets+1));
|
||||
head->layer_file_offsets [offsets] = (Uint32)offset;
|
||||
offsets++;
|
||||
}
|
||||
fp = SDL_RWtell (src);
|
||||
|
||||
lays = SDL_CreateRGBSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if ( lays == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
// Blit layers backwards, because Gimp saves them highest first
|
||||
for (i = offsets; i > 0; i--) {
|
||||
SDL_Rect rs, rd;
|
||||
SDL_RWseek (src, head->layer_file_offsets [i-1], RW_SEEK_SET);
|
||||
|
||||
layer = read_xcf_layer (src);
|
||||
do_layer_surface (lays, src, head, layer, load_tile);
|
||||
rs.x = 0;
|
||||
rs.y = 0;
|
||||
rs.w = layer->width;
|
||||
rs.h = layer->height;
|
||||
rd.x = layer->offset_x;
|
||||
rd.y = layer->offset_y;
|
||||
rd.w = layer->width;
|
||||
rd.h = layer->height;
|
||||
|
||||
if (layer->visible)
|
||||
SDL_BlitSurface (lays, &rs, surface, &rd);
|
||||
free_xcf_layer (layer);
|
||||
}
|
||||
|
||||
SDL_FreeSurface (lays);
|
||||
|
||||
SDL_RWseek (src, fp, RW_SEEK_SET);
|
||||
|
||||
// read channels
|
||||
channel = NULL;
|
||||
chnls = 0;
|
||||
while ((offset = SDL_ReadBE32 (src))) {
|
||||
channel = (xcf_channel **) SDL_realloc (channel, sizeof (xcf_channel *) * (chnls+1));
|
||||
fp = SDL_RWtell (src);
|
||||
SDL_RWseek (src, offset, RW_SEEK_SET);
|
||||
channel [chnls++] = (read_xcf_channel (src));
|
||||
SDL_RWseek (src, fp, RW_SEEK_SET);
|
||||
}
|
||||
|
||||
if (chnls) {
|
||||
SDL_Surface * chs;
|
||||
|
||||
chs = SDL_CreateRGBSurface(SDL_SWSURFACE, head->width, head->height, 32,
|
||||
0x00FF0000,0x0000FF00,0x000000FF,0xFF000000);
|
||||
|
||||
if (chs == NULL) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
for (i = 0; i < chnls; i++) {
|
||||
// printf ("CNLBLT %i\n", i);
|
||||
if (!channel [i]->selection && channel [i]->visible) {
|
||||
create_channel_surface (chs, (xcf_image_type)head->image_type, channel [i]->color, channel [i]->opacity);
|
||||
SDL_BlitSurface (chs, NULL, surface, NULL);
|
||||
}
|
||||
free_xcf_channel (channel [i]);
|
||||
}
|
||||
|
||||
SDL_FreeSurface (chs);
|
||||
}
|
||||
|
||||
done:
|
||||
free_xcf_header (head);
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
|
||||
return(surface);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXCF(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XCF type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXCF_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XCF */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a XV thumbnail image file loading framework */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XV
|
||||
|
||||
static int get_line(SDL_RWops *src, char *line, int size)
|
||||
{
|
||||
while ( size > 0 ) {
|
||||
if ( SDL_RWread(src, line, 1, 1) <= 0 ) {
|
||||
return -1;
|
||||
}
|
||||
if ( *line == '\r' ) {
|
||||
continue;
|
||||
}
|
||||
if ( *line == '\n' ) {
|
||||
*line = '\0';
|
||||
return 0;
|
||||
}
|
||||
++line;
|
||||
--size;
|
||||
}
|
||||
/* Out of space for the line */
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int get_header(SDL_RWops *src, int *w, int *h)
|
||||
{
|
||||
char line[1024];
|
||||
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
|
||||
/* Check the header magic */
|
||||
if ( (get_line(src, line, sizeof(line)) < 0) ||
|
||||
(SDL_memcmp(line, "P7 332", 6) != 0) ) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read the header */
|
||||
while ( get_line(src, line, sizeof(line)) == 0 ) {
|
||||
if ( SDL_memcmp(line, "#BUILTIN:", 9) == 0 ) {
|
||||
/* Builtin image, no data */
|
||||
break;
|
||||
}
|
||||
if ( SDL_memcmp(line, "#END_OF_COMMENTS", 16) == 0 ) {
|
||||
if ( get_line(src, line, sizeof(line)) == 0 ) {
|
||||
SDL_sscanf(line, "%d %d", w, h);
|
||||
if ( *w >= 0 && *h >= 0 ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* No image data */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXV(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
int is_XV;
|
||||
int w, h;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XV = 0;
|
||||
if ( get_header(src, &w, &h) == 0 ) {
|
||||
is_XV = 1;
|
||||
}
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XV);
|
||||
}
|
||||
|
||||
/* Load a XV thumbnail image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src)
|
||||
{
|
||||
Sint64 start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface = NULL;
|
||||
int w, h;
|
||||
Uint8 *pixels;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Read the header */
|
||||
if ( get_header(src, &w, &h) < 0 ) {
|
||||
error = "Unsupported image format";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Create the 3-3-2 indexed palette surface */
|
||||
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0xe0, 0x1c, 0x03, 0);
|
||||
if ( surface == NULL ) {
|
||||
error = "Out of memory";
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Load the image data */
|
||||
for ( pixels = (Uint8 *)surface->pixels; h > 0; --h ) {
|
||||
if ( SDL_RWread(src, pixels, w, 1) <= 0 ) {
|
||||
error = "Couldn't read image data";
|
||||
goto done;
|
||||
}
|
||||
pixels += surface->pitch;
|
||||
}
|
||||
|
||||
done:
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXV(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XXX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXV_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XV */
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* This is a generic "format not supported" image framework */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "SDL_image.h"
|
||||
|
||||
#ifdef LOAD_XXX
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXXX(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
int is_XXX;
|
||||
|
||||
if ( !src )
|
||||
return 0;
|
||||
start = SDL_RWtell(src);
|
||||
is_XXX = 0;
|
||||
|
||||
/* Detect the image here */
|
||||
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
return(is_XXX);
|
||||
}
|
||||
|
||||
/* Load a XXX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src)
|
||||
{
|
||||
int start;
|
||||
const char *error = NULL;
|
||||
SDL_Surface *surface = NULL;
|
||||
|
||||
if ( !src ) {
|
||||
/* The error message has been set in SDL_RWFromFile */
|
||||
return NULL;
|
||||
}
|
||||
start = SDL_RWtell(src);
|
||||
|
||||
/* Load the image here */
|
||||
|
||||
if ( error ) {
|
||||
SDL_RWseek(src, start, RW_SEEK_SET);
|
||||
if ( surface ) {
|
||||
SDL_FreeSurface(surface);
|
||||
surface = NULL;
|
||||
}
|
||||
IMG_SetError(error);
|
||||
}
|
||||
return surface;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* See if an image is contained in a data source */
|
||||
int IMG_isXXX(SDL_RWops *src)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Load a XXX type image from an SDL datasource */
|
||||
SDL_Surface *IMG_LoadXXX_RW(SDL_RWops *src)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#endif /* LOAD_XXX */
|
||||
@@ -0,0 +1,40 @@
|
||||
|
||||
SDL_image 2.0
|
||||
|
||||
The latest version of this library is available from:
|
||||
http://www.libsdl.org/projects/SDL_image/
|
||||
|
||||
This is a simple library to load images of various formats as SDL surfaces.
|
||||
This library supports BMP, PNM (PPM/PGM/PBM), XPM, LBM, PCX, GIF, JPEG, PNG,
|
||||
TGA, and TIFF formats.
|
||||
|
||||
API:
|
||||
#include "SDL_image.h"
|
||||
|
||||
SDL_Surface *IMG_Load(const char *file);
|
||||
or
|
||||
SDL_Surface *IMG_Load_RW(SDL_RWops *src, int freesrc);
|
||||
or
|
||||
SDL_Surface *IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, char *type);
|
||||
|
||||
where type is a string specifying the format (i.e. "PNG" or "pcx").
|
||||
Note that IMG_Load_RW cannot load TGA images.
|
||||
|
||||
To create a surface from an XPM image included in C source, use:
|
||||
|
||||
SDL_Surface *IMG_ReadXPMFromArray(char **xpm);
|
||||
|
||||
An example program 'showimage' is included, with source in showimage.c
|
||||
|
||||
JPEG support requires the JPEG library: http://www.ijg.org/
|
||||
PNG support requires the PNG library: http://www.libpng.org/pub/png/libpng.html
|
||||
and the Zlib library: http://www.gzip.org/zlib/
|
||||
TIFF support requires the TIFF library: ftp://ftp.sgi.com/graphics/tiff/
|
||||
|
||||
If you have these libraries installed in non-standard places, you can
|
||||
try adding those paths to the configure script, e.g.
|
||||
sh ./configure CPPFLAGS="-I/somewhere/include" LDFLAGS="-L/somewhere/lib"
|
||||
If this works, you may need to add /somewhere/lib to your LD_LIBRARY_PATH
|
||||
so shared library loading works correctly.
|
||||
|
||||
This library is under the zlib License, see the file "COPYING.txt" for details.
|
||||
+1
@@ -0,0 +1 @@
|
||||
.
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
SDL_image: An example image loading library for use with SDL
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
/* A simple library to load images of various formats as SDL surfaces */
|
||||
|
||||
#ifndef _SDL_IMAGE_H
|
||||
#define _SDL_IMAGE_H
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_version.h"
|
||||
#include "begin_code.h"
|
||||
|
||||
/* Set up for C function definitions, even when using C++ */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL
|
||||
*/
|
||||
#define SDL_IMAGE_MAJOR_VERSION 2
|
||||
#define SDL_IMAGE_MINOR_VERSION 0
|
||||
#define SDL_IMAGE_PATCHLEVEL 0
|
||||
|
||||
/* This macro can be used to fill a version structure with the compile-time
|
||||
* version of the SDL_image library.
|
||||
*/
|
||||
#define SDL_IMAGE_VERSION(X) \
|
||||
{ \
|
||||
(X)->major = SDL_IMAGE_MAJOR_VERSION; \
|
||||
(X)->minor = SDL_IMAGE_MINOR_VERSION; \
|
||||
(X)->patch = SDL_IMAGE_PATCHLEVEL; \
|
||||
}
|
||||
|
||||
/* This function gets the version of the dynamically linked SDL_image library.
|
||||
it should NOT be used to fill a version structure, instead you should
|
||||
use the SDL_IMAGE_VERSION() macro.
|
||||
*/
|
||||
extern DECLSPEC const SDL_version * SDLCALL IMG_Linked_Version(void);
|
||||
|
||||
typedef enum
|
||||
{
|
||||
IMG_INIT_JPG = 0x00000001,
|
||||
IMG_INIT_PNG = 0x00000002,
|
||||
IMG_INIT_TIF = 0x00000004,
|
||||
IMG_INIT_WEBP = 0x00000008
|
||||
} IMG_InitFlags;
|
||||
|
||||
/* Loads dynamic libraries and prepares them for use. Flags should be
|
||||
one or more flags from IMG_InitFlags OR'd together.
|
||||
It returns the flags successfully initialized, or 0 on failure.
|
||||
*/
|
||||
extern DECLSPEC int SDLCALL IMG_Init(int flags);
|
||||
|
||||
/* Unloads libraries loaded with IMG_Init */
|
||||
extern DECLSPEC void SDLCALL IMG_Quit(void);
|
||||
|
||||
/* Load an image from an SDL data source.
|
||||
The 'type' may be one of: "BMP", "GIF", "PNG", etc.
|
||||
|
||||
If the image format supports a transparent pixel, SDL will set the
|
||||
colorkey for the surface. You can enable RLE acceleration on the
|
||||
surface afterwards by calling:
|
||||
SDL_SetColorKey(image, SDL_RLEACCEL, image->format->colorkey);
|
||||
*/
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTyped_RW(SDL_RWops *src, int freesrc, const char *type);
|
||||
/* Convenience functions */
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_Load(const char *file);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_Load_RW(SDL_RWops *src, int freesrc);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2,0,0)
|
||||
/* Load an image directly into a render texture.
|
||||
*/
|
||||
extern DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture(SDL_Renderer *renderer, const char *file);
|
||||
extern DECLSPEC SDL_Texture * SDLCALL IMG_LoadTexture_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc);
|
||||
extern DECLSPEC SDL_Texture * SDLCALL IMG_LoadTextureTyped_RW(SDL_Renderer *renderer, SDL_RWops *src, int freesrc, const char *type);
|
||||
#endif /* SDL 2.0 */
|
||||
|
||||
/* Functions to detect a file type, given a seekable source */
|
||||
extern DECLSPEC int SDLCALL IMG_isICO(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isCUR(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isBMP(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isGIF(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isJPG(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isLBM(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isPCX(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isPNG(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isPNM(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isTIF(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isXCF(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isXPM(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isXV(SDL_RWops *src);
|
||||
extern DECLSPEC int SDLCALL IMG_isWEBP(SDL_RWops *src);
|
||||
|
||||
/* Individual loading functions */
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadICO_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadCUR_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadBMP_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadGIF_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadJPG_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadLBM_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXPM_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXV_RW(SDL_RWops *src);
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadWEBP_RW(SDL_RWops *src);
|
||||
|
||||
extern DECLSPEC SDL_Surface * SDLCALL IMG_ReadXPMFromArray(char **xpm);
|
||||
|
||||
/* Individual saving functions */
|
||||
extern DECLSPEC int SDLCALL IMG_SavePNG(SDL_Surface *surface, const char *file);
|
||||
extern DECLSPEC int SDLCALL IMG_SavePNG_RW(SDL_Surface *surface, SDL_RWops *dst, int freedst);
|
||||
|
||||
/* We'll use SDL for reporting errors */
|
||||
#define IMG_SetError SDL_SetError
|
||||
#define IMG_GetError SDL_GetError
|
||||
|
||||
/* Ends C function definitions when using C++ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#include "close_code.h"
|
||||
|
||||
#endif /* _SDL_IMAGE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
showimage: A test application for the SDL image loading library.
|
||||
Copyright (C) 1997-2013 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_image.h"
|
||||
|
||||
|
||||
/* Draw a Gimpish background pattern to show transparency in the image */
|
||||
static void draw_background(SDL_Renderer *renderer, int w, int h)
|
||||
{
|
||||
SDL_Color col[2] = {
|
||||
{ 0x66, 0x66, 0x66, 0xff },
|
||||
{ 0x99, 0x99, 0x99, 0xff },
|
||||
};
|
||||
int i, x, y;
|
||||
SDL_Rect rect;
|
||||
|
||||
rect.w = 8;
|
||||
rect.h = 8;
|
||||
for (y = 0; y < h; y += rect.h) {
|
||||
for (x = 0; x < w; x += rect.w) {
|
||||
/* use an 8x8 checkerboard pattern */
|
||||
i = (((x ^ y) >> 3) & 1);
|
||||
SDL_SetRenderDrawColor(renderer, col[i].r, col[i].g, col[i].b, col[i].a);
|
||||
|
||||
rect.x = x;
|
||||
rect.y = y;
|
||||
SDL_RenderFillRect(renderer, &rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SDL_Window *window;
|
||||
SDL_Renderer *renderer;
|
||||
SDL_Texture *texture;
|
||||
Uint32 flags;
|
||||
int i, w, h, done;
|
||||
SDL_Event event;
|
||||
const char *saveFile = NULL;
|
||||
|
||||
/* Check command line usage */
|
||||
if ( ! argv[1] ) {
|
||||
fprintf(stderr, "Usage: %s [-fullscreen] [-save file.png] <image_file> ...\n", argv[0]);
|
||||
return(1);
|
||||
}
|
||||
|
||||
flags = SDL_WINDOW_HIDDEN;
|
||||
for ( i=1; argv[i]; ++i ) {
|
||||
if ( strcmp(argv[i], "-fullscreen") == 0 ) {
|
||||
SDL_ShowCursor(0);
|
||||
flags |= SDL_WINDOW_FULLSCREEN;
|
||||
}
|
||||
}
|
||||
|
||||
if (SDL_CreateWindowAndRenderer(0, 0, flags, &window, &renderer) < 0) {
|
||||
fprintf(stderr, "SDL_CreateWindowAndRenderer() failed: %s\n", SDL_GetError());
|
||||
return(2);
|
||||
}
|
||||
|
||||
for ( i=1; argv[i]; ++i ) {
|
||||
if ( strcmp(argv[i], "-fullscreen") == 0 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( strcmp(argv[i], "-save") == 0 && argv[i+1] ) {
|
||||
++i;
|
||||
saveFile = argv[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Open the image file */
|
||||
texture = IMG_LoadTexture(renderer, argv[i]);
|
||||
if (!texture) {
|
||||
fprintf(stderr, "Couldn't load %s: %s\n", argv[i], SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
SDL_QueryTexture(texture, NULL, NULL, &w, &h);
|
||||
|
||||
/* Save the image file, if desired */
|
||||
if ( saveFile ) {
|
||||
SDL_Surface *surface = IMG_Load(argv[i]);
|
||||
if (surface) {
|
||||
if ( IMG_SavePNG(surface, saveFile) < 0 ) {
|
||||
fprintf(stderr, "Couldn't save %s: %s\n", saveFile, SDL_GetError());
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Couldn't load %s: %s\n", argv[i], SDL_GetError());
|
||||
}
|
||||
}
|
||||
|
||||
/* Show the window */
|
||||
SDL_SetWindowTitle(window, argv[i]);
|
||||
SDL_SetWindowSize(window, w, h);
|
||||
SDL_ShowWindow(window);
|
||||
|
||||
done = 0;
|
||||
while ( ! done ) {
|
||||
while ( SDL_PollEvent(&event) ) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYUP:
|
||||
switch (event.key.keysym.sym) {
|
||||
case SDLK_LEFT:
|
||||
if ( i > 1 ) {
|
||||
i -= 2;
|
||||
done = 1;
|
||||
}
|
||||
break;
|
||||
case SDLK_RIGHT:
|
||||
if ( argv[i+1] ) {
|
||||
done = 1;
|
||||
}
|
||||
break;
|
||||
case SDLK_ESCAPE:
|
||||
case SDLK_q:
|
||||
argv[i+1] = NULL;
|
||||
/* Drop through to done */
|
||||
case SDLK_SPACE:
|
||||
case SDLK_TAB:
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
done = 1;
|
||||
break;
|
||||
case SDL_QUIT:
|
||||
argv[i+1] = NULL;
|
||||
done = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Draw a background pattern in case the image has transparency */
|
||||
draw_background(renderer, w, h);
|
||||
|
||||
/* Display the image */
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
|
||||
SDL_Delay(100);
|
||||
}
|
||||
SDL_DestroyTexture(texture);
|
||||
}
|
||||
|
||||
/* We're done! */
|
||||
SDL_Quit();
|
||||
return(0);
|
||||
}
|
||||
Reference in New Issue
Block a user