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_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>', ''),
|
||||
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('RUNTIME_LINK', "Set preference for linking dependencies",'shared', ['shared','static']),
|
||||
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 = 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'
|
||||
if env['PLATFORM'] == 'FreeBSD':
|
||||
thread_suffix = ''
|
||||
|
@ -1626,7 +1593,7 @@ if not preconfigured:
|
|||
# prepend to make sure we link locally
|
||||
env.Prepend(CPPPATH = '#deps/agg/include')
|
||||
env.Prepend(LIBPATH = '#deps/agg')
|
||||
env.Prepend(CPPPATH = '#deps/pngquant/lib')
|
||||
env.Prepend(CPPPATH = '#deps/pngquant')
|
||||
env.Prepend(CPPPATH = '#deps/clipper/include')
|
||||
# prepend deps dir for auxillary headers
|
||||
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
|
||||
'ppmquant', part of his wonderful PBMPLUS tool suite.
|
||||
© 1997-2002 by Greg Roelofs; based on an idea by Stefan Schneider.
|
||||
© 2009-2014 by Kornel Lesiński.
|
||||
|
||||
Greg Roelofs hacked it into a (in his words) "slightly cheesy" 'pamquant' back
|
||||
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.
|
||||
All rights reserved.
|
||||
|
||||
Note that both licenses are basically BSD-like; that is, use the code however
|
||||
you like, as long as you acknowledge its origins.
|
||||
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.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
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.
|
||||
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.
|
||||
|
|
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()
|
||||
{
|
||||
#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*))
|
||||
{
|
||||
#if USE_SSE
|
||||
#if __SSE__ || (_M_IX86_FP > 0)
|
||||
if (!is_sse_available()) {
|
||||
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[])
|
||||
{
|
||||
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);
|
||||
|
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
|
||||
|
||||
#ifndef USE_SSE
|
||||
# if defined(__SSE__) && (defined(WIN32) || defined(__WIN32__))
|
||||
# define USE_SSE 1
|
||||
# else
|
||||
# define USE_SSE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if USE_SSE
|
||||
#if __SSE__ || (_M_IX86_FP > 0)
|
||||
# include <xmmintrin.h>
|
||||
# ifdef _MSC_VER
|
||||
# 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);
|
||||
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 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
|
||||
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.
|
||||
# Note: CPUs without SSE2 use 387 for doubles, even when SSE fp math is set.
|
||||
if 'gcc' in env['CC']:
|
||||
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":
|
||||
source += glob.glob('../deps/agg/src/' + '*.cpp')
|
||||
|
|
Loading…
Reference in a new issue