Use built-in compiler defines to detect SSE support.
Remove SSE tests from SConstruct. Minimize libimagequant files.
This commit is contained in:
parent
d0c1bed5a5
commit
40be65c947
33 changed files with 38 additions and 3063 deletions
35
SConstruct
35
SConstruct
|
@ -297,7 +297,6 @@ opts.AddVariables(
|
||||||
('CUSTOM_DEFINES', 'Custom Compiler DEFINES, e.g. -DENABLE_THIS', ''),
|
('CUSTOM_DEFINES', 'Custom Compiler DEFINES, e.g. -DENABLE_THIS', ''),
|
||||||
('CUSTOM_CFLAGS', 'Custom C flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> (only used for configure checks)', ''),
|
('CUSTOM_CFLAGS', 'Custom C flags, e.g. -I<include dir> if you have headers in a nonstandard directory <include dir> (only used for configure checks)', ''),
|
||||||
('CUSTOM_LDFLAGS', 'Custom linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir>', ''),
|
('CUSTOM_LDFLAGS', 'Custom linker flags, e.g. -L<lib dir> if you have libraries in a nonstandard directory <lib dir>', ''),
|
||||||
EnumVariable('USE_SSE', "Build with SSE instruction set (will default to 'no' if cross-compiling)",'detect', ['detect','yes','no']),
|
|
||||||
EnumVariable('LINKING', "Set library format for libmapnik",'shared', ['shared','static']),
|
EnumVariable('LINKING', "Set library format for libmapnik",'shared', ['shared','static']),
|
||||||
EnumVariable('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']),
|
EnumVariable('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']),
|
||||||
EnumVariable('OPTIMIZATION','Set compiler optimization level','3', ['0','1','2','3','4','s']),
|
EnumVariable('OPTIMIZATION','Set compiler optimization level','3', ['0','1','2','3','4','s']),
|
||||||
|
@ -1216,38 +1215,6 @@ if not preconfigured:
|
||||||
env.Append(LINKFLAGS = DEFAULT_CXX11_LINKFLAGS)
|
env.Append(LINKFLAGS = DEFAULT_CXX11_LINKFLAGS)
|
||||||
env.Append(LINKFLAGS = env['CUSTOM_LDFLAGS'])
|
env.Append(LINKFLAGS = env['CUSTOM_LDFLAGS'])
|
||||||
|
|
||||||
### platform specific bits
|
|
||||||
#
|
|
||||||
# libimagequant includes SSE optimizations, so detect if flag is set (USE_SSE)
|
|
||||||
# or if 'detect', check current machine for support
|
|
||||||
SSE_DETECTED = False
|
|
||||||
if "darwin" in sys.platform:
|
|
||||||
import subprocess
|
|
||||||
process = subprocess.Popen(["sysctl","-a"], stdout=subprocess.PIPE)
|
|
||||||
result = process.communicate()[0]
|
|
||||||
for line in result.split("\n"):
|
|
||||||
if "cpu.feature" in line and "SSE" in line:
|
|
||||||
if "USE_SSE" in env and env["USE_SSE"] == "detect":
|
|
||||||
color_print(4,'SSE detected on Darwin host')
|
|
||||||
SSE_DETECTED = True
|
|
||||||
break
|
|
||||||
elif "linux" in sys.platform:
|
|
||||||
for line in open("/proc/cpuinfo"):
|
|
||||||
if "flags" in line and "sse" in line:
|
|
||||||
if "USE_SSE" in env and env["USE_SSE"] == "detect":
|
|
||||||
color_print(4,'SSE detected on Linux host')
|
|
||||||
SSE_DETECTED = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if "USE_SSE" in env and env["USE_SSE"] == "detect":
|
|
||||||
color_print(4,'SSE detection not implemented on this platform, building without SSE')
|
|
||||||
|
|
||||||
# Only enable SSE when explitily set, or when not cross compiling and current host supports it
|
|
||||||
if (not env["HOST"] and (env["USE_SSE"] == "detect" and SSE_DETECTED)) or env["USE_SSE"] == "yes":
|
|
||||||
env.Append(CFLAGS = '-DUSE_SSE -msse')
|
|
||||||
if 'gcc' in env['CC']:
|
|
||||||
lib_env.Append(CFLAGS='-mfpmath=sse')
|
|
||||||
|
|
||||||
thread_suffix = 'mt'
|
thread_suffix = 'mt'
|
||||||
if env['PLATFORM'] == 'FreeBSD':
|
if env['PLATFORM'] == 'FreeBSD':
|
||||||
thread_suffix = ''
|
thread_suffix = ''
|
||||||
|
@ -1626,7 +1593,7 @@ if not preconfigured:
|
||||||
# prepend to make sure we link locally
|
# prepend to make sure we link locally
|
||||||
env.Prepend(CPPPATH = '#deps/agg/include')
|
env.Prepend(CPPPATH = '#deps/agg/include')
|
||||||
env.Prepend(LIBPATH = '#deps/agg')
|
env.Prepend(LIBPATH = '#deps/agg')
|
||||||
env.Prepend(CPPPATH = '#deps/pngquant/lib')
|
env.Prepend(CPPPATH = '#deps/pngquant')
|
||||||
env.Prepend(CPPPATH = '#deps/clipper/include')
|
env.Prepend(CPPPATH = '#deps/clipper/include')
|
||||||
# prepend deps dir for auxillary headers
|
# prepend deps dir for auxillary headers
|
||||||
env.Prepend(CPPPATH = '#deps')
|
env.Prepend(CPPPATH = '#deps')
|
||||||
|
|
11
deps/pngquant/.gitignore
vendored
11
deps/pngquant/.gitignore
vendored
|
@ -1,11 +0,0 @@
|
||||||
*.dylib
|
|
||||||
*.mode1v3
|
|
||||||
*.o
|
|
||||||
*.pbxproj
|
|
||||||
*.pbxuser
|
|
||||||
build
|
|
||||||
DerivedData
|
|
||||||
pngquant
|
|
||||||
build_configuration
|
|
||||||
lib/libimagequant.a
|
|
||||||
config.mk
|
|
125
deps/pngquant/CHANGELOG
vendored
125
deps/pngquant/CHANGELOG
vendored
|
@ -1,125 +0,0 @@
|
||||||
version 2.4
|
|
||||||
-----------
|
|
||||||
- fixed remapping of bright colors when dithering
|
|
||||||
- added libimagequant API to add fixed preset colors to the palette
|
|
||||||
|
|
||||||
version 2.3
|
|
||||||
-----------
|
|
||||||
- added ./configure script for better support of Intel C compiler and dependencies [thanks to pdknsk]
|
|
||||||
- tweaked quality metric to better estimate quality of images with large solid backgrounds [thanks to Rolf Timmermans]
|
|
||||||
- atomic file saves and fixed --skip-if-larger
|
|
||||||
- avoid applying quality setting to images that use palette already
|
|
||||||
- preserving standard PNG chunks (requires libpng 1.6)
|
|
||||||
- deprecated libpng 1.2 support
|
|
||||||
|
|
||||||
version 2.2
|
|
||||||
-----------
|
|
||||||
- preserving of unknown PNG chunks (enables optimized Android 9-patch images)
|
|
||||||
- improved color profile support: cHRM & gAMA as alternative to ICC profiles, OpenMP acceleration
|
|
||||||
- improved support for Intel C Compiler, speedup in 32-bit GCC, and some workarounds for Visual Studio's incomplete C support
|
|
||||||
|
|
||||||
version 2.1
|
|
||||||
-----------
|
|
||||||
- option to save files only if they're compressed better than the original
|
|
||||||
- option to generate posterized output (for use with 16-bit textures)
|
|
||||||
- support for ICC profiles via Little CMS library
|
|
||||||
|
|
||||||
version 2.0
|
|
||||||
-----------
|
|
||||||
- refactored codebase into pngquant and standalone libimagequant
|
|
||||||
- reduced memory usage by further 30% (and more for very large images)
|
|
||||||
- less precise remapping improving speed by 25% in higher speed settings
|
|
||||||
- --output option for writing converted file under the given path
|
|
||||||
- light dithering with --floyd=0.5
|
|
||||||
- fixed regression in dithering of alpha channel
|
|
||||||
|
|
||||||
version 1.8
|
|
||||||
-----------
|
|
||||||
- min/max quality option (number of colors is automatically adjusted for desired quality level)
|
|
||||||
- switched option parsing to getopt_long (syntax such as -s1 and --ext=ext is supported)
|
|
||||||
- significantly improved performance thanks to custom partial sorting
|
|
||||||
- optional Cocoa (Mac OS X) image reader for color profile support
|
|
||||||
- reduced memory usage by 20%
|
|
||||||
- remapping improved for very low number of colors
|
|
||||||
|
|
||||||
version 1.7
|
|
||||||
-----------
|
|
||||||
- new, accurate RGBA color similarity algorithm
|
|
||||||
- change of optional SSE3 code to SSE2 that is always enabled on x86-64
|
|
||||||
- optional OpenMP-based parallelisation of remapping
|
|
||||||
- changed long options to use double hyphen (-force to --force) [thanks to Jari Aalto]
|
|
||||||
|
|
||||||
version 1.6
|
|
||||||
-----------
|
|
||||||
- novel dithering algorithm that doesn't add noise unless necessary
|
|
||||||
- perceptual weighting of colors taking into account edges and noise
|
|
||||||
- much faster remapping
|
|
||||||
- improved portability, makefiles and man page
|
|
||||||
|
|
||||||
version 1.5
|
|
||||||
-----------
|
|
||||||
- palettes postprocessed with Voronoi iteration
|
|
||||||
- better RGBA color similarity algorithm and Floyd-Steinberg remapping
|
|
||||||
- SSE optimisations
|
|
||||||
|
|
||||||
version 1.4
|
|
||||||
-----------
|
|
||||||
- median cut is applied many times in a feedback loop
|
|
||||||
- speed/quality trade-off option
|
|
||||||
- faster remap of transparent areas
|
|
||||||
|
|
||||||
version 1.3
|
|
||||||
-----------
|
|
||||||
- significant changes to the algorithm: use of variance
|
|
||||||
to find largest dimensioin and to split most varying boxes
|
|
||||||
- use of premultiplied alpha for color blending
|
|
||||||
- conversion of output to gamma 2.2
|
|
||||||
|
|
||||||
version 1.2
|
|
||||||
-----------
|
|
||||||
- color computation done in floating point
|
|
||||||
- gamma correction applied
|
|
||||||
- dropped support for very old systems & compilers
|
|
||||||
|
|
||||||
version 1.1
|
|
||||||
-----------
|
|
||||||
- alpha-sensitive color reduction and dithering
|
|
||||||
- support -- and - arguments in command line
|
|
||||||
- number of colors optional (defaults to 256)
|
|
||||||
- increased maximum number of colors in histogram
|
|
||||||
|
|
||||||
version 1.0
|
|
||||||
-----------
|
|
||||||
- cleaned up Makefile.unx (better gcc optimizations, "clean" target)
|
|
||||||
- recompiled binaries with zlib 1.1.4
|
|
||||||
|
|
||||||
version 0.95
|
|
||||||
------------
|
|
||||||
- fixed Win32 filter bug (binary mode for stdin/stdout)
|
|
||||||
- fixed cosmetic "choosing colors" verbosity buglet
|
|
||||||
- fixed palette-size bug when number of colors in image < number requested
|
|
||||||
- fixed sample-depth bug (png_set_packing() not retroactively smart)
|
|
||||||
|
|
||||||
version 0.91
|
|
||||||
------------
|
|
||||||
- fixed some verbose/non-verbose oopers
|
|
||||||
- fixed Win32 (MSVC) portability issues (getpid(), random(), srandom())
|
|
||||||
- added Makefile.w32 for MSVC (tested with 5.0)
|
|
||||||
|
|
||||||
version 0.90
|
|
||||||
------------
|
|
||||||
- added support for multiple files on command line
|
|
||||||
- changed stdin support to write PNG stream to stdout (not "stdin-fs8.png")
|
|
||||||
|
|
||||||
version 0.75
|
|
||||||
------------
|
|
||||||
- added support for any type of input file [Glenn Randers-Pehrson]
|
|
||||||
- fixed palette-(re)scaling bug
|
|
||||||
- added -verbose and -quiet options (default now is -quiet)
|
|
||||||
- added palette-remapping to minimize size of tRNS chunk
|
|
||||||
- made Floyd-Steinberg dithering default
|
|
||||||
- changed output naming scheme to -fs8.png and -or8.png (FS or ordered dither)
|
|
||||||
|
|
||||||
version 0.70
|
|
||||||
------------
|
|
||||||
- first public release
|
|
80
deps/pngquant/COPYRIGHT
vendored
80
deps/pngquant/COPYRIGHT
vendored
|
@ -1,56 +1,36 @@
|
||||||
The quantization and dithering code in pngquant is lifted from Jef Poskanzer's
|
© 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
|
||||||
'ppmquant', part of his wonderful PBMPLUS tool suite.
|
© 2009-2014 by Kornel Lesiński.
|
||||||
|
|
||||||
Greg Roelofs hacked it into a (in his words) "slightly cheesy" 'pamquant' back
|
All rights reserved.
|
||||||
in 1997 (see http://pobox.com/~newt/greg_rgba.html) and finally he ripped out
|
|
||||||
the cheesy file-I/O parts and replaced them with nice PNG code in December
|
|
||||||
2000. The PNG reading and writing code is a merged and slightly simplified
|
|
||||||
version of readpng, readpng2, and writepng from his book "PNG: The Definitive
|
|
||||||
Guide."
|
|
||||||
In 2014 Greg has relicensed the code under the simplified BSD license.
|
|
||||||
|
|
||||||
Note that both licenses are basically BSD-like; that is, use the code however
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
you like, as long as you acknowledge its origins.
|
are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
pngquant.c:
|
© 1989, 1991 by Jef Poskanzer.
|
||||||
|
|
||||||
© 1989, 1991 by Jef Poskanzer.
|
Permission to use, copy, modify, and distribute this software and its
|
||||||
|
documentation for any purpose and without fee is hereby granted, provided
|
||||||
Permission to use, copy, modify, and distribute this software and its
|
that the above copyright notice appear in all copies and that both that
|
||||||
documentation for any purpose and without fee is hereby granted, provided
|
copyright notice and this permission notice appear in supporting
|
||||||
that the above copyright notice appear in all copies and that both that
|
documentation. This software is provided "as is" without express or
|
||||||
copyright notice and this permission notice appear in supporting
|
implied warranty.
|
||||||
documentation. This software is provided "as is" without express or
|
|
||||||
implied warranty.
|
|
||||||
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
|
|
||||||
pngquant.c and rwpng.c/h:
|
|
||||||
|
|
||||||
© 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
|
|
||||||
© 2009-2014 by Kornel Lesiński.
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
55
deps/pngquant/INSTALL
vendored
55
deps/pngquant/INSTALL
vendored
|
@ -1,55 +0,0 @@
|
||||||
To build pngquant from source on Mac OS X and most Linux distributions,
|
|
||||||
simply run:
|
|
||||||
|
|
||||||
$ make
|
|
||||||
|
|
||||||
It will create pngquant executable in the current directory. If you'd like
|
|
||||||
to install it system-wide:
|
|
||||||
|
|
||||||
$ sudo make install
|
|
||||||
|
|
||||||
By default it will be installed in /usr/local/bin. To install it in another
|
|
||||||
directory run `./configure --prefix=dir && make`.
|
|
||||||
|
|
||||||
pngquant uses GNU Makefile. To compile on FreeBSD you will need to use gmake,
|
|
||||||
and on Windows the MinGW compiler (MSVC does not support C99).
|
|
||||||
|
|
||||||
pngquant will compile with libpng 1.2, but you should use 1.5 or later.
|
|
||||||
|
|
||||||
|
|
||||||
##Compilation with OpenMP
|
|
||||||
|
|
||||||
$ ./configure --with-openmp && make
|
|
||||||
|
|
||||||
This makes pngquant faster in wall-clock time on multicore machines when one
|
|
||||||
image at a time is processed.
|
|
||||||
|
|
||||||
However, it increases total CPU time used, and thus it's not most optimal
|
|
||||||
for server-side and parallelized batch jobs which run many pngquant
|
|
||||||
instances at a time.
|
|
||||||
|
|
||||||
On OS X you may need to install gcc and add `CC=gcc-4.9` to `./configure`,
|
|
||||||
because clang doesn't support OpenMP (yet).
|
|
||||||
|
|
||||||
|
|
||||||
##Compilation without Cocoa image reader
|
|
||||||
|
|
||||||
Mac OS X version uses Cocoa to read images. This adds support for color profiles
|
|
||||||
and other image formats as input. `./configure --without-cocoa` switches back
|
|
||||||
to libpng.
|
|
||||||
|
|
||||||
|
|
||||||
##Compilation with Little CMS 2
|
|
||||||
|
|
||||||
$ ./configure --with-lcms2 && make
|
|
||||||
|
|
||||||
Enables support for ICC v2/v4 color profiles when reading images.
|
|
||||||
Requires Little CMS library available via `pgk-config` (e.g. install `liblcms2-dev`).
|
|
||||||
|
|
||||||
|
|
||||||
##Compilation of `libimagequant.a` only
|
|
||||||
|
|
||||||
If you want to use pngquant's conversion algorithm without loading/saving PNG
|
|
||||||
files, then you can run `make` in the `lib/` directory.
|
|
||||||
The library doesn't need libpng or zlib.
|
|
||||||
|
|
75
deps/pngquant/Makefile
vendored
75
deps/pngquant/Makefile
vendored
|
@ -1,75 +0,0 @@
|
||||||
-include config.mk
|
|
||||||
|
|
||||||
BIN ?= pngquant
|
|
||||||
BINPREFIX = $(DESTDIR)$(PREFIX)/bin
|
|
||||||
|
|
||||||
OBJS = pngquant.o rwpng.o
|
|
||||||
COCOA_OBJS = rwpng_cocoa.o
|
|
||||||
|
|
||||||
ifeq (1, $(COCOA_READER))
|
|
||||||
OBJS += $(COCOA_OBJS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
STATICLIB = lib/libimagequant.a
|
|
||||||
|
|
||||||
DISTFILES = *.[chm] pngquant.1 Makefile configure README.md INSTALL CHANGELOG COPYRIGHT
|
|
||||||
TARNAME = pngquant-$(VERSION)
|
|
||||||
TARFILE = $(TARNAME)-src.tar.bz2
|
|
||||||
|
|
||||||
LIBDISTFILES = lib/*.[ch] lib/COPYRIGHT lib/MANUAL.md lib/configure lib/Makefile
|
|
||||||
|
|
||||||
DLL=libimagequant.dll
|
|
||||||
DLLIMP=libimagequant_dll.a
|
|
||||||
DLLDEF=libimagequant_dll.def
|
|
||||||
|
|
||||||
all: $(BIN)
|
|
||||||
|
|
||||||
staticlib:
|
|
||||||
$(MAKE) -C lib static
|
|
||||||
|
|
||||||
$(STATICLIB): config.mk staticlib
|
|
||||||
|
|
||||||
$(OBJS): $(wildcard *.h) config.mk
|
|
||||||
|
|
||||||
rwpng_cocoa.o: rwpng_cocoa.m
|
|
||||||
$(CC) -Wno-enum-conversion -c $(CFLAGS) -o $@ $< || clang -Wno-enum-conversion -c -O3 $(CFLAGS) -o $@ $<
|
|
||||||
|
|
||||||
$(BIN): $(OBJS) $(STATICLIB)
|
|
||||||
$(CC) $^ $(LDFLAGS) -o $@
|
|
||||||
|
|
||||||
test: $(BIN)
|
|
||||||
./test/test.sh ./test $(BIN)
|
|
||||||
|
|
||||||
dist: $(TARFILE)
|
|
||||||
|
|
||||||
$(TARFILE): $(DISTFILES)
|
|
||||||
rm -rf $(TARFILE) $(TARNAME)
|
|
||||||
mkdir -p $(TARNAME)/lib
|
|
||||||
cp $(DISTFILES) $(TARNAME)
|
|
||||||
cp $(LIBDISTFILES) $(TARNAME)/lib
|
|
||||||
tar -cjf $(TARFILE) --numeric-owner --exclude='._*' $(TARNAME)
|
|
||||||
rm -rf $(TARNAME)
|
|
||||||
-shasum $(TARFILE)
|
|
||||||
|
|
||||||
install: $(BIN)
|
|
||||||
-mkdir -p '$(BINPREFIX)'
|
|
||||||
install -m 0755 -p '$(BIN)' '$(BINPREFIX)/$(BIN)'
|
|
||||||
|
|
||||||
uninstall:
|
|
||||||
rm -f '$(BINPREFIX)/$(BIN)'
|
|
||||||
|
|
||||||
clean:
|
|
||||||
$(MAKE) -C lib clean
|
|
||||||
rm -f '$(BIN)' $(OBJS) $(COCOA_OBJS) $(STATICLIB) $(TARFILE)
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
$(MAKE) -C lib distclean
|
|
||||||
rm -f config.mk pngquant-*-src.tar.bz2
|
|
||||||
|
|
||||||
config.mk:
|
|
||||||
ifeq ($(filter %clean %distclean, $(MAKECMDGOALS)), )
|
|
||||||
./configure
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: all clean dist distclean dll install uninstall test staticlib
|
|
||||||
.DELETE_ON_ERROR:
|
|
97
deps/pngquant/README.md
vendored
97
deps/pngquant/README.md
vendored
|
@ -1,97 +0,0 @@
|
||||||
#pngquant 2
|
|
||||||
|
|
||||||
This is the official `pngquant` and `libimagequant`.
|
|
||||||
|
|
||||||
[pngquant](http://pngquant.org) converts 24/32-bit RGBA PNGs to 8-bit palette with *alpha channel preserved*.
|
|
||||||
Such images are compatible with all modern browsers, and a special compatibility setting exists which helps transparency degrade well in Internet Explorer 6.
|
|
||||||
|
|
||||||
Quantized files are often 40-70% smaller than their 24/32-bit version.
|
|
||||||
|
|
||||||
This utility works on Linux, Mac OS X and Windows.
|
|
||||||
|
|
||||||
##Usage
|
|
||||||
|
|
||||||
- batch conversion of multiple files: `pngquant *.png`
|
|
||||||
- Unix-style stdin/stdout chaining: `… | pngquant - | …`
|
|
||||||
|
|
||||||
To further reduce file size, try [optipng](http://optipng.sourceforge.net) or [ImageOptim](http://imageoptim.pornel.net).
|
|
||||||
|
|
||||||
##Improvements since 1.0
|
|
||||||
|
|
||||||
Generated files are both smaller and look much better.
|
|
||||||
|
|
||||||
* Significantly better quality of quantisation
|
|
||||||
|
|
||||||
- more accurate remapping of semitransparent colors
|
|
||||||
- special dithering algorithm that does not add noise in well-quantized areas of the image
|
|
||||||
- uses variance instead of popularity for box selection (improvement suggested in the original median cut paper)
|
|
||||||
- feedback loop that repeats median cut for poorly quantized colors
|
|
||||||
- additional colormap improvement using Voronoi iteration
|
|
||||||
- supports much larger number of colors in input images without degradation of quality
|
|
||||||
- gamma correction (output is always generated with gamma 2.2 for web compatibility)
|
|
||||||
|
|
||||||
* More flexible commandline usage
|
|
||||||
|
|
||||||
- number of colors defaults to 256
|
|
||||||
- long options and standard switches like `--` and `-` are allowed
|
|
||||||
|
|
||||||
* Refactored and modernised code
|
|
||||||
|
|
||||||
- C99 with no workarounds for old systems
|
|
||||||
- floating-point math used throughout
|
|
||||||
- Intel SSE optimisations
|
|
||||||
- multicore support via OpenMP
|
|
||||||
- quantization moved to standalone libimagequant
|
|
||||||
|
|
||||||
##Options
|
|
||||||
|
|
||||||
See `pngquant -h` for full list.
|
|
||||||
|
|
||||||
###`--quality min-max`
|
|
||||||
|
|
||||||
`min` and `max` are numbers in range 0 (worst) to 100 (perfect), similar to JPEG. pngquant will use the least amount of colors required to meet or exceed the `max` quality. If conversion results in quality below the `min` quality the image won't be saved (if outputting to stdin, 24-bit original will be output) and pngquant will exit with status code 99.
|
|
||||||
|
|
||||||
pngquant --quality=65-80 image.png
|
|
||||||
|
|
||||||
###`--ext new.png`
|
|
||||||
|
|
||||||
Set custom extension (suffix) for output filename. By default `-or8.png` or `-fs8.png` is used. If you use `--ext=.png --force` options pngquant will overwrite input files in place (use with caution).
|
|
||||||
|
|
||||||
###`-o out.png` or `--output out.png`
|
|
||||||
|
|
||||||
Writes converted file to the given path. When this option is used only single input file is allowed.
|
|
||||||
|
|
||||||
###`--skip-if-larger`
|
|
||||||
|
|
||||||
Don't write converted files if the conversion isn't worth it.
|
|
||||||
|
|
||||||
###`--speed N`
|
|
||||||
|
|
||||||
Speed/quality trade-off from 1 (brute-force) to 11 (fastest). The default is 3. Speed 10 has 5% lower quality, but is 8 times faster than the default. Speed 11 disables dithering and lowers compression level.
|
|
||||||
|
|
||||||
###`--nofs`
|
|
||||||
|
|
||||||
Disables Floyd-Steinberg dithering.
|
|
||||||
|
|
||||||
###`--floyd=0.5`
|
|
||||||
|
|
||||||
Controls level of dithering (0 = none, 1 = full).
|
|
||||||
|
|
||||||
###`--posterize bits`
|
|
||||||
|
|
||||||
Reduce precision of the palette by number of bits. Use when the image will be displayed on low-depth screens (e.g. 16-bit displays or compressed textures in ARGB444 format).
|
|
||||||
|
|
||||||
###`--version`
|
|
||||||
|
|
||||||
Print version information to stdout.
|
|
||||||
|
|
||||||
###`-`
|
|
||||||
|
|
||||||
Read image from stdin and send result to stdout.
|
|
||||||
|
|
||||||
###`--`
|
|
||||||
|
|
||||||
Stops processing of arguments. This allows use of file names that start with `-`. If you're using pngquant in a script, it's advisable to put this before file names:
|
|
||||||
|
|
||||||
pngquant $OPTIONS -- "$FILE"
|
|
||||||
|
|
427
deps/pngquant/configure
vendored
427
deps/pngquant/configure
vendored
|
@ -1,427 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CONFIG="config.mk"
|
|
||||||
PREFIX="/usr/local"
|
|
||||||
VERSION=$(grep LIQ_VERSION_STRING lib/libimagequant.h | grep -Eo "2\.[0-9.]+")
|
|
||||||
|
|
||||||
DEBUG=
|
|
||||||
SSE=auto
|
|
||||||
OPENMP=
|
|
||||||
if [[ "$OSTYPE" =~ "darwin" ]]; then
|
|
||||||
COCOA_READER=auto
|
|
||||||
LCMS2=0
|
|
||||||
else
|
|
||||||
COCOA_READER=0
|
|
||||||
LCMS2=auto
|
|
||||||
fi
|
|
||||||
EXTRA_CFLAGS=
|
|
||||||
EXTRA_LDFLAGS=
|
|
||||||
|
|
||||||
# make gcc default compiler unless CC is already set
|
|
||||||
CC=${CC:-gcc}
|
|
||||||
|
|
||||||
help() {
|
|
||||||
printf "%4s %s\n" "" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in "$@"; do
|
|
||||||
case $i in
|
|
||||||
--help)
|
|
||||||
echo
|
|
||||||
help "--prefix= installation directory [$PREFIX]"
|
|
||||||
help "--extra-cflags= append to CFLAGS"
|
|
||||||
help "--extra-ldflags= append to LDFLAGS"
|
|
||||||
echo
|
|
||||||
help "--enable-debug"
|
|
||||||
help "--enable-sse/--disable-sse enable/disable SSE instructions"
|
|
||||||
echo
|
|
||||||
help "--with-openmp compile with multicore support"
|
|
||||||
help "--with-lcms2/--without-lcms2 compile with color profile support"
|
|
||||||
if [[ "$OSTYPE" =~ "darwin" ]]; then
|
|
||||||
help "--with-cocoa/--without-cocoa use Cocoa framework to read images"
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
help "CC=<compiler> use given compiler command"
|
|
||||||
help "CFLAGS=<flags> pass options to the compiler"
|
|
||||||
help "LDFLAGS=<flags> pass options to the linker"
|
|
||||||
echo
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
# Can be set before or after configure. Latter overrides former.
|
|
||||||
CC=*)
|
|
||||||
CC=${i#*=}
|
|
||||||
;;
|
|
||||||
CFLAGS=*)
|
|
||||||
CFLAGS=${i#*=}
|
|
||||||
;;
|
|
||||||
LDFLAGS=*)
|
|
||||||
LDFLAGS=${i#*=}
|
|
||||||
;;
|
|
||||||
--enable-debug)
|
|
||||||
DEBUG=1
|
|
||||||
;;
|
|
||||||
--enable-sse)
|
|
||||||
SSE=1
|
|
||||||
;;
|
|
||||||
--disable-sse)
|
|
||||||
SSE=0
|
|
||||||
;;
|
|
||||||
--with-openmp)
|
|
||||||
OPENMP=1
|
|
||||||
;;
|
|
||||||
--with-lcms2)
|
|
||||||
LCMS2=1
|
|
||||||
COCOA_READER=0
|
|
||||||
;;
|
|
||||||
--without-lcms2)
|
|
||||||
LCMS2=0
|
|
||||||
;;
|
|
||||||
--with-cocoa)
|
|
||||||
COCOA_READER=1
|
|
||||||
LCMS2=0
|
|
||||||
;;
|
|
||||||
--without-cocoa)
|
|
||||||
COCOA_READER=0
|
|
||||||
;;
|
|
||||||
--prefix=*)
|
|
||||||
PREFIX=${i#*=}
|
|
||||||
;;
|
|
||||||
# can be used multiple times or in quotes to set multiple flags
|
|
||||||
--extra-cflags=*)
|
|
||||||
EXTRA_CFLAGS="$EXTRA_CFLAGS ${i#*=}"
|
|
||||||
;;
|
|
||||||
--extra-ldflags=*)
|
|
||||||
EXTRA_LDFLAGS="$EXTRA_LDFLAGS ${i#*=}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "error: unknown switch ${i%%=*} (see $0 --help for the list)"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# If someone runs sudo make install as very first command, and configure later,
|
|
||||||
# $CONFIG cannot be overwritten, and must be deleted before continuing.
|
|
||||||
if [[ -f "$CONFIG" && ! -w "$CONFIG" ]]; then
|
|
||||||
echo "Cannot overwrite file $CONFIG! Please delete it."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cflags() {
|
|
||||||
CFLAGS="$CFLAGS $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
lflags() {
|
|
||||||
LDFLAGS="$LDFLAGS $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
status() {
|
|
||||||
printf "%10s: %s\n" "$1" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Append to CFLAGS if compiler supports flag, with optional prerequisite.
|
|
||||||
# Fails on errors and warnings.
|
|
||||||
conditional_cflags() {
|
|
||||||
if [ -z "echo | $("$CC" -xc -S -o /dev/null $2 $1 2>&1)" ]; then
|
|
||||||
cflags "$1"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# returns first matching file in directory
|
|
||||||
find_f() {
|
|
||||||
echo $(find "$1" -not -type d -name "$2" -print -quit 2> /dev/null)
|
|
||||||
}
|
|
||||||
|
|
||||||
# returns first matching file in directory (no symlinks)
|
|
||||||
find_h() {
|
|
||||||
echo $(find "$1" -type f -name "$2" -print -quit 2> /dev/null)
|
|
||||||
}
|
|
||||||
|
|
||||||
find_pkgconfig() {
|
|
||||||
LIBNAME=$1
|
|
||||||
if pkg-config --exists "$LIBNAME" &> /dev/null; then
|
|
||||||
cflags "$(pkg-config --cflags "$LIBNAME")"
|
|
||||||
lflags "$(pkg-config --libs "$LIBNAME")"
|
|
||||||
status "$LIBNAME" "shared ($(pkg-config --modversion "$LIBNAME"))"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
find_static() {
|
|
||||||
LIBNAME=$1
|
|
||||||
HEADERPATTERN=$2
|
|
||||||
STATICPATTERN=$3
|
|
||||||
|
|
||||||
HPATH=$(find_h . "$HEADERPATTERN")
|
|
||||||
if [ -n "$HPATH" ]; then
|
|
||||||
APATH=$(find_f . "$STATICPATTERN")
|
|
||||||
if [ -n "$APATH" ]; then
|
|
||||||
cflags "-I${HPATH%/*}"
|
|
||||||
lflags "${APATH}"
|
|
||||||
status "$LIBNAME" "static"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
find_library() {
|
|
||||||
LIBNAME=$1
|
|
||||||
DYNAMICLIBNAME=$2
|
|
||||||
HEADERPATTERN=$3
|
|
||||||
STATICPATTERN=$4
|
|
||||||
DYNAMICPATTERN=$5
|
|
||||||
|
|
||||||
# try static in current directory first
|
|
||||||
if find_static "$LIBNAME" "$HEADERPATTERN" "$STATICPATTERN"; then
|
|
||||||
return 0;
|
|
||||||
fi
|
|
||||||
|
|
||||||
# try shared
|
|
||||||
if find_pkgconfig "$LIBNAME"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
for i in "${DIRS[@]}"; do
|
|
||||||
DIR=($i)
|
|
||||||
HPATH=$(find_h "${DIR[0]}" "$HEADERPATTERN")
|
|
||||||
if [ -n "$HPATH" ]; then
|
|
||||||
SOPATH=$(find_f "${DIR[1]}" "$DYNAMICPATTERN")
|
|
||||||
if [ -n "$SOPATH" ]; then
|
|
||||||
cflags "-I${HPATH%/*}"
|
|
||||||
lflags "-L${SOPATH%/*} -l$DYNAMICLIBNAME"
|
|
||||||
status "$LIBNAME" "shared ... $SOPATH"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# returns full png.h version string
|
|
||||||
pngh_string() {
|
|
||||||
echo "$(grep -m1 "define PNG_LIBPNG_VER_STRING" "$1" | \
|
|
||||||
grep -Eo '"[^"]+"' | grep -Eo '[^"]+')"
|
|
||||||
}
|
|
||||||
|
|
||||||
# returns major minor version numbers from png.h
|
|
||||||
pngh_majmin() {
|
|
||||||
local MAJ=$(grep -m1 "define PNG_LIBPNG_VER_MAJOR" "$1" | grep -Eo "[0-9]+")
|
|
||||||
local MIN=$(grep -m1 "define PNG_LIBPNG_VER_MINOR" "$1" | grep -Eo "[0-9]+")
|
|
||||||
echo "${MAJ}${MIN}"
|
|
||||||
}
|
|
||||||
|
|
||||||
error() {
|
|
||||||
status "$1" "error ... $2"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
echo
|
|
||||||
|
|
||||||
# basic check
|
|
||||||
if ! echo "int main(){}" | "$CC" -xc -std=c99 -o /dev/null - &> /dev/null; then
|
|
||||||
error "Compiler" "$CC failed to compile anything (make sure it's installed and supports C99)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
status "Compiler" "$CC"
|
|
||||||
|
|
||||||
# init flags
|
|
||||||
CFLAGS=${CFLAGS:--O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall}
|
|
||||||
cflags "-std=c99 -I."
|
|
||||||
|
|
||||||
# DEBUG
|
|
||||||
if [ -z "$DEBUG" ]; then
|
|
||||||
cflags "-DNDEBUG"
|
|
||||||
status "Debug" "no"
|
|
||||||
else
|
|
||||||
cflags "-g"
|
|
||||||
status "Debug" "yes"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# SSE
|
|
||||||
if [ "$SSE" = 'auto' ]; then
|
|
||||||
if [[ "$(uname -m)" =~ (amd|x86_)64 ||
|
|
||||||
"$(grep -E -m1 "^flags" /proc/cpuinfo)" =~ "sse" ]]; then
|
|
||||||
SSE=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$SSE" -eq 1 ]; then
|
|
||||||
status "SSE" "yes"
|
|
||||||
cflags "-DUSE_SSE=1"
|
|
||||||
cflags "-msse"
|
|
||||||
# Silence a later ICC warning due to -msse working slightly different.
|
|
||||||
conditional_cflags "-wd10121"
|
|
||||||
# Must be set explicitly for GCC on x86_32. Other compilers imply it.
|
|
||||||
conditional_cflags "-mfpmath=sse" "-msse"
|
|
||||||
elif [ "$SSE" -eq 0 ]; then
|
|
||||||
status "SSE" "no"
|
|
||||||
cflags "-DUSE_SSE=0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OpenMP
|
|
||||||
if [ -n "$OPENMP" ]; then
|
|
||||||
if [[ "$("$CC" -xc -E -fopenmp <(echo "#ifdef _OPENMP
|
|
||||||
#include <omp.h>
|
|
||||||
#endif") 2>&1)" =~ "omp_get_thread_num" ]]; then
|
|
||||||
cflags "-fopenmp"
|
|
||||||
lflags "-fopenmp"
|
|
||||||
status "OpenMP" "yes"
|
|
||||||
else
|
|
||||||
error "OpenMP" "not supported by compiler (please install a compiler that supports OpenMP (e.g. gcc) and specify it with the CC= argument)"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# silence warnings about omp pragmas
|
|
||||||
cflags "-Wno-unknown-pragmas"
|
|
||||||
conditional_cflags "-wd3180" # ICC
|
|
||||||
status "OpenMP" "no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Cocoa
|
|
||||||
if [[ "$OSTYPE" =~ "darwin" ]]; then
|
|
||||||
cflags "-mmacosx-version-min=10.6"
|
|
||||||
lflags "-mmacosx-version-min=10.6"
|
|
||||||
|
|
||||||
if [ "$COCOA_READER" != 0 ] && "$CC" 2>/dev/null 1>/dev/null -xc -E <(echo "#import <Cocoa/Cocoa.h>"); then
|
|
||||||
COCOA_READER=1
|
|
||||||
cflags "-DUSE_COCOA=1"
|
|
||||||
lflags "-framework Cocoa"
|
|
||||||
status "Cocoa" "yes"
|
|
||||||
else
|
|
||||||
status "Cocoa" "no"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# pairs of possible *.h and lib*.so locations
|
|
||||||
DIRS=("/usr/local/include /usr/local/lib"
|
|
||||||
"/usr/include /usr/lib"
|
|
||||||
"/opt/local/include /opt/local/lib" # macports
|
|
||||||
)
|
|
||||||
|
|
||||||
if [[ "$OSTYPE" =~ "darwin" ]]; then
|
|
||||||
SOLIBSUFFIX=dylib
|
|
||||||
|
|
||||||
# Search Developer SDK paths, since Apple seems to have dropped the standard Unixy ones
|
|
||||||
XCODE_CMD="xcode-select"
|
|
||||||
XCODE_PATH=$($XCODE_CMD -p)
|
|
||||||
DIRS+=("$XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include $XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/lib")
|
|
||||||
DIRS+=("$XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/include $XCODE_PATH/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/usr/lib")
|
|
||||||
else
|
|
||||||
SOLIBSUFFIX=so
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# libpng
|
|
||||||
SUCCESS=0
|
|
||||||
# try static in current directory first
|
|
||||||
PNGH=$(find_h . "png.h")
|
|
||||||
if [ -n "$PNGH" ]; then
|
|
||||||
PNGH_STRING=$(pngh_string "$PNGH")
|
|
||||||
PNGH_MAJMIN=$(pngh_majmin "$PNGH")
|
|
||||||
if [[ -n "$PNGH_STRING" && -n "$PNGH_MAJMIN" ]]; then
|
|
||||||
LIBPNGA=$(find_f . "libpng${PNGH_MAJMIN}.a")
|
|
||||||
if [ -n "$LIBPNGA" ]; then
|
|
||||||
cflags "-I${PNGH%/*}"
|
|
||||||
lflags "${LIBPNGA}"
|
|
||||||
status "libpng" "static (${PNGH_STRING})"
|
|
||||||
SUCCESS=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
# try shared
|
|
||||||
if [ "$SUCCESS" -eq 0 ]; then
|
|
||||||
if find_pkgconfig libpng; then
|
|
||||||
SUCCESS=1
|
|
||||||
else
|
|
||||||
for i in "${DIRS[@]}"; do
|
|
||||||
DIR=($i)
|
|
||||||
PNGH=$(find_h "${DIR[0]}" "png.h")
|
|
||||||
if [ -n "$PNGH" ]; then
|
|
||||||
PNGH_STRING=$(pngh_string "$PNGH")
|
|
||||||
PNGH_MAJMIN=$(pngh_majmin "$PNGH")
|
|
||||||
if [[ -n "$PNGH_STRING" && -n "$PNGH_MAJMIN" ]]; then
|
|
||||||
LIBPNGSO=$(find_f "${DIR[1]}" "libpng${PNGH_MAJMIN}.$SOLIBSUFFIX*")
|
|
||||||
if [ -n "$LIBPNGSO" ]; then
|
|
||||||
cflags "-I${PNGH%/*}"
|
|
||||||
lflags "-L${LIBPNGSO%/*} -lpng${PNGH_MAJMIN}"
|
|
||||||
status "libpng" "shared (${PNGH_STRING})"
|
|
||||||
SUCCESS=1
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
if [ "$SUCCESS" -eq 0 ]; then
|
|
||||||
if [[ "$OSTYPE" =~ "darwin" ]]; then
|
|
||||||
LIBPNG_CMD='`brew install libpng`'
|
|
||||||
else
|
|
||||||
LIBPNG_CMD='`apt-get install libpng-dev` or `yum install libpng-devel`'
|
|
||||||
fi
|
|
||||||
error "libpng" "not found (try: $LIBPNG_CMD)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# zlib
|
|
||||||
if ! find_library "zlib" "z" "zlib.h" "libz.a" "libz.$SOLIBSUFFIX*"; then
|
|
||||||
error "zlib" "not found (please install zlib-devel package)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# lcms2
|
|
||||||
if [ "$LCMS2" != 0 ]; then
|
|
||||||
if find_library "lcms2" "lcms2" "lcms2.h" "liblcms2.a" "liblcms2.$SOLIBSUFFIX*"; then
|
|
||||||
cflags "-DUSE_LCMS=1"
|
|
||||||
else
|
|
||||||
if [ "$LCMS2" = 'auto' ]; then
|
|
||||||
status "lcms2" "no"
|
|
||||||
else
|
|
||||||
error "lcms2" "not found (please install libcms2-devel package)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
status "lcms2" "no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo
|
|
||||||
|
|
||||||
# As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this.
|
|
||||||
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
|
|
||||||
conditional_cflags "-fexcess-precision=fast"
|
|
||||||
|
|
||||||
# Intel C++ Compiler
|
|
||||||
|
|
||||||
# ICC does usually only produce fast(er) code when it can optimize to the full
|
|
||||||
# capabilites of the (Intel) CPU. This is equivalent to -march=native for GCC.
|
|
||||||
conditional_cflags "-xHOST"
|
|
||||||
|
|
||||||
# Disable unsafe fp optimizations and enforce fp precision as set in the source.
|
|
||||||
conditional_cflags "-fp-model source"
|
|
||||||
|
|
||||||
# Silence a gold linker warning about string misalignment.
|
|
||||||
conditional_cflags "-falign-stack=maintain-16-byte"
|
|
||||||
|
|
||||||
lflags "-lm" # Ubuntu requires this library last, issue #38
|
|
||||||
|
|
||||||
if [ -n "$EXTRA_CFLAGS" ]; then
|
|
||||||
cflags "$EXTRA_CFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$EXTRA_LDFLAGS" ]; then
|
|
||||||
lflags "$EXTRA_LDFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Overwrite previous configuration.
|
|
||||||
echo "
|
|
||||||
# auto-generated by configure
|
|
||||||
PREFIX = $PREFIX
|
|
||||||
VERSION = $VERSION
|
|
||||||
CC = $CC
|
|
||||||
CFLAGS = $CFLAGS
|
|
||||||
LDFLAGS = $LDFLAGS
|
|
||||||
COCOA_READER = $COCOA_READER
|
|
||||||
" > "$CONFIG"
|
|
||||||
|
|
||||||
# Configure static library the same way
|
|
||||||
cp "$CONFIG" lib/
|
|
36
deps/pngquant/lib/COPYRIGHT
vendored
36
deps/pngquant/lib/COPYRIGHT
vendored
|
@ -1,36 +0,0 @@
|
||||||
© 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
|
|
||||||
© 2009-2014 by Kornel Lesiński.
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
|
|
||||||
© 1989, 1991 by Jef Poskanzer.
|
|
||||||
|
|
||||||
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.
|
|
65
deps/pngquant/lib/Makefile
vendored
65
deps/pngquant/lib/Makefile
vendored
|
@ -1,65 +0,0 @@
|
||||||
-include config.mk
|
|
||||||
|
|
||||||
STATICLIB=libimagequant.a
|
|
||||||
SHAREDLIB=libimagequant.so.0
|
|
||||||
|
|
||||||
DLL=libimagequant.dll
|
|
||||||
DLLIMP=libimagequant_dll.a
|
|
||||||
DLLDEF=libimagequant_dll.def
|
|
||||||
|
|
||||||
OBJS = pam.o mediancut.o blur.o mempool.o viter.o nearest.o libimagequant.o
|
|
||||||
SHAREDOBJS = $(subst .o,.lo,$(OBJS))
|
|
||||||
|
|
||||||
BUILD_CONFIGURATION="$(CC) $(CFLAGS) $(LDFLAGS)"
|
|
||||||
|
|
||||||
DISTFILES = $(OBJS:.o=.c) *.h MANUAL.md COPYRIGHT Makefile configure
|
|
||||||
TARNAME = libimagequant-$(VERSION)
|
|
||||||
TARFILE = $(TARNAME)-src.tar.bz2
|
|
||||||
|
|
||||||
all: static shared
|
|
||||||
|
|
||||||
static: $(STATICLIB)
|
|
||||||
|
|
||||||
shared: $(SHAREDLIB)
|
|
||||||
|
|
||||||
dll:
|
|
||||||
$(MAKE) CFLAGSADD="-DLIQ_EXPORT='__declspec(dllexport)'" $(DLL)
|
|
||||||
|
|
||||||
|
|
||||||
$(DLL) $(DLLIMP): $(OBJS)
|
|
||||||
$(CC) -fPIC -shared -o $(DLL) $^ $(LDFLAGS) -Wl,--out-implib,$(DLLIMP),--output-def,$(DLLDEF)
|
|
||||||
|
|
||||||
$(STATICLIB): $(OBJS)
|
|
||||||
$(AR) $(ARFLAGS) $@ $^
|
|
||||||
|
|
||||||
$(SHAREDOBJS):
|
|
||||||
$(CC) -fPIC $(CFLAGS) -c $(@:.lo=.c) -o $@
|
|
||||||
|
|
||||||
$(SHAREDLIB): $(SHAREDOBJS)
|
|
||||||
$(CC) -shared -o $@ $^ $(LDFLAGS)
|
|
||||||
|
|
||||||
$(OBJS): $(wildcard *.h) config.mk
|
|
||||||
|
|
||||||
dist: $(TARFILE)
|
|
||||||
|
|
||||||
$(TARFILE): $(DISTFILES)
|
|
||||||
rm -rf $(TARFILE) $(TARNAME)
|
|
||||||
mkdir $(TARNAME)
|
|
||||||
cp $(DISTFILES) $(TARNAME)
|
|
||||||
tar -cjf $(TARFILE) --numeric-owner --exclude='._*' $(TARNAME)
|
|
||||||
rm -rf $(TARNAME)
|
|
||||||
-shasum $(TARFILE)
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f $(OBJS) $(SHAREDOBJS) $(SHAREDLIB) $(STATICLIB) $(TARFILE) $(DLL) $(DLLIMP) $(DLLDEF)
|
|
||||||
|
|
||||||
distclean: clean
|
|
||||||
rm -f config.mk
|
|
||||||
|
|
||||||
config.mk:
|
|
||||||
ifeq ($(filter %clean %distclean, $(MAKECMDGOALS)), )
|
|
||||||
./configure
|
|
||||||
endif
|
|
||||||
|
|
||||||
.PHONY: all static shared clean dist distclean dll
|
|
||||||
.DELETE_ON_ERROR:
|
|
205
deps/pngquant/lib/configure
vendored
205
deps/pngquant/lib/configure
vendored
|
@ -1,205 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CONFIG="config.mk"
|
|
||||||
PREFIX="/usr/local"
|
|
||||||
VERSION=$(grep LIQ_VERSION_STRING libimagequant.h | grep -Eo "2\.[0-9.]+")
|
|
||||||
|
|
||||||
DEBUG=
|
|
||||||
SSE=auto
|
|
||||||
OPENMP=
|
|
||||||
EXTRA_CFLAGS=
|
|
||||||
EXTRA_LDFLAGS=
|
|
||||||
|
|
||||||
# make gcc default compiler unless CC is already set
|
|
||||||
CC=${CC:-gcc}
|
|
||||||
|
|
||||||
help() {
|
|
||||||
printf "%4s %s\n" "" "$1"
|
|
||||||
}
|
|
||||||
|
|
||||||
for i in "$@"; do
|
|
||||||
case $i in
|
|
||||||
--help)
|
|
||||||
echo
|
|
||||||
help "--prefix= installation directory [$PREFIX]"
|
|
||||||
help "--extra-cflags= append to CFLAGS"
|
|
||||||
help "--extra-ldflags= append to LDFLAGS"
|
|
||||||
echo
|
|
||||||
help "--enable-debug"
|
|
||||||
help "--enable-sse/--disable-sse enable/disable SSE instructions"
|
|
||||||
echo
|
|
||||||
help "--with-openmp compile with multicore support"
|
|
||||||
echo
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
# Can be set before or after configure. Latter overrides former.
|
|
||||||
CC=*)
|
|
||||||
CC=${i#*=}
|
|
||||||
;;
|
|
||||||
CFLAGS=*)
|
|
||||||
CFLAGS=${i#*=}
|
|
||||||
;;
|
|
||||||
LDFLAGS=*)
|
|
||||||
LDFLAGS=${i#*=}
|
|
||||||
;;
|
|
||||||
--enable-debug)
|
|
||||||
DEBUG=1
|
|
||||||
;;
|
|
||||||
--enable-sse)
|
|
||||||
SSE=1
|
|
||||||
;;
|
|
||||||
--disable-sse)
|
|
||||||
SSE=0
|
|
||||||
;;
|
|
||||||
--with-openmp)
|
|
||||||
OPENMP=1
|
|
||||||
;;
|
|
||||||
--prefix=*)
|
|
||||||
PREFIX=${i#*=}
|
|
||||||
;;
|
|
||||||
# can be used multiple times or in quotes to set multiple flags
|
|
||||||
--extra-cflags=*)
|
|
||||||
EXTRA_CFLAGS="$EXTRA_CFLAGS ${i#*=}"
|
|
||||||
;;
|
|
||||||
--extra-ldflags=*)
|
|
||||||
EXTRA_LDFLAGS="$EXTRA_LDFLAGS ${i#*=}"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo "error: unknown switch ${i%%=*}"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# If someone runs sudo make install as very first command, and configure later,
|
|
||||||
# $CONFIG cannot be overwritten, and must be deleted before continuing.
|
|
||||||
if [[ -f "$CONFIG" && ! -w "$CONFIG" ]]; then
|
|
||||||
echo "Cannot overwrite file $CONFIG! Please delete it."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cflags() {
|
|
||||||
CFLAGS="$CFLAGS $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
lflags() {
|
|
||||||
LDFLAGS="$LDFLAGS $1"
|
|
||||||
}
|
|
||||||
|
|
||||||
status() {
|
|
||||||
printf "%10s: %s\n" "$1" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Append to CFLAGS if compiler supports flag, with optional prerequisite.
|
|
||||||
# Fails on errors and warnings.
|
|
||||||
conditional_cflags() {
|
|
||||||
if [ -z "$("$CC" -xc -S -o /dev/null $2 $1 <(echo) 2>&1)" ]; then
|
|
||||||
cflags "$1"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
error() {
|
|
||||||
status "$1" "error ... $2"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
echo
|
|
||||||
|
|
||||||
# basic check
|
|
||||||
if ! "$CC" -xc -std=c99 <(echo "int main(){}") -o /dev/null &> /dev/null; then
|
|
||||||
error "Compiler" "$CC is no C compiler"
|
|
||||||
fi
|
|
||||||
|
|
||||||
status "Compiler" "$CC"
|
|
||||||
|
|
||||||
# init flags
|
|
||||||
CFLAGS=${CFLAGS:--O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -Wall}
|
|
||||||
cflags "-std=c99 -I."
|
|
||||||
|
|
||||||
# DEBUG
|
|
||||||
if [ -z "$DEBUG" ]; then
|
|
||||||
cflags "-DNDEBUG"
|
|
||||||
status "Debug" "no"
|
|
||||||
else
|
|
||||||
cflags "-g"
|
|
||||||
status "Debug" "yes"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# SSE
|
|
||||||
if [ "$SSE" = 'auto' ]; then
|
|
||||||
if [[ "$(uname -m)" =~ (amd|x86_)64 ||
|
|
||||||
"$(grep -E -m1 "^flags" /proc/cpuinfo)" =~ "sse" ]]; then
|
|
||||||
SSE=1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$SSE" -eq 1 ]; then
|
|
||||||
status "SSE" "yes"
|
|
||||||
cflags "-DUSE_SSE=1"
|
|
||||||
cflags "-msse"
|
|
||||||
# Silence a later ICC warning due to -msse working slightly different.
|
|
||||||
conditional_cflags "-wd10121"
|
|
||||||
# Must be set explicitly for GCC on x86_32. Other compilers imply it.
|
|
||||||
conditional_cflags "-mfpmath=sse" "-msse"
|
|
||||||
elif [ "$SSE" -eq 0 ]; then
|
|
||||||
status "SSE" "no"
|
|
||||||
cflags "-DUSE_SSE=0"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# OpenMP
|
|
||||||
if [ -n "$OPENMP" ]; then
|
|
||||||
if [[ "$("$CC" -xc -E -fopenmp <(echo -e \
|
|
||||||
"#ifdef _OPENMP
|
|
||||||
#include <omp.h>
|
|
||||||
#endif") 2>&1)" =~ "omp_get_thread_num" ]]; then
|
|
||||||
cflags "-fopenmp"
|
|
||||||
lflags "-fopenmp"
|
|
||||||
status "OpenMP" "yes"
|
|
||||||
else
|
|
||||||
error "OpenMP" "not supported by compiler"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# silence warnings about omp pragmas
|
|
||||||
cflags "-Wno-unknown-pragmas"
|
|
||||||
conditional_cflags "-wd3180" # ICC
|
|
||||||
status "OpenMP" "no"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo
|
|
||||||
|
|
||||||
# As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this.
|
|
||||||
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
|
|
||||||
conditional_cflags "-fexcess-precision=fast"
|
|
||||||
|
|
||||||
# Intel C++ Compiler
|
|
||||||
|
|
||||||
# ICC does usually only produce fast(er) code when it can optimize to the full
|
|
||||||
# capabilites of the (Intel) CPU. This is equivalent to -march=native for GCC.
|
|
||||||
conditional_cflags "-xHOST"
|
|
||||||
|
|
||||||
# Disable unsafe fp optimizations and enforce fp precision as set in the source.
|
|
||||||
conditional_cflags "-fp-model source"
|
|
||||||
|
|
||||||
# Silence a gold linker warning about string misalignment.
|
|
||||||
conditional_cflags "-falign-stack=maintain-16-byte"
|
|
||||||
|
|
||||||
lflags "-lm" # Ubuntu requires this library last, issue #38
|
|
||||||
|
|
||||||
if [ -n "$EXTRA_CFLAGS" ]; then
|
|
||||||
cflags "$EXTRA_CFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$EXTRA_LDFLAGS" ]; then
|
|
||||||
lflags "$EXTRA_LDFLAGS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Overwrite previous configuration.
|
|
||||||
echo "
|
|
||||||
# auto-generated by configure
|
|
||||||
PREFIX = $PREFIX
|
|
||||||
VERSION = $VERSION
|
|
||||||
CC = $CC
|
|
||||||
CFLAGS = $CFLAGS
|
|
||||||
LDFLAGS = $LDFLAGS
|
|
||||||
" > $CONFIG
|
|
|
@ -154,7 +154,7 @@ static void liq_verbose_printf_flush(liq_attr *attr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USE_SSE
|
#if __SSE__ || (_M_IX86_FP > 0)
|
||||||
inline static bool is_sse_available()
|
inline static bool is_sse_available()
|
||||||
{
|
{
|
||||||
#if (defined(__x86_64__) || defined(__amd64))
|
#if (defined(__x86_64__) || defined(__amd64))
|
||||||
|
@ -416,7 +416,7 @@ static void liq_aligned_free(void *inptr)
|
||||||
|
|
||||||
LIQ_EXPORT liq_attr* liq_attr_create_with_allocator(void* (*custom_malloc)(size_t), void (*custom_free)(void*))
|
LIQ_EXPORT liq_attr* liq_attr_create_with_allocator(void* (*custom_malloc)(size_t), void (*custom_free)(void*))
|
||||||
{
|
{
|
||||||
#if USE_SSE
|
#if __SSE__ || (_M_IX86_FP > 0)
|
||||||
if (!is_sse_available()) {
|
if (!is_sse_available()) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -640,7 +640,7 @@ static const rgba_pixel *liq_image_get_row_rgba(liq_image *img, unsigned int row
|
||||||
static void convert_row_to_f(liq_image *img, f_pixel *row_f_pixels, const unsigned int row, const float gamma_lut[])
|
static void convert_row_to_f(liq_image *img, f_pixel *row_f_pixels, const unsigned int row, const float gamma_lut[])
|
||||||
{
|
{
|
||||||
assert(row_f_pixels);
|
assert(row_f_pixels);
|
||||||
assert(!USE_SSE || 0 == ((uintptr_t)row_f_pixels & 15));
|
assert(!(__SSE__ || (_M_IX86_FP > 0)) || 0 == ((uintptr_t)row_f_pixels & 15));
|
||||||
|
|
||||||
const rgba_pixel *const row_pixels = liq_image_get_row_rgba(img, row);
|
const rgba_pixel *const row_pixels = liq_image_get_row_rgba(img, row);
|
||||||
|
|
12
deps/pngquant/lib/pam.h → deps/pngquant/pam.h
vendored
12
deps/pngquant/lib/pam.h → deps/pngquant/pam.h
vendored
|
@ -28,15 +28,7 @@
|
||||||
|
|
||||||
#define MAX_DIFF 1e20
|
#define MAX_DIFF 1e20
|
||||||
|
|
||||||
#ifndef USE_SSE
|
#if __SSE__ || (_M_IX86_FP > 0)
|
||||||
# if defined(__SSE__) && (defined(WIN32) || defined(__WIN32__))
|
|
||||||
# define USE_SSE 1
|
|
||||||
# else
|
|
||||||
# define USE_SSE 0
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if USE_SSE
|
|
||||||
# include <xmmintrin.h>
|
# include <xmmintrin.h>
|
||||||
# ifdef _MSC_VER
|
# ifdef _MSC_VER
|
||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
|
@ -186,7 +178,7 @@ inline static float min_colordifference(const f_pixel px, const f_pixel py)
|
||||||
ALWAYS_INLINE static float colordifference(f_pixel px, f_pixel py);
|
ALWAYS_INLINE static float colordifference(f_pixel px, f_pixel py);
|
||||||
inline static float colordifference(f_pixel px, f_pixel py)
|
inline static float colordifference(f_pixel px, f_pixel py)
|
||||||
{
|
{
|
||||||
#if USE_SSE
|
#if __SSE__ || (_M_IX86_FP > 0)
|
||||||
const __m128 vpx = _mm_load_ps((const float*)&px);
|
const __m128 vpx = _mm_load_ps((const float*)&px);
|
||||||
const __m128 vpy = _mm_load_ps((const float*)&py);
|
const __m128 vpy = _mm_load_ps((const float*)&py);
|
||||||
|
|
129
deps/pngquant/pngquant.1
vendored
129
deps/pngquant/pngquant.1
vendored
|
@ -1,129 +0,0 @@
|
||||||
.Dd 2013-02-25
|
|
||||||
.Dt pngquant 1
|
|
||||||
.Sh NAME
|
|
||||||
.Nm pngquant
|
|
||||||
.Nd PNG converter and lossy image compressor
|
|
||||||
.Sh SYNOPSIS
|
|
||||||
.Nm
|
|
||||||
.Aq options
|
|
||||||
.Op ncolors
|
|
||||||
.Pa file
|
|
||||||
.Op Ar
|
|
||||||
.Nm
|
|
||||||
.Aq options
|
|
||||||
.Op ncolors
|
|
||||||
.Fl
|
|
||||||
.Cm < Ns Pa file
|
|
||||||
.Cm > Ns Pa file
|
|
||||||
.Sh DESCRIPTION
|
|
||||||
.Nm
|
|
||||||
converts 32-bit RGBA PNGs to 8-bit (or smaller) RGBA-palette PNGs, optionally using Floyd-Steinberg dithering.
|
|
||||||
The output filename is the same as the input name except that it ends in
|
|
||||||
.Ql -fs8.png
|
|
||||||
or
|
|
||||||
.Ql -or8.png
|
|
||||||
(unless the input is stdin, in which case the quantized image will go to stdout).
|
|
||||||
The default behavior if the output file exists is to skip the conversion; use
|
|
||||||
.Fl Fl force
|
|
||||||
to overwrite.
|
|
||||||
.Sh OPTIONS
|
|
||||||
.Bl -tag -width -indent
|
|
||||||
.It Fl o Ar out.png , Fl Fl output Ar out.png
|
|
||||||
Writes converted file to the given path. When this option is used only single input file is allowed.
|
|
||||||
.It Fl Fl ext Ar new.png
|
|
||||||
File extension (suffix) to use for output files instead of the default
|
|
||||||
.Ql -fs8.png
|
|
||||||
or
|
|
||||||
.Ql -or8.png .
|
|
||||||
.It Fl f , Fl Fl force
|
|
||||||
Overwrite existing output files.
|
|
||||||
.Do
|
|
||||||
.Fl Fl ext
|
|
||||||
.Ar .png
|
|
||||||
.Fl Fl force
|
|
||||||
.Dc
|
|
||||||
can be used to convert files in place (which is unsafe).
|
|
||||||
.It Fl Fl nofs , Fl Fl ordered
|
|
||||||
Disable Floyd-Steinberg dithering.
|
|
||||||
.It Fl Fl floyd Op Ar =N
|
|
||||||
Set dithering level using fractional number between
|
|
||||||
.Cm 0
|
|
||||||
(none) and
|
|
||||||
.Cm 1
|
|
||||||
(full, the default).
|
|
||||||
.It Fl s Ar N , Fl Fl speed Ar N
|
|
||||||
.Cm 1
|
|
||||||
(brute-force) to
|
|
||||||
.Cm 11
|
|
||||||
(fastest). The default is
|
|
||||||
.Cm 3 .
|
|
||||||
Speed
|
|
||||||
.Cm 10
|
|
||||||
has 5% lower quality, but is about 8 times faster than the default. Speed 11 disables dithering and lowers compression level.
|
|
||||||
.It Fl Q Ar min-max , Fl Fl quality Ar min-max
|
|
||||||
.Va min
|
|
||||||
and
|
|
||||||
.Va max
|
|
||||||
are numbers in range
|
|
||||||
.Cm 0
|
|
||||||
(worst) to
|
|
||||||
.Cm 100
|
|
||||||
(perfect), similar to JPEG.
|
|
||||||
.Nm
|
|
||||||
will use the least amount of colors required to meet or exceed the
|
|
||||||
.Va max
|
|
||||||
quality. If conversion results in quality below the
|
|
||||||
.Va min
|
|
||||||
quality the image won't be saved (or if outputting to stdin, 24-bit original will be output) and pngquant will exit with status code
|
|
||||||
.Er 99 .
|
|
||||||
.It Fl Fl skip-if-larger
|
|
||||||
If conversion results in a file larger than the original the image won't be saved and pngquant will exit with status code
|
|
||||||
.Er 98 .
|
|
||||||
Additionally, file size gain must be greater than the amount of quality lost.
|
|
||||||
.It Fl Fl posterize Ar bits
|
|
||||||
Truncate number of least significant bits of color (per channel). Use this when image will be output on low-depth displays (e.g. 16-bit RGB).
|
|
||||||
.It Fl Fl iebug
|
|
||||||
Workaround for Internet Explorer 6, which only displays fully opaque pixels.
|
|
||||||
.Nm
|
|
||||||
will make almost-opaque pixels fully opaque and will reduce amount of semi-transparent colors. When this option is enabled the default filename suffix is
|
|
||||||
.Ql -ie-fs8.png
|
|
||||||
/
|
|
||||||
.Ql -ie-or8.png .
|
|
||||||
.It Fl Fl transbug
|
|
||||||
Workaround for readers that expect fully transparent color to be the last entry in the palette.
|
|
||||||
.It Fl v , Fl Fl verbose
|
|
||||||
Enable verbose messages showing progress and information about input/output. Opposite is
|
|
||||||
.Fl Fl quiet .
|
|
||||||
Errors are output to
|
|
||||||
.Pa stderr
|
|
||||||
regardless of this option.
|
|
||||||
.It Fl V , Fl Fl version
|
|
||||||
Display version on
|
|
||||||
.Pa stdout
|
|
||||||
and exit.
|
|
||||||
.It Fl h , Fl Fl help
|
|
||||||
Display help and exit.
|
|
||||||
.El
|
|
||||||
.Sh EXAMPLE
|
|
||||||
Creating a new image with the number of colors reduced to 64:
|
|
||||||
.Bd -ragged -offset indent
|
|
||||||
.Nm
|
|
||||||
.Cm 64 image.png
|
|
||||||
.Ed
|
|
||||||
.Pp
|
|
||||||
The resulting image will have 64 colors and will be saved as
|
|
||||||
.Pa image-fs8.png .
|
|
||||||
.Pp
|
|
||||||
Overwriting image in-place if it can be reduced without too much quality loss:
|
|
||||||
.Bd -ragged -offset indent
|
|
||||||
.Nm
|
|
||||||
.Cm -f --ext .png --quality 70-95 image.png
|
|
||||||
.Ed
|
|
||||||
.Sh AUTHOR
|
|
||||||
.Nm
|
|
||||||
is developed by Kornel Lesinski
|
|
||||||
.Aq Mt kornel@pngquant.org
|
|
||||||
based on code by Greg Roelofs
|
|
||||||
.Aq Mt newt@pobox.com .
|
|
||||||
.Pp
|
|
||||||
.Lk http://pngquant.org "pngquant homepage" .
|
|
864
deps/pngquant/pngquant.c
vendored
864
deps/pngquant/pngquant.c
vendored
|
@ -1,864 +0,0 @@
|
||||||
/* pngquant.c - quantize the colors in an alphamap down to a specified number
|
|
||||||
**
|
|
||||||
** Copyright (C) 1989, 1991 by Jef Poskanzer.
|
|
||||||
**
|
|
||||||
** 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.
|
|
||||||
**
|
|
||||||
** - - - -
|
|
||||||
**
|
|
||||||
** © 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
|
|
||||||
** © 2009-2014 by Kornel Lesiński.
|
|
||||||
**
|
|
||||||
** All rights reserved.
|
|
||||||
**
|
|
||||||
** Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
** are permitted provided that the following conditions are met:
|
|
||||||
**
|
|
||||||
** 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
** this list of conditions and the following disclaimer.
|
|
||||||
**
|
|
||||||
** 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
** this list of conditions and the following disclaimer in the documentation
|
|
||||||
** and/or other materials provided with the distribution.
|
|
||||||
**
|
|
||||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
**
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define PNGQUANT_VERSION LIQ_VERSION_STRING " (April 2015)"
|
|
||||||
|
|
||||||
#define PNGQUANT_USAGE "\
|
|
||||||
usage: pngquant [options] [ncolors] -- pngfile [pngfile ...]\n\
|
|
||||||
pngquant [options] [ncolors] - >stdout <stdin\n\n\
|
|
||||||
options:\n\
|
|
||||||
--force overwrite existing output files (synonym: -f)\n\
|
|
||||||
--skip-if-larger only save converted files if they're smaller than original\n\
|
|
||||||
--output file output path, only if one input file is specified (synonym: -o)\n\
|
|
||||||
--ext new.png set custom suffix/extension for output filenames\n\
|
|
||||||
--quality min-max don't save below min, use fewer colors below max (0-100)\n\
|
|
||||||
--speed N speed/quality trade-off. 1=slow, 3=default, 11=fast & rough\n\
|
|
||||||
--nofs disable Floyd-Steinberg dithering\n\
|
|
||||||
--posterize N output lower resolution color (e.g. for ARGB4444 output)\n\
|
|
||||||
--verbose print status messages (synonym: -v)\n\
|
|
||||||
\n\
|
|
||||||
Quantizes one or more 32-bit RGBA PNGs to 8-bit (or smaller) RGBA-palette\n\
|
|
||||||
PNGs using Floyd-Steinberg diffusion dithering (unless disabled).\n\
|
|
||||||
The output filename is the same as the input name except that\n\
|
|
||||||
it ends in \"-fs8.png\", \"-or8.png\" or your custom extension (unless the\n\
|
|
||||||
input is stdin, in which case the quantized image will go to stdout).\n\
|
|
||||||
The default behavior if the output file exists is to skip the conversion;\n\
|
|
||||||
use --force to overwrite. See man page for full list of options.\n"
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
extern char *optarg;
|
|
||||||
extern int optind, opterr;
|
|
||||||
|
|
||||||
#if defined(WIN32) || defined(__WIN32__)
|
|
||||||
# include <fcntl.h> /* O_BINARY */
|
|
||||||
# include <io.h> /* setmode() */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#include <omp.h>
|
|
||||||
#else
|
|
||||||
#define omp_get_max_threads() 1
|
|
||||||
#define omp_get_thread_num() 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "rwpng.h" /* typedefs, common macros, public prototypes */
|
|
||||||
#include "lib/libimagequant.h"
|
|
||||||
|
|
||||||
struct pngquant_options {
|
|
||||||
liq_attr *liq;
|
|
||||||
liq_image *fixed_palette_image;
|
|
||||||
liq_log_callback_function *log_callback;
|
|
||||||
void *log_callback_user_info;
|
|
||||||
float floyd;
|
|
||||||
bool using_stdin, using_stdout, force, fast_compression, ie_mode,
|
|
||||||
min_quality_limit, skip_if_larger,
|
|
||||||
verbose;
|
|
||||||
};
|
|
||||||
|
|
||||||
static pngquant_error prepare_output_image(liq_result *result, liq_image *input_image, png8_image *output_image);
|
|
||||||
static void set_palette(liq_result *result, png8_image *output_image);
|
|
||||||
static pngquant_error read_image(liq_attr *options, const char *filename, int using_stdin, png24_image *input_image_p, liq_image **liq_image_p, bool keep_input_pixels, bool verbose);
|
|
||||||
static pngquant_error write_image(png8_image *output_image, png24_image *output_image24, const char *outname, struct pngquant_options *options);
|
|
||||||
static char *add_filename_extension(const char *filename, const char *newext);
|
|
||||||
static bool file_exists(const char *outname);
|
|
||||||
|
|
||||||
static void verbose_printf(struct pngquant_options *context, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
if (context->log_callback) {
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
int required_space = vsnprintf(NULL, 0, fmt, va)+1; // +\0
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
char buf[required_space];
|
|
||||||
va_start(va, fmt);
|
|
||||||
vsnprintf(buf, required_space, fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
|
|
||||||
context->log_callback(context->liq, buf, context->log_callback_user_info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_callback(const liq_attr *attr, const char *msg, void* user_info)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s\n", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#define LOG_BUFFER_SIZE 1300
|
|
||||||
struct buffered_log {
|
|
||||||
int buf_used;
|
|
||||||
char buf[LOG_BUFFER_SIZE];
|
|
||||||
};
|
|
||||||
|
|
||||||
static void log_callback_buferred_flush(const liq_attr *attr, void *context)
|
|
||||||
{
|
|
||||||
struct buffered_log *log = context;
|
|
||||||
if (log->buf_used) {
|
|
||||||
fwrite(log->buf, 1, log->buf_used, stderr);
|
|
||||||
fflush(stderr);
|
|
||||||
log->buf_used = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void log_callback_buferred(const liq_attr *attr, const char *msg, void* context)
|
|
||||||
{
|
|
||||||
struct buffered_log *log = context;
|
|
||||||
int len = strlen(msg);
|
|
||||||
if (len > LOG_BUFFER_SIZE-2) len = LOG_BUFFER_SIZE-2;
|
|
||||||
|
|
||||||
if (len > LOG_BUFFER_SIZE - log->buf_used - 2) log_callback_buferred_flush(attr, log);
|
|
||||||
memcpy(&log->buf[log->buf_used], msg, len);
|
|
||||||
log->buf_used += len+1;
|
|
||||||
log->buf[log->buf_used-1] = '\n';
|
|
||||||
log->buf[log->buf_used] = '\0';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void print_full_version(FILE *fd)
|
|
||||||
{
|
|
||||||
fprintf(fd, "pngquant, %s, by Greg Roelofs, Kornel Lesinski.\n"
|
|
||||||
#ifndef NDEBUG
|
|
||||||
" DEBUG (slow) version.\n" /* NDEBUG disables assert() */
|
|
||||||
#endif
|
|
||||||
#if USE_SSE
|
|
||||||
" Compiled with SSE instructions.\n"
|
|
||||||
#endif
|
|
||||||
#if _OPENMP
|
|
||||||
" Compiled with OpenMP (multicore support).\n"
|
|
||||||
#endif
|
|
||||||
, PNGQUANT_VERSION);
|
|
||||||
rwpng_version_info(fd);
|
|
||||||
fputs("\n", fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_usage(FILE *fd)
|
|
||||||
{
|
|
||||||
fputs(PNGQUANT_USAGE, fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* N = automatic quality, uses limit unless force is set (N-N or 0-N)
|
|
||||||
* -N = no better than N (same as 0-N)
|
|
||||||
* N-M = no worse than N, no better than M
|
|
||||||
* N- = no worse than N, perfect if possible (same as N-100)
|
|
||||||
*
|
|
||||||
* where N,M are numbers between 0 (lousy) and 100 (perfect)
|
|
||||||
*/
|
|
||||||
static bool parse_quality(const char *quality, liq_attr *options, bool *min_quality_limit)
|
|
||||||
{
|
|
||||||
long limit, target;
|
|
||||||
const char *str = quality; char *end;
|
|
||||||
|
|
||||||
long t1 = strtol(str, &end, 10);
|
|
||||||
if (str == end) return false;
|
|
||||||
str = end;
|
|
||||||
|
|
||||||
if ('\0' == end[0] && t1 < 0) { // quality="-%d"
|
|
||||||
target = -t1;
|
|
||||||
limit = 0;
|
|
||||||
} else if ('\0' == end[0]) { // quality="%d"
|
|
||||||
target = t1;
|
|
||||||
limit = t1*9/10;
|
|
||||||
} else if ('-' == end[0] && '\0' == end[1]) { // quality="%d-"
|
|
||||||
target = 100;
|
|
||||||
limit = t1;
|
|
||||||
} else { // quality="%d-%d"
|
|
||||||
long t2 = strtol(str, &end, 10);
|
|
||||||
if (str == end || t2 > 0) return false;
|
|
||||||
target = -t2;
|
|
||||||
limit = t1;
|
|
||||||
}
|
|
||||||
|
|
||||||
*min_quality_limit = (limit > 0);
|
|
||||||
return LIQ_OK == liq_set_quality(options, limit, target);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct {const char *old; const char *newopt;} obsolete_options[] = {
|
|
||||||
{"-fs","--floyd=1"},
|
|
||||||
{"-nofs", "--ordered"},
|
|
||||||
{"-floyd", "--floyd=1"},
|
|
||||||
{"-nofloyd", "--ordered"},
|
|
||||||
{"-ordered", "--ordered"},
|
|
||||||
{"-force", "--force"},
|
|
||||||
{"-noforce", "--no-force"},
|
|
||||||
{"-verbose", "--verbose"},
|
|
||||||
{"-quiet", "--quiet"},
|
|
||||||
{"-noverbose", "--quiet"},
|
|
||||||
{"-noquiet", "--verbose"},
|
|
||||||
{"-help", "--help"},
|
|
||||||
{"-version", "--version"},
|
|
||||||
{"-ext", "--ext"},
|
|
||||||
{"-speed", "--speed"},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void fix_obsolete_options(const unsigned int argc, char *argv[])
|
|
||||||
{
|
|
||||||
for(unsigned int argn=1; argn < argc; argn++) {
|
|
||||||
if ('-' != argv[argn][0]) continue;
|
|
||||||
|
|
||||||
if ('-' == argv[argn][1]) break; // stop on first --option or --
|
|
||||||
|
|
||||||
for(unsigned int i=0; i < sizeof(obsolete_options)/sizeof(obsolete_options[0]); i++) {
|
|
||||||
if (0 == strcmp(obsolete_options[i].old, argv[argn])) {
|
|
||||||
fprintf(stderr, " warning: option '%s' has been replaced with '%s'.\n", obsolete_options[i].old, obsolete_options[i].newopt);
|
|
||||||
argv[argn] = (char*)obsolete_options[i].newopt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum {arg_floyd=1, arg_ordered, arg_ext, arg_no_force, arg_iebug,
|
|
||||||
arg_transbug, arg_map, arg_posterize, arg_skip_larger};
|
|
||||||
|
|
||||||
static const struct option long_options[] = {
|
|
||||||
{"verbose", no_argument, NULL, 'v'},
|
|
||||||
{"quiet", no_argument, NULL, 'q'},
|
|
||||||
{"force", no_argument, NULL, 'f'},
|
|
||||||
{"no-force", no_argument, NULL, arg_no_force},
|
|
||||||
{"floyd", optional_argument, NULL, arg_floyd},
|
|
||||||
{"ordered", no_argument, NULL, arg_ordered},
|
|
||||||
{"nofs", no_argument, NULL, arg_ordered},
|
|
||||||
{"iebug", no_argument, NULL, arg_iebug},
|
|
||||||
{"transbug", no_argument, NULL, arg_transbug},
|
|
||||||
{"ext", required_argument, NULL, arg_ext},
|
|
||||||
{"skip-if-larger", no_argument, NULL, arg_skip_larger},
|
|
||||||
{"output", required_argument, NULL, 'o'},
|
|
||||||
{"speed", required_argument, NULL, 's'},
|
|
||||||
{"quality", required_argument, NULL, 'Q'},
|
|
||||||
{"posterize", required_argument, NULL, arg_posterize},
|
|
||||||
{"map", required_argument, NULL, arg_map},
|
|
||||||
{"version", no_argument, NULL, 'V'},
|
|
||||||
{"help", no_argument, NULL, 'h'},
|
|
||||||
{NULL, 0, NULL, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
pngquant_error pngquant_file(const char *filename, const char *outname, struct pngquant_options *options);
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
struct pngquant_options options = {
|
|
||||||
.floyd = 1.f, // floyd-steinberg dithering
|
|
||||||
};
|
|
||||||
options.liq = liq_attr_create();
|
|
||||||
|
|
||||||
if (!options.liq) {
|
|
||||||
fputs("SSE-capable CPU is required for this build.\n", stderr);
|
|
||||||
return WRONG_ARCHITECTURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int error_count=0, skipped_count=0, file_count=0;
|
|
||||||
pngquant_error latest_error=SUCCESS;
|
|
||||||
const char *newext = NULL, *output_file_path = NULL;
|
|
||||||
|
|
||||||
fix_obsolete_options(argc, argv);
|
|
||||||
|
|
||||||
int opt;
|
|
||||||
do {
|
|
||||||
opt = getopt_long(argc, argv, "Vvqfhs:Q:o:", long_options, NULL);
|
|
||||||
switch (opt) {
|
|
||||||
case 'v':
|
|
||||||
options.verbose = true;
|
|
||||||
break;
|
|
||||||
case 'q':
|
|
||||||
options.verbose = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case arg_floyd:
|
|
||||||
options.floyd = optarg ? atof(optarg) : 1.0;
|
|
||||||
if (options.floyd < 0 || options.floyd > 1.f) {
|
|
||||||
fputs("--floyd argument must be in 0..1 range\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case arg_ordered: options.floyd = 0; break;
|
|
||||||
|
|
||||||
case 'f': options.force = true; break;
|
|
||||||
case arg_no_force: options.force = false; break;
|
|
||||||
|
|
||||||
case arg_ext: newext = optarg; break;
|
|
||||||
case 'o':
|
|
||||||
if (output_file_path) {
|
|
||||||
fputs("--output option can be used only once\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
output_file_path = optarg; break;
|
|
||||||
|
|
||||||
case arg_iebug:
|
|
||||||
// opacities above 238 will be rounded up to 255, because IE6 truncates <255 to 0.
|
|
||||||
liq_set_min_opacity(options.liq, 238);
|
|
||||||
options.ie_mode = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case arg_transbug:
|
|
||||||
liq_set_last_index_transparent(options.liq, true);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case arg_skip_larger:
|
|
||||||
options.skip_if_larger = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
{
|
|
||||||
int speed = atoi(optarg);
|
|
||||||
if (speed >= 10) {
|
|
||||||
options.fast_compression = true;
|
|
||||||
}
|
|
||||||
if (speed == 11) {
|
|
||||||
options.floyd = 0;
|
|
||||||
speed = 10;
|
|
||||||
}
|
|
||||||
if (LIQ_OK != liq_set_speed(options.liq, speed)) {
|
|
||||||
fputs("Speed should be between 1 (slow) and 11 (fast).\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'Q':
|
|
||||||
if (!parse_quality(optarg, options.liq, &options.min_quality_limit)) {
|
|
||||||
fputs("Quality should be in format min-max where min and max are numbers in range 0-100.\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case arg_posterize:
|
|
||||||
if (LIQ_OK != liq_set_min_posterization(options.liq, atoi(optarg))) {
|
|
||||||
fputs("Posterization should be number of bits in range 0-4.\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case arg_map:
|
|
||||||
{
|
|
||||||
png24_image tmp = {};
|
|
||||||
if (SUCCESS != read_image(options.liq, optarg, false, &tmp, &options.fixed_palette_image, false, false)) {
|
|
||||||
fprintf(stderr, " error: unable to load %s", optarg);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
print_full_version(stdout);
|
|
||||||
print_usage(stdout);
|
|
||||||
return SUCCESS;
|
|
||||||
|
|
||||||
case 'V':
|
|
||||||
puts(PNGQUANT_VERSION);
|
|
||||||
return SUCCESS;
|
|
||||||
|
|
||||||
case -1: break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
} while (opt != -1);
|
|
||||||
|
|
||||||
int argn = optind;
|
|
||||||
|
|
||||||
if (argn >= argc) {
|
|
||||||
if (argn > 1) {
|
|
||||||
fputs("No input files specified.\n", stderr);
|
|
||||||
} else {
|
|
||||||
print_full_version(stderr);
|
|
||||||
}
|
|
||||||
print_usage(stderr);
|
|
||||||
return MISSING_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.verbose) {
|
|
||||||
liq_set_log_callback(options.liq, log_callback, NULL);
|
|
||||||
options.log_callback = log_callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *colors_end;
|
|
||||||
unsigned long colors = strtoul(argv[argn], &colors_end, 10);
|
|
||||||
if (colors_end != argv[argn] && '\0' == colors_end[0]) {
|
|
||||||
if (LIQ_OK != liq_set_max_colors(options.liq, colors)) {
|
|
||||||
fputs("Number of colors must be between 2 and 256.\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
argn++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newext && output_file_path) {
|
|
||||||
fputs("--ext and --output options can't be used at the same time\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
// new filename extension depends on options used. Typically basename-fs8.png
|
|
||||||
if (newext == NULL) {
|
|
||||||
newext = options.floyd > 0 ? "-ie-fs8.png" : "-ie-or8.png";
|
|
||||||
if (!options.ie_mode) {
|
|
||||||
newext += 3; /* skip "-ie" */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argn == argc || (argn == argc-1 && 0==strcmp(argv[argn],"-"))) {
|
|
||||||
options.using_stdin = true;
|
|
||||||
options.using_stdout = !output_file_path;
|
|
||||||
argn = argc-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const int num_files = argc-argn;
|
|
||||||
|
|
||||||
if (output_file_path && num_files != 1) {
|
|
||||||
fputs("Only one input file is allowed when --output is used\n", stderr);
|
|
||||||
return INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
// if there's a lot of files, coarse parallelism can be used
|
|
||||||
if (num_files > 2*omp_get_max_threads()) {
|
|
||||||
omp_set_nested(0);
|
|
||||||
omp_set_dynamic(1);
|
|
||||||
} else {
|
|
||||||
omp_set_nested(1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#pragma omp parallel for \
|
|
||||||
schedule(static, 1) reduction(+:skipped_count) reduction(+:error_count) reduction(+:file_count) shared(latest_error)
|
|
||||||
for(int i=0; i < num_files; i++) {
|
|
||||||
struct pngquant_options opts = options;
|
|
||||||
opts.liq = liq_attr_copy(options.liq);
|
|
||||||
|
|
||||||
const char *filename = opts.using_stdin ? "stdin" : argv[argn+i];
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
struct buffered_log buf = {};
|
|
||||||
if (opts.log_callback && omp_get_num_threads() > 1 && num_files > 1) {
|
|
||||||
liq_set_log_callback(opts.liq, log_callback_buferred, &buf);
|
|
||||||
liq_set_log_flush_callback(opts.liq, log_callback_buferred_flush, &buf);
|
|
||||||
options.log_callback = log_callback_buferred;
|
|
||||||
options.log_callback_user_info = &buf;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
pngquant_error retval = SUCCESS;
|
|
||||||
|
|
||||||
const char *outname = output_file_path;
|
|
||||||
char *outname_free = NULL;
|
|
||||||
if (!options.using_stdout) {
|
|
||||||
if (!outname) {
|
|
||||||
outname = outname_free = add_filename_extension(filename, newext);
|
|
||||||
}
|
|
||||||
if (!options.force && file_exists(outname)) {
|
|
||||||
fprintf(stderr, " error: '%s' exists; not overwriting\n", outname);
|
|
||||||
retval = NOT_OVERWRITING_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCESS == retval) {
|
|
||||||
retval = pngquant_file(filename, outname, &opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(outname_free);
|
|
||||||
|
|
||||||
liq_attr_destroy(opts.liq);
|
|
||||||
|
|
||||||
if (retval) {
|
|
||||||
#pragma omp critical
|
|
||||||
{
|
|
||||||
latest_error = retval;
|
|
||||||
}
|
|
||||||
if (retval == TOO_LOW_QUALITY || retval == TOO_LARGE_FILE) {
|
|
||||||
skipped_count++;
|
|
||||||
} else {
|
|
||||||
error_count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++file_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error_count) {
|
|
||||||
verbose_printf(&options, "There were errors quantizing %d file%s out of a total of %d file%s.",
|
|
||||||
error_count, (error_count == 1)? "" : "s", file_count, (file_count == 1)? "" : "s");
|
|
||||||
}
|
|
||||||
if (skipped_count) {
|
|
||||||
verbose_printf(&options, "Skipped %d file%s out of a total of %d file%s.",
|
|
||||||
skipped_count, (skipped_count == 1)? "" : "s", file_count, (file_count == 1)? "" : "s");
|
|
||||||
}
|
|
||||||
if (!skipped_count && !error_count) {
|
|
||||||
verbose_printf(&options, "No errors detected while quantizing %d image%s.",
|
|
||||||
file_count, (file_count == 1)? "" : "s");
|
|
||||||
}
|
|
||||||
|
|
||||||
liq_image_destroy(options.fixed_palette_image);
|
|
||||||
liq_attr_destroy(options.liq);
|
|
||||||
|
|
||||||
return latest_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pngquant_error pngquant_file(const char *filename, const char *outname, struct pngquant_options *options)
|
|
||||||
{
|
|
||||||
pngquant_error retval = SUCCESS;
|
|
||||||
|
|
||||||
verbose_printf(options, "%s:", filename);
|
|
||||||
|
|
||||||
liq_image *input_image = NULL;
|
|
||||||
png24_image input_image_rwpng = {};
|
|
||||||
bool keep_input_pixels = options->skip_if_larger || (options->using_stdout && options->min_quality_limit); // original may need to be output to stdout
|
|
||||||
if (SUCCESS == retval) {
|
|
||||||
retval = read_image(options->liq, filename, options->using_stdin, &input_image_rwpng, &input_image, keep_input_pixels, options->verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
int quality_percent = 90; // quality on 0-100 scale, updated upon successful remap
|
|
||||||
png8_image output_image = {};
|
|
||||||
if (SUCCESS == retval) {
|
|
||||||
verbose_printf(options, " read %luKB file", (input_image_rwpng.file_size+1023UL)/1024UL);
|
|
||||||
|
|
||||||
#if USE_LCMS
|
|
||||||
if (input_image_rwpng.lcms_status == ICCP) {
|
|
||||||
verbose_printf(options, " used embedded ICC profile to transform image to sRGB colorspace");
|
|
||||||
} else if (input_image_rwpng.lcms_status == GAMA_CHRM) {
|
|
||||||
verbose_printf(options, " used gAMA and cHRM chunks to transform image to sRGB colorspace");
|
|
||||||
} else if (input_image_rwpng.lcms_status == ICCP_WARN_GRAY) {
|
|
||||||
verbose_printf(options, " warning: ignored ICC profile in GRAY colorspace");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (input_image_rwpng.gamma != 0.45455) {
|
|
||||||
verbose_printf(options, " corrected image from gamma %2.1f to sRGB gamma",
|
|
||||||
1.0/input_image_rwpng.gamma);
|
|
||||||
}
|
|
||||||
|
|
||||||
// when using image as source of a fixed palette the palette is extracted using regular quantization
|
|
||||||
liq_result *remap = liq_quantize_image(options->liq, options->fixed_palette_image ? options->fixed_palette_image : input_image);
|
|
||||||
|
|
||||||
if (remap) {
|
|
||||||
liq_set_output_gamma(remap, 0.45455); // fixed gamma ~2.2 for the web. PNG can't store exact 1/2.2
|
|
||||||
liq_set_dithering_level(remap, options->floyd);
|
|
||||||
|
|
||||||
retval = prepare_output_image(remap, input_image, &output_image);
|
|
||||||
if (SUCCESS == retval) {
|
|
||||||
if (LIQ_OK != liq_write_remapped_image_rows(remap, input_image, output_image.row_pointers)) {
|
|
||||||
retval = OUT_OF_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_palette(remap, &output_image);
|
|
||||||
|
|
||||||
double palette_error = liq_get_quantization_error(remap);
|
|
||||||
if (palette_error >= 0) {
|
|
||||||
quality_percent = liq_get_quantization_quality(remap);
|
|
||||||
verbose_printf(options, " mapped image to new colors...MSE=%.3f (Q=%d)", palette_error, quality_percent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
liq_result_destroy(remap);
|
|
||||||
} else {
|
|
||||||
retval = TOO_LOW_QUALITY;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCESS == retval) {
|
|
||||||
|
|
||||||
if (options->skip_if_larger) {
|
|
||||||
// this is very rough approximation, but generally avoid losing more quality than is gained in file size.
|
|
||||||
// Quality is squared, because even greater savings are needed to justify big quality loss.
|
|
||||||
double quality = quality_percent/100.0;
|
|
||||||
output_image.maximum_file_size = (input_image_rwpng.file_size-1) * quality*quality;
|
|
||||||
}
|
|
||||||
|
|
||||||
output_image.fast_compression = options->fast_compression;
|
|
||||||
output_image.chunks = input_image_rwpng.chunks; input_image_rwpng.chunks = NULL;
|
|
||||||
retval = write_image(&output_image, NULL, outname, options);
|
|
||||||
|
|
||||||
if (TOO_LARGE_FILE == retval) {
|
|
||||||
verbose_printf(options, " file exceeded expected size of %luKB", (unsigned long)output_image.maximum_file_size/1024UL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options->using_stdout && keep_input_pixels && (TOO_LARGE_FILE == retval || TOO_LOW_QUALITY == retval)) {
|
|
||||||
// when outputting to stdout it'd be nasty to create 0-byte file
|
|
||||||
// so if quality is too low, output 24-bit original
|
|
||||||
pngquant_error write_retval = write_image(NULL, &input_image_rwpng, outname, options);
|
|
||||||
if (write_retval) {
|
|
||||||
retval = write_retval;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
liq_image_destroy(input_image);
|
|
||||||
rwpng_free_image24(&input_image_rwpng);
|
|
||||||
rwpng_free_image8(&output_image);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_palette(liq_result *result, png8_image *output_image)
|
|
||||||
{
|
|
||||||
const liq_palette *palette = liq_get_palette(result);
|
|
||||||
|
|
||||||
// tRNS, etc.
|
|
||||||
output_image->num_palette = palette->count;
|
|
||||||
output_image->num_trans = 0;
|
|
||||||
for(unsigned int i=0; i < palette->count; i++) {
|
|
||||||
liq_color px = palette->entries[i];
|
|
||||||
if (px.a < 255) {
|
|
||||||
output_image->num_trans = i+1;
|
|
||||||
}
|
|
||||||
output_image->palette[i] = (png_color){.red=px.r, .green=px.g, .blue=px.b};
|
|
||||||
output_image->trans[i] = px.a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static bool file_exists(const char *outname)
|
|
||||||
{
|
|
||||||
FILE *outfile = fopen(outname, "rb");
|
|
||||||
if ((outfile ) != NULL) {
|
|
||||||
fclose(outfile);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build the output filename from the input name by inserting "-fs8" or
|
|
||||||
* "-or8" before the ".png" extension (or by appending that plus ".png" if
|
|
||||||
* there isn't any extension), then make sure it doesn't exist already */
|
|
||||||
static char *add_filename_extension(const char *filename, const char *newext)
|
|
||||||
{
|
|
||||||
size_t x = strlen(filename);
|
|
||||||
|
|
||||||
char* outname = malloc(x+4+strlen(newext)+1);
|
|
||||||
if (!outname) return NULL;
|
|
||||||
|
|
||||||
strncpy(outname, filename, x);
|
|
||||||
if (strncmp(outname+x-4, ".png", 4) == 0 || strncmp(outname+x-4, ".PNG", 4) == 0) {
|
|
||||||
strcpy(outname+x-4, newext);
|
|
||||||
} else {
|
|
||||||
strcpy(outname+x, newext);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outname;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *temp_filename(const char *basename) {
|
|
||||||
size_t x = strlen(basename);
|
|
||||||
|
|
||||||
char *outname = malloc(x+1+4);
|
|
||||||
if (!outname) return NULL;
|
|
||||||
|
|
||||||
strcpy(outname, basename);
|
|
||||||
strcpy(outname+x, ".tmp");
|
|
||||||
|
|
||||||
return outname;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void set_binary_mode(FILE *fp)
|
|
||||||
{
|
|
||||||
#if defined(WIN32) || defined(__WIN32__)
|
|
||||||
setmode(fp == stdout ? 1 : 0, O_BINARY);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *filename_part(const char *path)
|
|
||||||
{
|
|
||||||
const char *outfilename = strrchr(path, '/');
|
|
||||||
if (outfilename) {
|
|
||||||
return outfilename+1;
|
|
||||||
} else {
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool replace_file(const char *from, const char *to, const bool force) {
|
|
||||||
#if defined(WIN32) || defined(__WIN32__)
|
|
||||||
if (force) {
|
|
||||||
// On Windows rename doesn't replace
|
|
||||||
unlink(to);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return (0 == rename(from, to));
|
|
||||||
}
|
|
||||||
|
|
||||||
static pngquant_error write_image(png8_image *output_image, png24_image *output_image24, const char *outname, struct pngquant_options *options)
|
|
||||||
{
|
|
||||||
FILE *outfile;
|
|
||||||
char *tempname = NULL;
|
|
||||||
|
|
||||||
if (options->using_stdout) {
|
|
||||||
set_binary_mode(stdout);
|
|
||||||
outfile = stdout;
|
|
||||||
|
|
||||||
if (output_image) {
|
|
||||||
verbose_printf(options, " writing %d-color image to stdout", output_image->num_palette);
|
|
||||||
} else {
|
|
||||||
verbose_printf(options, " writing truecolor image to stdout");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tempname = temp_filename(outname);
|
|
||||||
if (!tempname) return OUT_OF_MEMORY_ERROR;
|
|
||||||
|
|
||||||
if ((outfile = fopen(tempname, "wb")) == NULL) {
|
|
||||||
fprintf(stderr, " error: cannot open '%s' for writing\n", tempname);
|
|
||||||
free(tempname);
|
|
||||||
return CANT_WRITE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (output_image) {
|
|
||||||
verbose_printf(options, " writing %d-color image as %s", output_image->num_palette, filename_part(outname));
|
|
||||||
} else {
|
|
||||||
verbose_printf(options, " writing truecolor image as %s", filename_part(outname));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pngquant_error retval;
|
|
||||||
#pragma omp critical (libpng)
|
|
||||||
{
|
|
||||||
if (output_image) {
|
|
||||||
retval = rwpng_write_image8(outfile, output_image);
|
|
||||||
} else {
|
|
||||||
retval = rwpng_write_image24(outfile, output_image24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!options->using_stdout) {
|
|
||||||
fclose(outfile);
|
|
||||||
|
|
||||||
if (SUCCESS == retval) {
|
|
||||||
// Image has been written to a temporary file and then moved over destination.
|
|
||||||
// This makes replacement atomic and avoids damaging destination file on write error.
|
|
||||||
if (!replace_file(tempname, outname, options->force)) {
|
|
||||||
retval = CANT_WRITE_ERROR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval) {
|
|
||||||
unlink(tempname);
|
|
||||||
}
|
|
||||||
free(tempname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval && retval != TOO_LARGE_FILE) {
|
|
||||||
fprintf(stderr, " error: failed writing image to %s\n", outname);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pngquant_error read_image(liq_attr *options, const char *filename, int using_stdin, png24_image *input_image_p, liq_image **liq_image_p, bool keep_input_pixels, bool verbose)
|
|
||||||
{
|
|
||||||
FILE *infile;
|
|
||||||
|
|
||||||
if (using_stdin) {
|
|
||||||
set_binary_mode(stdin);
|
|
||||||
infile = stdin;
|
|
||||||
} else if ((infile = fopen(filename, "rb")) == NULL) {
|
|
||||||
fprintf(stderr, " error: cannot open %s for reading\n", filename);
|
|
||||||
return READ_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
pngquant_error retval;
|
|
||||||
#pragma omp critical (libpng)
|
|
||||||
{
|
|
||||||
retval = rwpng_read_image24(infile, input_image_p, verbose);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!using_stdin) {
|
|
||||||
fclose(infile);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retval) {
|
|
||||||
fprintf(stderr, " error: cannot decode image %s\n", using_stdin ? "from stdin" : filename_part(filename));
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
*liq_image_p = liq_image_create_rgba_rows(options, (void**)input_image_p->row_pointers, input_image_p->width, input_image_p->height, input_image_p->gamma);
|
|
||||||
|
|
||||||
if (!*liq_image_p) {
|
|
||||||
return OUT_OF_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!keep_input_pixels) {
|
|
||||||
if (LIQ_OK != liq_image_set_memory_ownership(*liq_image_p, LIQ_OWN_ROWS | LIQ_OWN_PIXELS)) {
|
|
||||||
return OUT_OF_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
input_image_p->row_pointers = NULL;
|
|
||||||
input_image_p->rgba_data = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static pngquant_error prepare_output_image(liq_result *result, liq_image *input_image, png8_image *output_image)
|
|
||||||
{
|
|
||||||
output_image->width = liq_image_get_width(input_image);
|
|
||||||
output_image->height = liq_image_get_height(input_image);
|
|
||||||
output_image->gamma = liq_get_output_gamma(result);
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Step 3.7 [GRR]: allocate memory for the entire indexed image
|
|
||||||
*/
|
|
||||||
|
|
||||||
output_image->indexed_data = malloc(output_image->height * output_image->width);
|
|
||||||
output_image->row_pointers = malloc(output_image->height * sizeof(output_image->row_pointers[0]));
|
|
||||||
|
|
||||||
if (!output_image->indexed_data || !output_image->row_pointers) {
|
|
||||||
return OUT_OF_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned int row = 0; row < output_image->height; ++row) {
|
|
||||||
output_image->row_pointers[row] = output_image->indexed_data + row*output_image->width;
|
|
||||||
}
|
|
||||||
|
|
||||||
const liq_palette *palette = liq_get_palette(result);
|
|
||||||
// tRNS, etc.
|
|
||||||
output_image->num_palette = palette->count;
|
|
||||||
output_image->num_trans = 0;
|
|
||||||
for(unsigned int i=0; i < palette->count; i++) {
|
|
||||||
if (palette->entries[i].a < 255) {
|
|
||||||
output_image->num_trans = i+1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
62
deps/pngquant/pngquant.spec
vendored
62
deps/pngquant/pngquant.spec
vendored
|
@ -1,62 +0,0 @@
|
||||||
Name: pngquant
|
|
||||||
Version: 2.4.1
|
|
||||||
Release: 1%{?dist}
|
|
||||||
Summary: PNG quantization tool for reducing image file size
|
|
||||||
License: BSD
|
|
||||||
URL: http://pngquant.org
|
|
||||||
Source0: https://github.com/pornel/pngquant/archive/%{version}.tar.gz
|
|
||||||
BuildRequires: libpng-devel%{?_isa} >= 1.2.46-1
|
|
||||||
BuildRequires: zlib-devel%{?_isa} >= 1.2.3-1
|
|
||||||
BuildRequires: gcc%{?_isa} >= 4.2-1
|
|
||||||
Requires: libpng%{?_isa} >= 1.2.46-1
|
|
||||||
Requires: zlib%{?isa} >= 1.2.3-1
|
|
||||||
|
|
||||||
%description
|
|
||||||
pngquant converts 24/32-bit RGBA PNG images to 8-bit palette with
|
|
||||||
alpha channel preserved. Such images are compatible with all modern web
|
|
||||||
browsers and a compatibility setting is available to help transparency
|
|
||||||
degrade well in Internet Explorer 6. Quantized files are often 40-70
|
|
||||||
percent smaller than their 24/32-bit version. pngquant uses the
|
|
||||||
median cut algorithm.
|
|
||||||
|
|
||||||
%prep
|
|
||||||
%setup -q -n pngquant-%{version}
|
|
||||||
|
|
||||||
%build
|
|
||||||
./configure --prefix=%{_prefix}
|
|
||||||
make %{?_smp_mflags}
|
|
||||||
|
|
||||||
|
|
||||||
%install
|
|
||||||
rm -rf %{buildroot}
|
|
||||||
mkdir -p %{buildroot}/%{_bindir}
|
|
||||||
make install PREFIX=%{_prefix} DESTDIR=%{buildroot}
|
|
||||||
install -Dpm0755 pngquant %{buildroot}/%{_bindir}/pngquant
|
|
||||||
install -Dpm0644 pngquant.1 %{buildroot}/%{_mandir}/man1/pngquant.1
|
|
||||||
|
|
||||||
|
|
||||||
%files
|
|
||||||
%defattr(-,root,root,-)
|
|
||||||
%doc README.md CHANGELOG COPYRIGHT
|
|
||||||
%{_bindir}/pngquant
|
|
||||||
%{_mandir}/man1/pngquant.1*
|
|
||||||
|
|
||||||
|
|
||||||
%changelog
|
|
||||||
|
|
||||||
* Fri Sep 12 2014 Michael Dec <grepwood@sucs.org> 1.8.3-1
|
|
||||||
- Update to latest upstream version and corrected the .spec
|
|
||||||
|
|
||||||
* Thu May 03 2012 Craig Barnes <cr@igbarn.es> - 1.7.2-1
|
|
||||||
- Update to latest upstream version
|
|
||||||
|
|
||||||
* Sun Jan 15 2012 Craig Barnes <cr@igbarn.es> - 1.7.0-1
|
|
||||||
- Update to latest upstream version
|
|
||||||
|
|
||||||
* Mon Jan 09 2012 Craig Barnes <cr@igbarn.es> - 1.6.4-1
|
|
||||||
- Update to latest version
|
|
||||||
- Remove Makefile patch (merged upstream)
|
|
||||||
- Use prefix macro when installing (upstream changed the default prefix)
|
|
||||||
|
|
||||||
* Wed Dec 28 2011 Craig Barnes <cr@igbarn.es> - 1.6.2-1
|
|
||||||
- Initial package
|
|
615
deps/pngquant/rwpng.c
vendored
615
deps/pngquant/rwpng.c
vendored
|
@ -1,615 +0,0 @@
|
||||||
/*---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
pngquant: RGBA -> RGBA-palette quantization program rwpng.c
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
© 1998-2000 by Greg Roelofs.
|
|
||||||
© 2009-2014 by Kornel Lesiński.
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "png.h"
|
|
||||||
#include "rwpng.h"
|
|
||||||
#if USE_LCMS
|
|
||||||
#include "lcms2.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef Z_BEST_COMPRESSION
|
|
||||||
#define Z_BEST_COMPRESSION 9
|
|
||||||
#endif
|
|
||||||
#ifndef Z_BEST_SPEED
|
|
||||||
#define Z_BEST_SPEED 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _OPENMP
|
|
||||||
#include <omp.h>
|
|
||||||
#else
|
|
||||||
#define omp_get_max_threads() 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PNG_LIBPNG_VER < 10500
|
|
||||||
typedef png_const_charp png_const_bytep;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void rwpng_error_handler(png_structp png_ptr, png_const_charp msg);
|
|
||||||
static void rwpng_warning_stderr_handler(png_structp png_ptr, png_const_charp msg);
|
|
||||||
static void rwpng_warning_silent_handler(png_structp png_ptr, png_const_charp msg);
|
|
||||||
int rwpng_read_image24_cocoa(FILE *infile, png24_image *mainprog_ptr);
|
|
||||||
|
|
||||||
|
|
||||||
void rwpng_version_info(FILE *fp)
|
|
||||||
{
|
|
||||||
const char *pngver = png_get_header_ver(NULL);
|
|
||||||
|
|
||||||
#if USE_COCOA
|
|
||||||
fprintf(fp, " Using Apple Cocoa image reader and libpng %s.\n", pngver);
|
|
||||||
#elif USE_LCMS
|
|
||||||
fprintf(fp, " Using libpng %s with Little CMS color profile support.\n", pngver);
|
|
||||||
#else
|
|
||||||
fprintf(fp, " Using libpng %s.\n", pngver);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if PNG_LIBPNG_VER < 10600
|
|
||||||
if (strcmp(pngver, "1.3.") < 0) {
|
|
||||||
fputs("\nWARNING: Your version of libpng is outdated and may produce corrupted files.\n"
|
|
||||||
"Please recompile pngquant with the current version of libpng (1.6 or later).\n", fp);
|
|
||||||
} else if (strcmp(pngver, "1.6.") < 0) {
|
|
||||||
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
|
|
||||||
fputs("\nWARNING: Your version of libpng is old and has buggy support for custom chunks.\n"
|
|
||||||
"Please recompile pngquant with the current version of libpng (1.6 or later).\n", fp);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct rwpng_read_data {
|
|
||||||
FILE *const fp;
|
|
||||||
png_size_t bytes_read;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
|
||||||
{
|
|
||||||
struct rwpng_read_data *read_data = (struct rwpng_read_data *)png_get_io_ptr(png_ptr);
|
|
||||||
|
|
||||||
png_size_t read = fread(data, 1, length, read_data->fp);
|
|
||||||
if (!read) {
|
|
||||||
png_error(png_ptr, "Read error");
|
|
||||||
}
|
|
||||||
read_data->bytes_read += read;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rwpng_write_state {
|
|
||||||
FILE *outfile;
|
|
||||||
png_size_t maximum_file_size;
|
|
||||||
png_size_t bytes_written;
|
|
||||||
pngquant_error retval;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
|
||||||
{
|
|
||||||
struct rwpng_write_state *write_state = (struct rwpng_write_state *)png_get_io_ptr(png_ptr);
|
|
||||||
|
|
||||||
if (SUCCESS != write_state->retval) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fwrite(data, length, 1, write_state->outfile)) {
|
|
||||||
write_state->retval = CANT_WRITE_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
write_state->bytes_written += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void user_flush_data(png_structp png_ptr)
|
|
||||||
{
|
|
||||||
// libpng never calls this :(
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static png_bytepp rwpng_create_row_pointers(png_infop info_ptr, png_structp png_ptr, unsigned char *base, unsigned int height, unsigned int rowbytes)
|
|
||||||
{
|
|
||||||
if (!rowbytes) {
|
|
||||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
png_bytepp row_pointers = malloc(height * sizeof(row_pointers[0]));
|
|
||||||
if (!row_pointers) return NULL;
|
|
||||||
for(unsigned int row = 0; row < height; ++row) {
|
|
||||||
row_pointers[row] = base + row * rowbytes;
|
|
||||||
}
|
|
||||||
return row_pointers;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int read_chunk_callback(png_structp png_ptr, png_unknown_chunkp in_chunk)
|
|
||||||
{
|
|
||||||
if (0 == memcmp("iCCP", in_chunk->name, 5) ||
|
|
||||||
0 == memcmp("cHRM", in_chunk->name, 5) ||
|
|
||||||
0 == memcmp("gAMA", in_chunk->name, 5)) {
|
|
||||||
return 0; // not handled
|
|
||||||
}
|
|
||||||
|
|
||||||
struct rwpng_chunk **head = (struct rwpng_chunk **)png_get_user_chunk_ptr(png_ptr);
|
|
||||||
|
|
||||||
struct rwpng_chunk *chunk = malloc(sizeof(struct rwpng_chunk));
|
|
||||||
memcpy(chunk->name, in_chunk->name, 5);
|
|
||||||
chunk->size = in_chunk->size;
|
|
||||||
chunk->location = in_chunk->location;
|
|
||||||
chunk->data = in_chunk->size ? malloc(in_chunk->size) : NULL;
|
|
||||||
if (in_chunk->size) {
|
|
||||||
memcpy(chunk->data, in_chunk->data, in_chunk->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
chunk->next = *head;
|
|
||||||
*head = chunk;
|
|
||||||
|
|
||||||
return 1; // marks as "handled", libpng won't store it
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
retval:
|
|
||||||
0 = success
|
|
||||||
21 = bad sig
|
|
||||||
22 = bad IHDR
|
|
||||||
24 = insufficient memory
|
|
||||||
25 = libpng error (via longjmp())
|
|
||||||
26 = wrong PNG color type (no alpha channel)
|
|
||||||
*/
|
|
||||||
|
|
||||||
pngquant_error rwpng_read_image24_libpng(FILE *infile, png24_image *mainprog_ptr, int verbose)
|
|
||||||
{
|
|
||||||
png_structp png_ptr = NULL;
|
|
||||||
png_infop info_ptr = NULL;
|
|
||||||
png_size_t rowbytes;
|
|
||||||
int color_type, bit_depth;
|
|
||||||
|
|
||||||
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
|
|
||||||
rwpng_error_handler, verbose ? rwpng_warning_stderr_handler : rwpng_warning_silent_handler);
|
|
||||||
if (!png_ptr) {
|
|
||||||
return PNG_OUT_OF_MEMORY_ERROR; /* out of memory */
|
|
||||||
}
|
|
||||||
|
|
||||||
info_ptr = png_create_info_struct(png_ptr);
|
|
||||||
if (!info_ptr) {
|
|
||||||
png_destroy_read_struct(&png_ptr, NULL, NULL);
|
|
||||||
return PNG_OUT_OF_MEMORY_ERROR; /* out of memory */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setjmp() must be called in every function that calls a non-trivial
|
|
||||||
* libpng function */
|
|
||||||
|
|
||||||
if (setjmp(mainprog_ptr->jmpbuf)) {
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
return LIBPNG_FATAL_ERROR; /* fatal libpng error (via longjmp()) */
|
|
||||||
}
|
|
||||||
|
|
||||||
#if PNG_LIBPNG_VER >= 10500 && defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
|
|
||||||
/* copy standard chunks too */
|
|
||||||
png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_IF_SAFE, (png_const_bytep)"pHYs\0iTXt\0tEXt\0zTXt", 4);
|
|
||||||
#endif
|
|
||||||
png_set_read_user_chunk_fn(png_ptr, &mainprog_ptr->chunks, read_chunk_callback);
|
|
||||||
|
|
||||||
struct rwpng_read_data read_data = {infile, 0};
|
|
||||||
png_set_read_fn(png_ptr, &read_data, user_read_data);
|
|
||||||
|
|
||||||
png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
|
|
||||||
|
|
||||||
|
|
||||||
/* alternatively, could make separate calls to png_get_image_width(),
|
|
||||||
* etc., but want bit_depth and color_type for later [don't care about
|
|
||||||
* compression_type and filter_type => NULLs] */
|
|
||||||
|
|
||||||
png_get_IHDR(png_ptr, info_ptr, &mainprog_ptr->width, &mainprog_ptr->height,
|
|
||||||
&bit_depth, &color_type, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
|
|
||||||
/* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
|
|
||||||
* transparency chunks to full alpha channel; strip 16-bit-per-sample
|
|
||||||
* images to 8 bits per sample; and convert grayscale to RGB[A] */
|
|
||||||
|
|
||||||
/* GRR TO DO: preserve all safe-to-copy ancillary PNG chunks */
|
|
||||||
|
|
||||||
if (!(color_type & PNG_COLOR_MASK_ALPHA)) {
|
|
||||||
#ifdef PNG_READ_FILLER_SUPPORTED
|
|
||||||
png_set_expand(png_ptr);
|
|
||||||
png_set_filler(png_ptr, 65535L, PNG_FILLER_AFTER);
|
|
||||||
#else
|
|
||||||
fprintf(stderr, "pngquant readpng: image is neither RGBA nor GA\n");
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
mainprog_ptr->retval = WRONG_INPUT_COLOR_TYPE;
|
|
||||||
return mainprog_ptr->retval;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bit_depth == 16) {
|
|
||||||
png_set_strip_16(png_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(color_type & PNG_COLOR_MASK_COLOR)) {
|
|
||||||
png_set_gray_to_rgb(png_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* get source gamma for gamma correction, or use sRGB default */
|
|
||||||
double gamma = 0.45455;
|
|
||||||
if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB)) {
|
|
||||||
png_get_gAMA(png_ptr, info_ptr, &gamma);
|
|
||||||
if (gamma < 0 || gamma > 1.0) {
|
|
||||||
fprintf(stderr, "pngquant readpng: ignored out-of-range gamma %f\n", gamma);
|
|
||||||
gamma = 0.45455;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mainprog_ptr->gamma = gamma;
|
|
||||||
|
|
||||||
png_set_interlace_handling(png_ptr);
|
|
||||||
|
|
||||||
/* all transformations have been registered; now update info_ptr data,
|
|
||||||
* get rowbytes and channels, and allocate image memory */
|
|
||||||
|
|
||||||
png_read_update_info(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
|
|
||||||
|
|
||||||
if ((mainprog_ptr->rgba_data = malloc(rowbytes*mainprog_ptr->height)) == NULL) {
|
|
||||||
fprintf(stderr, "pngquant readpng: unable to allocate image data\n");
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
return PNG_OUT_OF_MEMORY_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->rgba_data, mainprog_ptr->height, 0);
|
|
||||||
|
|
||||||
/* now we can go ahead and just read the whole image */
|
|
||||||
|
|
||||||
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) */
|
|
||||||
|
|
||||||
png_read_end(png_ptr, NULL);
|
|
||||||
|
|
||||||
#if USE_LCMS
|
|
||||||
#if PNG_LIBPNG_VER < 10500
|
|
||||||
png_charp ProfileData;
|
|
||||||
#else
|
|
||||||
png_bytep ProfileData;
|
|
||||||
#endif
|
|
||||||
png_uint_32 ProfileLen;
|
|
||||||
|
|
||||||
cmsHPROFILE hInProfile = NULL;
|
|
||||||
|
|
||||||
/* color_type is read from the image before conversion to RGBA */
|
|
||||||
int COLOR_PNG = color_type & PNG_COLOR_MASK_COLOR;
|
|
||||||
|
|
||||||
mainprog_ptr->lcms_status = NONE;
|
|
||||||
|
|
||||||
/* embedded ICC profile */
|
|
||||||
if (png_get_iCCP(png_ptr, info_ptr, &(png_charp){0}, &(int){0}, &ProfileData, &ProfileLen)) {
|
|
||||||
|
|
||||||
hInProfile = cmsOpenProfileFromMem(ProfileData, ProfileLen);
|
|
||||||
cmsColorSpaceSignature colorspace = cmsGetColorSpace(hInProfile);
|
|
||||||
|
|
||||||
/* only RGB (and GRAY) valid for PNGs */
|
|
||||||
if (colorspace == cmsSigRgbData && COLOR_PNG) {
|
|
||||||
mainprog_ptr->lcms_status = ICCP;
|
|
||||||
} else {
|
|
||||||
if (colorspace == cmsSigGrayData && !COLOR_PNG) {
|
|
||||||
mainprog_ptr->lcms_status = ICCP_WARN_GRAY;
|
|
||||||
}
|
|
||||||
cmsCloseProfile(hInProfile);
|
|
||||||
hInProfile = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* build RGB profile from cHRM and gAMA */
|
|
||||||
if (hInProfile == NULL && COLOR_PNG &&
|
|
||||||
!png_get_valid(png_ptr, info_ptr, PNG_INFO_sRGB) &&
|
|
||||||
png_get_valid(png_ptr, info_ptr, PNG_INFO_gAMA) &&
|
|
||||||
png_get_valid(png_ptr, info_ptr, PNG_INFO_cHRM)) {
|
|
||||||
|
|
||||||
cmsCIExyY WhitePoint;
|
|
||||||
cmsCIExyYTRIPLE Primaries;
|
|
||||||
|
|
||||||
png_get_cHRM(png_ptr, info_ptr, &WhitePoint.x, &WhitePoint.y,
|
|
||||||
&Primaries.Red.x, &Primaries.Red.y,
|
|
||||||
&Primaries.Green.x, &Primaries.Green.y,
|
|
||||||
&Primaries.Blue.x, &Primaries.Blue.y);
|
|
||||||
|
|
||||||
WhitePoint.Y = Primaries.Red.Y = Primaries.Green.Y = Primaries.Blue.Y = 1.0;
|
|
||||||
|
|
||||||
cmsToneCurve *GammaTable[3];
|
|
||||||
GammaTable[0] = GammaTable[1] = GammaTable[2] = cmsBuildGamma(NULL, 1/gamma);
|
|
||||||
|
|
||||||
hInProfile = cmsCreateRGBProfile(&WhitePoint, &Primaries, GammaTable);
|
|
||||||
|
|
||||||
cmsFreeToneCurve(GammaTable[0]);
|
|
||||||
|
|
||||||
mainprog_ptr->lcms_status = GAMA_CHRM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* transform image to sRGB colorspace */
|
|
||||||
if (hInProfile != NULL) {
|
|
||||||
|
|
||||||
cmsHPROFILE hOutProfile = cmsCreate_sRGBProfile();
|
|
||||||
cmsHTRANSFORM hTransform = cmsCreateTransform(hInProfile, TYPE_RGBA_8,
|
|
||||||
hOutProfile, TYPE_RGBA_8,
|
|
||||||
INTENT_PERCEPTUAL,
|
|
||||||
omp_get_max_threads() > 1 ? cmsFLAGS_NOCACHE : 0);
|
|
||||||
|
|
||||||
#pragma omp parallel for \
|
|
||||||
if (mainprog_ptr->height*mainprog_ptr->width > 8000) \
|
|
||||||
schedule(static)
|
|
||||||
for (unsigned int i = 0; i < mainprog_ptr->height; i++) {
|
|
||||||
/* It is safe to use the same block for input and output,
|
|
||||||
when both are of the same TYPE. */
|
|
||||||
cmsDoTransform(hTransform, row_pointers[i],
|
|
||||||
row_pointers[i],
|
|
||||||
mainprog_ptr->width);
|
|
||||||
}
|
|
||||||
|
|
||||||
cmsDeleteTransform(hTransform);
|
|
||||||
cmsCloseProfile(hOutProfile);
|
|
||||||
cmsCloseProfile(hInProfile);
|
|
||||||
|
|
||||||
mainprog_ptr->gamma = 0.45455;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
|
|
||||||
|
|
||||||
mainprog_ptr->file_size = read_data.bytes_read;
|
|
||||||
mainprog_ptr->row_pointers = (unsigned char **)row_pointers;
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rwpng_free_chunks(struct rwpng_chunk *chunk) {
|
|
||||||
if (!chunk) return;
|
|
||||||
rwpng_free_chunks(chunk->next);
|
|
||||||
free(chunk->data);
|
|
||||||
free(chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rwpng_free_image24(png24_image *image)
|
|
||||||
{
|
|
||||||
free(image->row_pointers);
|
|
||||||
image->row_pointers = NULL;
|
|
||||||
|
|
||||||
free(image->rgba_data);
|
|
||||||
image->rgba_data = NULL;
|
|
||||||
|
|
||||||
rwpng_free_chunks(image->chunks);
|
|
||||||
image->chunks = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rwpng_free_image8(png8_image *image)
|
|
||||||
{
|
|
||||||
free(image->indexed_data);
|
|
||||||
image->indexed_data = NULL;
|
|
||||||
|
|
||||||
free(image->row_pointers);
|
|
||||||
image->row_pointers = NULL;
|
|
||||||
|
|
||||||
rwpng_free_chunks(image->chunks);
|
|
||||||
image->chunks = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pngquant_error rwpng_read_image24(FILE *infile, png24_image *input_image_p, int verbose)
|
|
||||||
{
|
|
||||||
#if USE_COCOA
|
|
||||||
return rwpng_read_image24_cocoa(infile, input_image_p);
|
|
||||||
#else
|
|
||||||
return rwpng_read_image24_libpng(infile, input_image_p, verbose);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static pngquant_error rwpng_write_image_init(rwpng_png_image *mainprog_ptr, png_structpp png_ptr_p, png_infopp info_ptr_p, int fast_compression)
|
|
||||||
{
|
|
||||||
/* could also replace libpng warning-handler (final NULL), but no need: */
|
|
||||||
|
|
||||||
*png_ptr_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, rwpng_error_handler, NULL);
|
|
||||||
|
|
||||||
if (!(*png_ptr_p)) {
|
|
||||||
return LIBPNG_INIT_ERROR; /* out of memory */
|
|
||||||
}
|
|
||||||
|
|
||||||
*info_ptr_p = png_create_info_struct(*png_ptr_p);
|
|
||||||
if (!(*info_ptr_p)) {
|
|
||||||
png_destroy_write_struct(png_ptr_p, NULL);
|
|
||||||
return LIBPNG_INIT_ERROR; /* out of memory */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setjmp() must be called in every function that calls a PNG-writing
|
|
||||||
* libpng function, unless an alternate error handler was installed--
|
|
||||||
* but compatible error handlers must either use longjmp() themselves
|
|
||||||
* (as in this program) or exit immediately, so here we go: */
|
|
||||||
|
|
||||||
if (setjmp(mainprog_ptr->jmpbuf)) {
|
|
||||||
png_destroy_write_struct(png_ptr_p, info_ptr_p);
|
|
||||||
return LIBPNG_INIT_ERROR; /* libpng error (via longjmp()) */
|
|
||||||
}
|
|
||||||
|
|
||||||
png_set_compression_level(*png_ptr_p, fast_compression ? Z_BEST_SPEED : Z_BEST_COMPRESSION);
|
|
||||||
png_set_compression_mem_level(*png_ptr_p, fast_compression ? 9 : 5); // judging by optipng results, smaller mem makes libpng compress slightly better
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void rwpng_write_end(png_infopp info_ptr_p, png_structpp png_ptr_p, png_bytepp row_pointers)
|
|
||||||
{
|
|
||||||
png_write_info(*png_ptr_p, *info_ptr_p);
|
|
||||||
|
|
||||||
png_set_packing(*png_ptr_p);
|
|
||||||
|
|
||||||
png_write_image(*png_ptr_p, row_pointers);
|
|
||||||
|
|
||||||
png_write_end(*png_ptr_p, NULL);
|
|
||||||
|
|
||||||
png_destroy_write_struct(png_ptr_p, info_ptr_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rwpng_set_gamma(png_infop info_ptr, png_structp png_ptr, double gamma)
|
|
||||||
{
|
|
||||||
/* remap sets gamma to 0.45455 */
|
|
||||||
png_set_gAMA(png_ptr, info_ptr, gamma);
|
|
||||||
png_set_sRGB(png_ptr, info_ptr, 0); // 0 = Perceptual
|
|
||||||
}
|
|
||||||
|
|
||||||
pngquant_error rwpng_write_image8(FILE *outfile, const png8_image *mainprog_ptr)
|
|
||||||
{
|
|
||||||
png_structp png_ptr;
|
|
||||||
png_infop info_ptr;
|
|
||||||
|
|
||||||
pngquant_error retval = rwpng_write_image_init((rwpng_png_image*)mainprog_ptr, &png_ptr, &info_ptr, mainprog_ptr->fast_compression);
|
|
||||||
if (retval) return retval;
|
|
||||||
|
|
||||||
struct rwpng_write_state write_state;
|
|
||||||
write_state = (struct rwpng_write_state){
|
|
||||||
.outfile = outfile,
|
|
||||||
.maximum_file_size = mainprog_ptr->maximum_file_size,
|
|
||||||
.retval = SUCCESS,
|
|
||||||
};
|
|
||||||
png_set_write_fn(png_ptr, &write_state, user_write_data, user_flush_data);
|
|
||||||
|
|
||||||
// Palette images generally don't gain anything from filtering
|
|
||||||
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_FILTER_VALUE_NONE);
|
|
||||||
|
|
||||||
rwpng_set_gamma(info_ptr, png_ptr, mainprog_ptr->gamma);
|
|
||||||
|
|
||||||
/* set the image parameters appropriately */
|
|
||||||
int sample_depth;
|
|
||||||
#if PNG_LIBPNG_VER > 10400 /* old libpng corrupts files with low depth */
|
|
||||||
if (mainprog_ptr->num_palette <= 2)
|
|
||||||
sample_depth = 1;
|
|
||||||
else if (mainprog_ptr->num_palette <= 4)
|
|
||||||
sample_depth = 2;
|
|
||||||
else if (mainprog_ptr->num_palette <= 16)
|
|
||||||
sample_depth = 4;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
sample_depth = 8;
|
|
||||||
|
|
||||||
struct rwpng_chunk *chunk = mainprog_ptr->chunks;
|
|
||||||
int chunk_num=0;
|
|
||||||
while(chunk) {
|
|
||||||
png_unknown_chunk pngchunk = {
|
|
||||||
.size = chunk->size,
|
|
||||||
.data = chunk->data,
|
|
||||||
.location = chunk->location,
|
|
||||||
};
|
|
||||||
memcpy(pngchunk.name, chunk->name, 5);
|
|
||||||
png_set_unknown_chunks(png_ptr, info_ptr, &pngchunk, 1);
|
|
||||||
|
|
||||||
#if defined(PNG_HAVE_IHDR) && PNG_LIBPNG_VER < 10600
|
|
||||||
png_set_unknown_chunk_location(png_ptr, info_ptr, chunk_num, pngchunk.location ? pngchunk.location : PNG_HAVE_IHDR);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
chunk = chunk->next;
|
|
||||||
chunk_num++;
|
|
||||||
}
|
|
||||||
|
|
||||||
png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
|
|
||||||
sample_depth, PNG_COLOR_TYPE_PALETTE,
|
|
||||||
0, PNG_COMPRESSION_TYPE_DEFAULT,
|
|
||||||
PNG_FILTER_TYPE_BASE);
|
|
||||||
|
|
||||||
png_set_PLTE(png_ptr, info_ptr, &mainprog_ptr->palette[0], mainprog_ptr->num_palette);
|
|
||||||
|
|
||||||
if (mainprog_ptr->num_trans > 0) {
|
|
||||||
png_set_tRNS(png_ptr, info_ptr, mainprog_ptr->trans, mainprog_ptr->num_trans, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
rwpng_write_end(&info_ptr, &png_ptr, mainprog_ptr->row_pointers);
|
|
||||||
|
|
||||||
if (SUCCESS == write_state.retval && write_state.maximum_file_size && write_state.bytes_written > write_state.maximum_file_size) {
|
|
||||||
return TOO_LARGE_FILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return write_state.retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
pngquant_error rwpng_write_image24(FILE *outfile, const png24_image *mainprog_ptr)
|
|
||||||
{
|
|
||||||
png_structp png_ptr;
|
|
||||||
png_infop info_ptr;
|
|
||||||
|
|
||||||
pngquant_error retval = rwpng_write_image_init((rwpng_png_image*)mainprog_ptr, &png_ptr, &info_ptr, 0);
|
|
||||||
if (retval) return retval;
|
|
||||||
|
|
||||||
png_init_io(png_ptr, outfile);
|
|
||||||
|
|
||||||
rwpng_set_gamma(info_ptr, png_ptr, mainprog_ptr->gamma);
|
|
||||||
|
|
||||||
png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
|
|
||||||
8, PNG_COLOR_TYPE_RGB_ALPHA,
|
|
||||||
0, PNG_COMPRESSION_TYPE_DEFAULT,
|
|
||||||
PNG_FILTER_TYPE_BASE);
|
|
||||||
|
|
||||||
|
|
||||||
png_bytepp row_pointers = rwpng_create_row_pointers(info_ptr, png_ptr, mainprog_ptr->rgba_data, mainprog_ptr->height, 0);
|
|
||||||
|
|
||||||
rwpng_write_end(&info_ptr, &png_ptr, row_pointers);
|
|
||||||
|
|
||||||
free(row_pointers);
|
|
||||||
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void rwpng_warning_stderr_handler(png_structp png_ptr, png_const_charp msg) {
|
|
||||||
fprintf(stderr, " %s\n", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rwpng_warning_silent_handler(png_structp png_ptr, png_const_charp msg) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rwpng_error_handler(png_structp png_ptr, png_const_charp msg)
|
|
||||||
{
|
|
||||||
rwpng_png_image *mainprog_ptr;
|
|
||||||
|
|
||||||
/* This function, aside from the extra step of retrieving the "error
|
|
||||||
* pointer" (below) and the fact that it exists within the application
|
|
||||||
* rather than within libpng, is essentially identical to libpng's
|
|
||||||
* default error handler. The second point is critical: since both
|
|
||||||
* setjmp() and longjmp() are called from the same code, they are
|
|
||||||
* guaranteed to have compatible notions of how big a jmp_buf is,
|
|
||||||
* regardless of whether _BSD_SOURCE or anything else has (or has not)
|
|
||||||
* been defined. */
|
|
||||||
|
|
||||||
fprintf(stderr, " error: %s (libpng failed)\n", msg);
|
|
||||||
fflush(stderr);
|
|
||||||
|
|
||||||
mainprog_ptr = png_get_error_ptr(png_ptr);
|
|
||||||
if (mainprog_ptr == NULL) abort();
|
|
||||||
|
|
||||||
longjmp(mainprog_ptr->jmpbuf, 1);
|
|
||||||
}
|
|
125
deps/pngquant/rwpng.h
vendored
125
deps/pngquant/rwpng.h
vendored
|
@ -1,125 +0,0 @@
|
||||||
/*---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
pngquant: RGBA -> RGBA-palette quantization program rwpng.h
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
© 1998-2000 by Greg Roelofs.
|
|
||||||
© 2009-2014 by Kornel Lesiński.
|
|
||||||
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef RWPNG_H
|
|
||||||
#define RWPNG_H
|
|
||||||
|
|
||||||
#include "png.h" /* if this include fails, you need to install libpng (e.g. libpng-devel package) and run ./configure */
|
|
||||||
#include <setjmp.h>
|
|
||||||
|
|
||||||
#ifndef USE_COCOA
|
|
||||||
#define USE_COCOA 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SUCCESS = 0,
|
|
||||||
MISSING_ARGUMENT = 1,
|
|
||||||
READ_ERROR = 2,
|
|
||||||
INVALID_ARGUMENT = 4,
|
|
||||||
NOT_OVERWRITING_ERROR = 15,
|
|
||||||
CANT_WRITE_ERROR = 16,
|
|
||||||
OUT_OF_MEMORY_ERROR = 17,
|
|
||||||
WRONG_ARCHITECTURE = 18, // Missing SSE
|
|
||||||
PNG_OUT_OF_MEMORY_ERROR = 24,
|
|
||||||
LIBPNG_FATAL_ERROR = 25,
|
|
||||||
WRONG_INPUT_COLOR_TYPE = 26,
|
|
||||||
LIBPNG_INIT_ERROR = 35,
|
|
||||||
TOO_LARGE_FILE = 98,
|
|
||||||
TOO_LOW_QUALITY = 99,
|
|
||||||
} pngquant_error;
|
|
||||||
|
|
||||||
struct rwpng_chunk {
|
|
||||||
struct rwpng_chunk *next;
|
|
||||||
png_byte *data;
|
|
||||||
png_size_t size;
|
|
||||||
png_byte name[5];
|
|
||||||
png_byte location;
|
|
||||||
};
|
|
||||||
|
|
||||||
#if USE_LCMS
|
|
||||||
typedef enum {
|
|
||||||
NONE = 0,
|
|
||||||
ICCP = 1, // used ICC profile
|
|
||||||
ICCP_WARN_GRAY = 2, // ignore and warn about GRAY ICC profile
|
|
||||||
GAMA_CHRM = 3, // used gAMA and cHARM
|
|
||||||
} lcms_transform;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
jmp_buf jmpbuf;
|
|
||||||
png_uint_32 width;
|
|
||||||
png_uint_32 height;
|
|
||||||
png_size_t file_size;
|
|
||||||
double gamma;
|
|
||||||
unsigned char **row_pointers;
|
|
||||||
unsigned char *rgba_data;
|
|
||||||
struct rwpng_chunk *chunks;
|
|
||||||
#if USE_LCMS
|
|
||||||
lcms_transform lcms_status;
|
|
||||||
#endif
|
|
||||||
} png24_image;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
jmp_buf jmpbuf;
|
|
||||||
png_uint_32 width;
|
|
||||||
png_uint_32 height;
|
|
||||||
png_size_t maximum_file_size;
|
|
||||||
double gamma;
|
|
||||||
unsigned char **row_pointers;
|
|
||||||
unsigned char *indexed_data;
|
|
||||||
unsigned int num_palette;
|
|
||||||
unsigned int num_trans;
|
|
||||||
png_color palette[256];
|
|
||||||
unsigned char trans[256];
|
|
||||||
struct rwpng_chunk *chunks;
|
|
||||||
char fast_compression;
|
|
||||||
} png8_image;
|
|
||||||
|
|
||||||
typedef union {
|
|
||||||
jmp_buf jmpbuf;
|
|
||||||
png24_image png24;
|
|
||||||
png8_image png8;
|
|
||||||
} rwpng_png_image;
|
|
||||||
|
|
||||||
/* prototypes for public functions in rwpng.c */
|
|
||||||
|
|
||||||
void rwpng_version_info(FILE *fp);
|
|
||||||
|
|
||||||
pngquant_error rwpng_read_image24(FILE *infile, png24_image *mainprog_ptr, int verbose);
|
|
||||||
pngquant_error rwpng_write_image8(FILE *outfile, const png8_image *mainprog_ptr);
|
|
||||||
pngquant_error rwpng_write_image24(FILE *outfile, const png24_image *mainprog_ptr);
|
|
||||||
void rwpng_free_image24(png24_image *);
|
|
||||||
void rwpng_free_image8(png8_image *);
|
|
||||||
|
|
||||||
#endif
|
|
73
deps/pngquant/rwpng_cocoa.m
vendored
73
deps/pngquant/rwpng_cocoa.m
vendored
|
@ -1,73 +0,0 @@
|
||||||
//
|
|
||||||
// rwpng_cocoa.m
|
|
||||||
// pngquant
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "rwpng.h"
|
|
||||||
|
|
||||||
#ifdef USE_COCOA
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <CoreGraphics/CoreGraphics.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "lib/libimagequant.h"
|
|
||||||
#include "lib/pam.h"
|
|
||||||
|
|
||||||
int rwpng_read_image24_cocoa(FILE *fp, png24_image *out)
|
|
||||||
{
|
|
||||||
rgba_pixel *pixel_data;
|
|
||||||
int width, height;
|
|
||||||
@autoreleasepool {
|
|
||||||
NSFileHandle *fh = [[NSFileHandle alloc] initWithFileDescriptor:fileno(fp)];
|
|
||||||
NSData *data = [fh readDataToEndOfFile];
|
|
||||||
out->file_size = [data length];
|
|
||||||
CGImageRef image = [[NSBitmapImageRep imageRepWithData:data] CGImage];
|
|
||||||
[fh release];
|
|
||||||
|
|
||||||
if (!image) return READ_ERROR;
|
|
||||||
|
|
||||||
width = CGImageGetWidth(image);
|
|
||||||
height = CGImageGetHeight(image);
|
|
||||||
|
|
||||||
pixel_data = calloc(width*height,4);
|
|
||||||
|
|
||||||
CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
|
|
||||||
|
|
||||||
CGContextRef context = CGBitmapContextCreate(pixel_data,
|
|
||||||
width, height,
|
|
||||||
8, width*4,
|
|
||||||
colorspace,
|
|
||||||
kCGImageAlphaPremultipliedLast);
|
|
||||||
|
|
||||||
CGColorSpaceRelease(colorspace);
|
|
||||||
|
|
||||||
if (!context) return READ_ERROR;
|
|
||||||
|
|
||||||
CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), image);
|
|
||||||
CGContextRelease(context);
|
|
||||||
}
|
|
||||||
// reverse premultiplication
|
|
||||||
|
|
||||||
for(int i=0; i < width*height; i++) {
|
|
||||||
if (pixel_data[i].a) {
|
|
||||||
pixel_data[i] = (rgba_pixel){
|
|
||||||
.a = pixel_data[i].a,
|
|
||||||
.r = pixel_data[i].r*255/pixel_data[i].a,
|
|
||||||
.g = pixel_data[i].g*255/pixel_data[i].a,
|
|
||||||
.b = pixel_data[i].b*255/pixel_data[i].a,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out->gamma = 0.45455;
|
|
||||||
out->width = width;
|
|
||||||
out->height = height;
|
|
||||||
out->rgba_data = (unsigned char *)pixel_data;
|
|
||||||
out->row_pointers = malloc(sizeof(out->row_pointers[0])*out->height);
|
|
||||||
for(int i=0; i < out->height; i++) {
|
|
||||||
out->row_pointers[i] = (unsigned char *)&pixel_data[width*i];
|
|
||||||
}
|
|
||||||
return SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -346,12 +346,12 @@ source += Split(
|
||||||
""")
|
""")
|
||||||
|
|
||||||
# libimagequant
|
# libimagequant
|
||||||
lib_env.Append(CFLAGS = "-O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -std=c99")
|
lib_env.Append(CFLAGS = "-O3 -fno-math-errno -funroll-loops -fomit-frame-pointer -std=c99 -msse -mfpmath=sse")
|
||||||
# As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this.
|
# As of GCC 4.5, 387 fp math is significantly slower in C99 mode without this.
|
||||||
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
|
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
|
||||||
if 'gcc' in env['CC']:
|
if 'gcc' in env['CC']:
|
||||||
lib_env.Append(CFLAGS='-fexcess-prevision=fast')
|
lib_env.Append(CFLAGS='-fexcess-prevision=fast')
|
||||||
source += glob.glob("../deps/pngquant/lib/" + "*.c")
|
source += glob.glob("../deps/pngquant/" + "*.c")
|
||||||
|
|
||||||
if env['RUNTIME_LINK'] == "static":
|
if env['RUNTIME_LINK'] == "static":
|
||||||
source += glob.glob('../deps/agg/src/' + '*.cpp')
|
source += glob.glob('../deps/agg/src/' + '*.cpp')
|
||||||
|
|
Loading…
Reference in a new issue