You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1497 lines
49 KiB
1497 lines
49 KiB
8 years ago
|
diff --git a/.gitignore b/.gitignore
|
||
|
index 3fa052c..3d432d8 100644
|
||
|
--- a/.gitignore
|
||
|
+++ b/.gitignore
|
||
|
@@ -8,5 +8,8 @@ build
|
||
|
DerivedData
|
||
|
pngquant
|
||
|
lib/libimagequant.a
|
||
|
+*.obj
|
||
|
+*.lib
|
||
|
config.mk
|
||
|
test/test
|
||
|
+target/
|
||
|
--- /dev/null
|
||
|
+++ b/Cargo.toml
|
||
|
@@ -0,0 +1,39 @@
|
||
|
+[package]
|
||
|
+authors = ["Kornel Lesiński <kornel@pngquant.org>"]
|
||
|
+build = "rust/build.rs"
|
||
|
+categories = ["multimedia::images"]
|
||
|
+description = "Convert 24/32-bit images to 8-bit palette with alpha channel.\nBindings for libimagequant that powers pngquant lossy PNG compressor.\n\nDual-licensed like pngquant. See https://pngquant.org for details."
|
||
|
+documentation= "https://github.com/pornel/pngquant#readme"
|
||
|
+homepage = "https://pngquant.org"
|
||
|
+include = ["rwpng*", "pngquant.c", "rust/*", "COPYRIGHT", "Cargo.toml", "README.md"]
|
||
|
+keywords = ["quantization", "palette", "image", "pngquant", "compression"]
|
||
|
+license = "GPL-3.0+"
|
||
|
+name = "pngquant"
|
||
|
+repository = "https://github.com/pornel/pngquant.git"
|
||
|
+version = "2.9.1"
|
||
|
+
|
||
|
+[[bin]]
|
||
|
+name = "pngquant"
|
||
|
+path = "rust/bin.rs"
|
||
|
+
|
||
|
+[build-dependencies]
|
||
|
+gcc = "0.3.51"
|
||
|
+
|
||
|
+[dependencies]
|
||
|
+getopts = "0.2.14"
|
||
|
+libpng-sys = "0.1"
|
||
|
+
|
||
|
+[dependencies.imagequant-sys]
|
||
|
+path = "lib"
|
||
|
+version = "0.1.1"
|
||
|
+
|
||
|
+[dependencies.lcms2-sys]
|
||
|
+optional = true
|
||
|
+version = "2.4.1"
|
||
|
+
|
||
|
+[features]
|
||
|
+default = ["sse", "lcms2"]
|
||
|
+cocoa = []
|
||
|
+lcms2 = ["lcms2-sys"]
|
||
|
+sse = ["imagequant-sys/sse"]
|
||
|
+alloc_system = []
|
||
|
diff --git a/INSTALL b/INSTALL
|
||
|
index 9aab09b..059dfb8 100644
|
||
|
--- a/INSTALL
|
||
|
+++ b/INSTALL
|
||
|
@@ -9,6 +9,8 @@ To get the code:
|
||
|
You will need libpng installed with development headers.
|
||
|
On Linux install `libpng-dev` package. On macOS `brew install libpng`.
|
||
|
|
||
|
+There's an optional `./configure` step (see sections below). Run:
|
||
|
+
|
||
|
make
|
||
|
|
||
|
It will create `pngquant` executable in the current directory. If you'd like
|
||
|
@@ -24,12 +26,53 @@ pngquant uses GNU Makefile. To compile on FreeBSD you will need to use `gmake`.
|
||
|
Avoid Linux distros that ship with libpng 1.2. It is old and buggy.
|
||
|
Use libpng 1.6 or later.
|
||
|
|
||
|
+If you have Rust, you can also build with `cargo build`.
|
||
|
+
|
||
|
+
|
||
|
+### Custom static libpng
|
||
|
+
|
||
|
+Extract libpng source code as a *sub*directory of pngquant source directory.
|
||
|
+Build static libpng (`./configure --enable-static && make`), and then
|
||
|
+`./configure && make` pngquant.
|
||
|
+
|
||
|
+When building with Cargo, `export PNG_STATIC=1`.
|
||
|
+
|
||
|
## Windows
|
||
|
|
||
|
-Compiling on Windows is horrible. Please use pre-built binaries if possible.
|
||
|
+Compiling on Windows can be done in two ways: using Rust or using C toolchain.
|
||
|
+
|
||
|
+### Building with Rust's Cargo
|
||
|
+
|
||
|
+This is the easiest option.
|
||
|
|
||
|
-Install git (msys-git). Install mingw or mingw64, depending on your OS version.
|
||
|
-Ensure system PATH environment variable to contains `C:\mingw\bin`.
|
||
|
+Install git (msys-git).
|
||
|
+
|
||
|
+Install Visual C++ 2015 Build Tools.
|
||
|
+
|
||
|
+Install Rust (https://www.rust-lang.org/install.html)
|
||
|
+
|
||
|
+Restart Windows.
|
||
|
+
|
||
|
+Open Git's Bash prompt and run:
|
||
|
+
|
||
|
+ git clone -b msvc --recursive https://github.com/pornel/pngquant.git
|
||
|
+ cd pngquant
|
||
|
+
|
||
|
+This will create pngquant folder in your user folder. And then run:
|
||
|
+
|
||
|
+ cargo build --release
|
||
|
+
|
||
|
+It will create `pngquant.exe` in `target/release` subfolder.
|
||
|
+
|
||
|
+
|
||
|
+### Building using C toolchain
|
||
|
+
|
||
|
+It's going to be much harder. Please reconsider the Rust/Cargo option.
|
||
|
+
|
||
|
+Install git (msys-git).
|
||
|
+
|
||
|
+Install mingw64. Ensure system PATH environment variable
|
||
|
+contains `C:\mingw64\bin`.
|
||
|
|
||
|
Restart Windows.
|
||
|
|
||
|
@@ -89,10 +132,25 @@ to libpng.
|
||
|
Enables support for ICC v2/v4 color profiles when reading images.
|
||
|
Requires Little CMS library available via `pgk-config` (e.g. install `liblcms2-dev`).
|
||
|
|
||
|
+When building with Cargo lcms2 is used by default. It's linked dynamically if
|
||
|
+`pkg-config` is working. Otherwise uses static build as a fallback.
|
||
|
+Set `export LCMS2_STATIC=1` to force static linking in Cargo.
|
||
|
+
|
||
|
|
||
|
-##Compilation of `libimagequant.a` only
|
||
|
+## 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.
|
||
|
+The library doesn't need libpng nor zlib.
|
||
|
+
|
||
|
+
|
||
|
+## Compilation with other versions of libimagequant
|
||
|
+
|
||
|
+This is an advanced option for Linux distributions wishing to unbundle libimagequant.
|
||
|
+
|
||
|
+Option `--with-libimagequant` makes `./configure` query pkg-config for `imagequant`.
|
||
|
+
|
||
|
+Additionally, `--with-libimagequant=<dir>` makes `./configure` search in `<dir>/lib`
|
||
|
+for `libimagequant.so` and `<dir>/include` for `libimagequant.h`.
|
||
|
|
||
|
+ ./configure --with-libimagequant=/usr/local
|
||
|
diff --git a/Makefile b/Makefile
|
||
|
index 50213fa..0c1e3fc 100644
|
||
|
--- a/Makefile
|
||
|
+++ b/Makefile
|
||
|
@@ -1,61 +1,47 @@
|
||
|
-include config.mk
|
||
|
|
||
|
+LIQSRCDIR ?= lib
|
||
|
BIN ?= pngquant
|
||
|
BINPREFIX ?= $(DESTDIR)$(PREFIX)/bin
|
||
|
MANPREFIX ?= $(DESTDIR)$(PREFIX)/share/man
|
||
|
|
||
|
-OBJS = pngquant.o rwpng.o
|
||
|
+OBJS = pngquant.o pngquant_opts.o rwpng.o
|
||
|
COCOA_OBJS = rwpng_cocoa.o
|
||
|
|
||
|
ifeq (1, $(COCOA_READER))
|
||
|
OBJS += $(COCOA_OBJS)
|
||
|
endif
|
||
|
|
||
|
-STATICLIB = lib/libimagequant.a
|
||
|
-SHAREDLIB = lib/libimagequant.so
|
||
|
-
|
||
|
+STATICLIB = $(LIQSRCDIR)/libimagequant.a
|
||
|
DISTFILES = *.[chm] pngquant.1 Makefile configure README.md INSTALL CHANGELOG COPYRIGHT
|
||
|
TARNAME = pngquant-$(VERSION)
|
||
|
TARFILE = $(TARNAME)-src.tar.gz
|
||
|
|
||
|
-LIBDISTFILES = lib/*.[ch] lib/COPYRIGHT lib/README.md lib/configure lib/Makefile
|
||
|
+LIBDISTFILES = $(LIQSRCDIR)/*.[ch] $(LIQSRCDIR)/COPYRIGHT $(LIQSRCDIR)/README.md $(LIQSRCDIR)/configure $(LIQSRCDIR)/Makefile
|
||
|
|
||
|
TESTBIN = test/test
|
||
|
|
||
|
all: $(BIN)
|
||
|
|
||
|
-staticlib: $(STATICLIB)
|
||
|
-
|
||
|
-$(STATICLIB): config.mk $(LIBDISTFILES)
|
||
|
- $(MAKE) -C lib static
|
||
|
+$(LIQSRCDIR)/config.mk: config.mk
|
||
|
+ ( cd '$(LIQSRCDIR)'; ./configure $(LIQCONFIGUREFLAGS) )
|
||
|
|
||
|
-sharedlib: lib/libimagequant.h
|
||
|
- $(MAKE) -C lib shared
|
||
|
-
|
||
|
-$(SHAREDLIB): config.mk sharedlib
|
||
|
+$(STATICLIB): $(LIQSRCDIR)/config.mk $(LIBDISTFILES)
|
||
|
+ $(MAKE) -C '$(LIQSRCDIR)' static
|
||
|
|
||
|
$(OBJS): $(wildcard *.h) config.mk
|
||
|
|
||
|
rwpng_cocoa.o: rwpng_cocoa.m
|
||
|
$(CC) -Wno-enum-conversion -c $(CFLAGS) -o $@ $< &> /dev/null || clang -Wno-enum-conversion -c -O3 -o $@ $<
|
||
|
|
||
|
-$(BIN): $(OBJS) $(STATICLIB)
|
||
|
- $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
|
||
|
+$(BIN): $(OBJS) $(STATICLIBDEPS)
|
||
|
+ $(CC) $(OBJS) $(CFLAGS) $(LDFLAGS) -o $@
|
||
|
|
||
|
-$(TESTBIN): test/test.o $(STATICLIB)
|
||
|
- $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $@
|
||
|
+$(TESTBIN): test/test.o $(STATICLIBDEPS)
|
||
|
+ $(CC) test/test.o $(CFLAGS) $(LDFLAGS) -o $@
|
||
|
|
||
|
test: $(BIN) $(TESTBIN)
|
||
|
- ./test/test.sh ./test $(BIN) $(TESTBIN)
|
||
|
-
|
||
|
-bin.shared: $(OBJS) $(SHAREDLIB)
|
||
|
- $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $(BIN)
|
||
|
-
|
||
|
-testbin.shared: test/test.o $(SHAREDLIB)
|
||
|
- $(CC) $^ $(CFLAGS) $(LDFLAGS) -o $(TESTBIN)
|
||
|
-
|
||
|
-test.shared: bin.shared testbin.shared
|
||
|
- ./test/test.sh ./test $(BIN) $(TESTBIN)
|
||
|
+ LD_LIBRARY_PATH='$(LIQSRCDIR)' ./test/test.sh ./test $(BIN) $(TESTBIN)
|
||
|
|
||
|
dist: $(TARFILE)
|
||
|
|
||
|
@@ -79,20 +65,17 @@ uninstall:
|
||
|
rm -f '$(MANPREFIX)/man1/$(BIN).1'
|
||
|
|
||
|
clean:
|
||
|
- $(MAKE) -C lib clean
|
||
|
- rm -f '$(BIN)' $(OBJS) $(COCOA_OBJS) $(STATICLIB) $(TARFILE)
|
||
|
+ -test -n '$(LIQSRCDIR)' && $(MAKE) -C '$(LIQSRCDIR)' clean
|
||
|
+ rm -f '$(BIN)' $(OBJS) $(COCOA_OBJS) $(TARFILE)
|
||
|
|
||
|
distclean: clean
|
||
|
- $(MAKE) -C lib distclean
|
||
|
+ -test -n '$(LIQSRCDIR)' && $(MAKE) -C '$(LIQSRCDIR)' distclean
|
||
|
rm -f config.mk pngquant-*-src.tar.gz
|
||
|
|
||
|
-config.mk: lib/libimagequant.h
|
||
|
+config.mk:
|
||
|
ifeq ($(filter %clean %distclean, $(MAKECMDGOALS)), )
|
||
|
./configure
|
||
|
endif
|
||
|
|
||
|
-lib/libimagequant.h:
|
||
|
- git submodule init && git submodule update || true
|
||
|
-
|
||
|
-.PHONY: all clean dist distclean dll install uninstall test staticlib
|
||
|
+.PHONY: all clean dist distclean dll install uninstall test
|
||
|
.DELETE_ON_ERROR:
|
||
|
diff --git a/README.md b/README.md
|
||
|
index 5311a47..cc7900e 100644
|
||
|
--- a/README.md
|
||
|
+++ b/README.md
|
||
|
@@ -49,7 +49,7 @@ 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.
|
||
|
+Speed/quality trade-off from 1 (slowest, highest quality, smallest files) to 11 (fastest, less consistent quality, light comperssion). The default is 3. It's recommended to keep the default, unless you need to generate images in real time (e.g. map tiles). Higher speeds are fine with 256 colors, but don't handle lower number of colors well.
|
||
|
|
||
|
### `--nofs`
|
||
|
|
||
|
diff --git a/configure b/configure
|
||
|
index 2952d59..7879f4e 100755
|
||
|
--- a/configure
|
||
|
+++ b/configure
|
||
|
@@ -3,14 +3,9 @@
|
||
|
CONFIG="config.mk"
|
||
|
PREFIX="/usr/local"
|
||
|
|
||
|
-test -f lib/libimagequant.h || { git submodule init && git submodule update; } || {
|
||
|
- echo "error: libimagequant not found in ./lib/"
|
||
|
- echo "If you're using git, do clone with --recursive, or download from https://github.com/ImageOptim/libimagequant"
|
||
|
- exit 1;
|
||
|
-}
|
||
|
-VERSION=$(grep LIQ_VERSION_STRING lib/libimagequant.h | grep -Eo "2\.[0-9.]+")
|
||
|
-
|
||
|
DEBUG=
|
||
|
+LIQSRCDIR=./lib
|
||
|
+LIQCONFIGURE=(--quiet)
|
||
|
SSE=auto
|
||
|
OPENMP=
|
||
|
LIBPNG_DIR=.
|
||
|
@@ -34,7 +29,7 @@ help() {
|
||
|
|
||
|
for i in "$@"; do
|
||
|
case $i in
|
||
|
- --help)
|
||
|
+ --help|-h)
|
||
|
echo
|
||
|
help "--prefix=<dir> installation directory [$PREFIX]"
|
||
|
help "--extra-cflags=<flags> append to CFLAGS"
|
||
|
@@ -43,6 +38,7 @@ for i in "$@"; do
|
||
|
help "--enable-debug"
|
||
|
help "--enable-sse/--disable-sse enable/disable SSE instructions"
|
||
|
echo
|
||
|
+ help "--with-libimagequant=<dir> external libimagequant (lib/ default)"
|
||
|
help "--with-openmp=static compile with multicore support"
|
||
|
help "--with-lcms2/--without-lcms2 compile with color profile support"
|
||
|
if [[ "$OSTYPE" =~ "darwin" ]]; then
|
||
|
@@ -60,27 +56,35 @@ fi
|
||
|
CC=*)
|
||
|
CC=${i#*=}
|
||
|
SKIP_CC_CHECK=1
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
CFLAGS=*)
|
||
|
CFLAGS=${i#*=}
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
LDFLAGS=*)
|
||
|
LDFLAGS=${i#*=}
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--enable-debug)
|
||
|
DEBUG=1
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--enable-sse)
|
||
|
SSE=1
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--disable-sse)
|
||
|
SSE=0
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--with-openmp)
|
||
|
OPENMP=1
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--with-openmp=static)
|
||
|
OPENMP=static
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--with-lcms2)
|
||
|
LCMS2=1
|
||
|
@@ -99,15 +103,24 @@ fi
|
||
|
--with-libpng=*)
|
||
|
LIBPNG_DIR=${i#*=}
|
||
|
;;
|
||
|
+ --with-libimagequant=*)
|
||
|
+ LIQSRCDIR=${i#*=}
|
||
|
+ ;;
|
||
|
+ --with-libimagequant)
|
||
|
+ LIQSRCDIR=""
|
||
|
+ ;;
|
||
|
--prefix=*)
|
||
|
PREFIX=${i#*=}
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
# can be used multiple times or in quotes to set multiple flags
|
||
|
--extra-cflags=*)
|
||
|
EXTRA_CFLAGS="$EXTRA_CFLAGS ${i#*=}"
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
--extra-ldflags=*)
|
||
|
EXTRA_LDFLAGS="$EXTRA_LDFLAGS ${i#*=}"
|
||
|
+ LIQCONFIGURE+=("$i")
|
||
|
;;
|
||
|
*)
|
||
|
echo "warning: unknown switch ${i%%=*} (see $0 --help for the list)"
|
||
|
@@ -157,7 +170,8 @@ find_pkgconfig() {
|
||
|
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"))"
|
||
|
+ LIBRARY_FOUND_VERSION=$(pkg-config --modversion "$LIBNAME")
|
||
|
+ status "$LIBNAME" "shared ($LIBRARY_FOUND_VERSION)"
|
||
|
return 0
|
||
|
fi
|
||
|
return 1
|
||
|
@@ -172,9 +186,10 @@ find_static() {
|
||
|
if [ -n "$HPATH" ]; then
|
||
|
local APATH=$(find_f . "$STATICPATTERN")
|
||
|
if [ -n "$APATH" ]; then
|
||
|
+ LIBRARY_FOUND_HEADER=$HPATH
|
||
|
cflags "-I${HPATH%/*}"
|
||
|
lflags "${APATH}"
|
||
|
- status "$LIBNAME" "static"
|
||
|
+ status "$LIBNAME" "static ($APATH)"
|
||
|
return 0
|
||
|
fi
|
||
|
fi
|
||
|
@@ -192,6 +207,7 @@ find_dynamic() {
|
||
|
if [ -n "$HPATH" ]; then
|
||
|
local SOPATH=$(find_f "$LIBDIR" "$DYNAMICPATTERN")
|
||
|
if [ -n "$SOPATH" ]; then
|
||
|
+ LIBRARY_FOUND_HEADER=$HPATH
|
||
|
cflags "-I${HPATH%/*}"
|
||
|
lflags "-L${SOPATH%/*} -l$DYNAMICLIBNAME"
|
||
|
status "$LIBNAME" "shared ... $SOPATH"
|
||
|
@@ -208,6 +224,20 @@ find_library() {
|
||
|
local STATICPATTERN=$4
|
||
|
local DYNAMICPATTERN=$5
|
||
|
|
||
|
+ # other functions will overwrite it
|
||
|
+ LIBRARY_FOUND_HEADER=
|
||
|
+ LIBRARY_FOUND_VERSION=
|
||
|
+ LIBRARY_FOUND_BUILD=
|
||
|
+
|
||
|
+ if [ "imagequant" = "$LIBNAME" -a -n "$LIQSRCDIR" -a -f "$LIQSRCDIR"/"$HEADERPATTERN" ]; then
|
||
|
+ status "$LIBNAME" "build static"
|
||
|
+ cflags "-I$LIQSRCDIR"
|
||
|
+ lflags "$LIQSRCDIR/libimagequant.a"
|
||
|
+ LIBRARY_FOUND_HEADER="$LIQSRCDIR"/"$HEADERPATTERN"
|
||
|
+ LIBRARY_FOUND_BUILD="$LIQSRCDIR"
|
||
|
+ return 0;
|
||
|
+ fi
|
||
|
+
|
||
|
# try static in current directory first
|
||
|
if find_static "$LIBNAME" "$HEADERPATTERN" "$STATICPATTERN"; then
|
||
|
return 0;
|
||
|
@@ -341,7 +371,13 @@ if command -v >/dev/null libpng-config; then
|
||
|
DIRS+=("$(libpng-config --prefix) $(libpng-config --libdir)")
|
||
|
fi
|
||
|
|
||
|
-DIRS+=("/usr/local/include /usr/local/lib"
|
||
|
+if [ -n $"LIQSRCDIR" ]; then
|
||
|
+ DIRS+=("$LIQSRCDIR" "$LIQSRCDIR") # local libimagequant
|
||
|
+fi
|
||
|
+
|
||
|
+DIRS+=(
|
||
|
+ "/usr/local/include /usr/local/lib"
|
||
|
+ "/usr/include /usr/lib64"
|
||
|
"/usr/include /usr/lib"
|
||
|
"/opt/local/include /opt/local/lib" # macports
|
||
|
)
|
||
|
@@ -361,6 +397,34 @@ else
|
||
|
fi
|
||
|
|
||
|
|
||
|
+# libimagequant
|
||
|
+if [ "./lib" = "$LIQSRCDIR" -a -d ".git" -a ! -f "lib/libimagequant.h" ]; then
|
||
|
+ git submodule init && git submodule update;
|
||
|
+fi
|
||
|
+
|
||
|
+
|
||
|
+if find_library "imagequant" "imagequant" "libimagequant.h" "libimagequant.a" "libimagequant.$SOLIBSUFFIX*"; then
|
||
|
+ if [ -z "$LIBRARY_FOUND_VERSION" ]; then
|
||
|
+ VERSION=$LIBRARY_FOUND_VERSION
|
||
|
+ elif [ -z "$LIBRARY_FOUND_HEADER" ]; then
|
||
|
+ VERSION=$(grep LIQ_VERSION_STRING "$LIBRARY_FOUND_HEADER" | grep -Eo "2\.[0-9.]+")
|
||
|
+ else
|
||
|
+ VERSION=unknown
|
||
|
+ fi
|
||
|
+
|
||
|
+ if [ -n "$LIBRARY_FOUND_BUILD" ]; then
|
||
|
+ STATICLIBDEPS="$LIBRARY_FOUND_BUILD/libimagequant.h $LIBRARY_FOUND_BUILD/libimagequant.a"
|
||
|
+ LIQSRCDIR="$LIBRARY_FOUND_BUILD"
|
||
|
+ fi
|
||
|
+else
|
||
|
+ if [ -n "$LIQSRCDIR" -a ! -f "$LIQSRCDIR"/libimagequant.h ]; then
|
||
|
+ echo "If you're using git, do clone with --recursive, or download from https://github.com/ImageOptim/libimagequant"
|
||
|
+ error "imagequant" "libimagequant.h not found in $LIQSRCDIR/"
|
||
|
+ else
|
||
|
+ error "imagequant" "not found. Get it from https://github.com/ImageOptim/libimagequant and build it in ./lib/"
|
||
|
+ fi
|
||
|
+fi
|
||
|
+
|
||
|
# libpng
|
||
|
# try if given flags are enough
|
||
|
HAS_LIBPNG=0
|
||
|
@@ -484,7 +548,8 @@ CFLAGS = $CFLAGS
|
||
|
LDFLAGS = $LDFLAGS
|
||
|
COCOA_READER = $COCOA_READER
|
||
|
SOLIBSUFFIX = $SOLIBSUFFIX
|
||
|
+STATICLIBDEPS = $STATICLIBDEPS
|
||
|
+LIQSRCDIR = $LIQSRCDIR
|
||
|
+LIQCONFIGUREFLAGS = $(printf "'%s' " "${LIQCONFIGURE[@]}")
|
||
|
" > "$CONFIG"
|
||
|
|
||
|
-# Configure static library the same way
|
||
|
-cp "$CONFIG" lib/
|
||
|
diff --git a/pngquant.c b/pngquant.c
|
||
|
index 481bf74..68a7f28 100644
|
||
|
--- a/pngquant.c
|
||
|
+++ b/pngquant.c
|
||
|
@@ -39,7 +39,7 @@
|
||
|
**
|
||
|
*/
|
||
|
|
||
|
-#define PNGQUANT_VERSION LIQ_VERSION_STRING " (April 2017)"
|
||
|
+#define PNGQUANT_VERSION LIQ_VERSION_STRING " (June 2017)"
|
||
|
|
||
|
#define PNGQUANT_USAGE "\
|
||
|
usage: pngquant [options] [ncolors] -- pngfile [pngfile ...]\n\
|
||
|
@@ -71,16 +71,13 @@ use --force to overwrite. See man page for full list of options.\n"
|
||
|
#include <string.h>
|
||
|
#include <stdarg.h>
|
||
|
#include <stdbool.h>
|
||
|
-#include <getopt.h>
|
||
|
-#include <unistd.h>
|
||
|
#include <math.h>
|
||
|
|
||
|
-extern char *optarg;
|
||
|
-extern int optind, opterr;
|
||
|
-
|
||
|
-#if defined(WIN32) || defined(__WIN32__)
|
||
|
+#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
|
||
|
# include <fcntl.h> /* O_BINARY */
|
||
|
# include <io.h> /* setmode() */
|
||
|
+#else
|
||
|
+# include <unistd.h>
|
||
|
#endif
|
||
|
|
||
|
#ifdef _OPENMP
|
||
|
@@ -91,19 +88,8 @@ extern int optind, opterr;
|
||
|
#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,
|
||
|
- strip,
|
||
|
- verbose;
|
||
|
-};
|
||
|
+#include "libimagequant.h" /* if you get compile error, add -Ilib to compiler flags */
|
||
|
+#include "pngquant_opts.h"
|
||
|
|
||
|
static pngquant_error prepare_output_image(liq_result *result, liq_image *input_image, rwpng_color_transform tag, png8_image *output_image);
|
||
|
static void set_palette(liq_result *result, png8_image *output_image);
|
||
|
@@ -120,12 +106,19 @@ static void verbose_printf(struct pngquant_options *context, const char *fmt, ..
|
||
|
int required_space = vsnprintf(NULL, 0, fmt, va)+1; // +\0
|
||
|
va_end(va);
|
||
|
|
||
|
+#if defined(_MSC_VER)
|
||
|
+ char *buf = malloc(required_space);
|
||
|
+#else
|
||
|
char buf[required_space];
|
||
|
+#endif
|
||
|
va_start(va, fmt);
|
||
|
vsnprintf(buf, required_space, fmt, va);
|
||
|
va_end(va);
|
||
|
|
||
|
context->log_callback(context->liq, buf, context->log_callback_user_info);
|
||
|
+#if defined(_MSC_VER)
|
||
|
+ free(buf);
|
||
|
+#endif
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -224,268 +217,144 @@ static bool parse_quality(const char *quality, liq_attr *options, bool *min_qual
|
||
|
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, arg_strip};
|
||
|
-
|
||
|
-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},
|
||
|
- {"strip", no_argument, NULL, arg_strip},
|
||
|
- {"map", required_argument, NULL, arg_map},
|
||
|
- {"version", no_argument, NULL, 'V'},
|
||
|
- {"help", no_argument, NULL, 'h'},
|
||
|
- {NULL, 0, NULL, 0},
|
||
|
-};
|
||
|
-
|
||
|
+pngquant_error pngquant_main(struct pngquant_options *options);
|
||
|
pngquant_error pngquant_file(const char *filename, const char *outname, struct pngquant_options *options);
|
||
|
|
||
|
-
|
||
|
+#ifndef PNGQUANT_NO_MAIN
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
struct pngquant_options options = {
|
||
|
.floyd = 1.f, // floyd-steinberg dithering
|
||
|
.strip = false,
|
||
|
};
|
||
|
- options.liq = liq_attr_create();
|
||
|
|
||
|
- if (!options.liq) {
|
||
|
- fputs("SSE-capable CPU is required for this build.\n", stderr);
|
||
|
- return WRONG_ARCHITECTURE;
|
||
|
+ pngquant_error retval = pngquant_parse_options(argc, argv, &options);
|
||
|
+ if (retval != SUCCESS) {
|
||
|
+ return retval;
|
||
|
}
|
||
|
|
||
|
- 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.f;
|
||
|
- 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;
|
||
|
+ return pngquant_main(&options);
|
||
|
+}
|
||
|
+#endif
|
||
|
|
||
|
- case 'f': options.force = true; break;
|
||
|
- case arg_no_force: options.force = false; break;
|
||
|
+pngquant_error pngquant_main(struct pngquant_options *options)
|
||
|
+{
|
||
|
+ if (options->print_version) {
|
||
|
+ puts(PNGQUANT_VERSION);
|
||
|
+ return SUCCESS;
|
||
|
+ }
|
||
|
|
||
|
- 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;
|
||
|
- }
|
||
|
- if (strcmp(optarg, "-") == 0) {
|
||
|
- options.using_stdout = true;
|
||
|
- break;
|
||
|
- }
|
||
|
- 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);
|
||
|
- fputs(" warning: the workaround for IE6 is deprecated\n", stderr);
|
||
|
- 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;
|
||
|
+ if (options->missing_arguments) {
|
||
|
+ print_full_version(stderr);
|
||
|
+ print_usage(stderr);
|
||
|
+ return MISSING_ARGUMENT;
|
||
|
+ }
|
||
|
|
||
|
- 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;
|
||
|
+ if (options->print_help) {
|
||
|
+ print_full_version(stdout);
|
||
|
+ print_usage(stdout);
|
||
|
+ return SUCCESS;
|
||
|
+ }
|
||
|
|
||
|
- 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_strip:
|
||
|
- options.strip = true;
|
||
|
- break;
|
||
|
-
|
||
|
- case arg_map:
|
||
|
- {
|
||
|
- png24_image tmp = {};
|
||
|
- if (SUCCESS != read_image(options.liq, optarg, false, &tmp, &options.fixed_palette_image, true, true, false)) {
|
||
|
- fprintf(stderr, " error: unable to load %s", optarg);
|
||
|
- return INVALID_ARGUMENT;
|
||
|
- }
|
||
|
- liq_result *tmp_quantize = liq_quantize_image(options.liq, options.fixed_palette_image);
|
||
|
- const liq_palette *pal = liq_get_palette(tmp_quantize);
|
||
|
- if (!pal) {
|
||
|
- fprintf(stderr, " error: unable to read colors from %s", optarg);
|
||
|
- return INVALID_ARGUMENT;
|
||
|
- }
|
||
|
- for(unsigned int i=0; i < pal->count; i++) {
|
||
|
- liq_image_add_fixed_color(options.fixed_palette_image, pal->entries[i]);
|
||
|
- }
|
||
|
- liq_result_destroy(tmp_quantize);
|
||
|
- }
|
||
|
- break;
|
||
|
+ options->liq = liq_attr_create();
|
||
|
|
||
|
- case 'h':
|
||
|
- print_full_version(stdout);
|
||
|
- print_usage(stdout);
|
||
|
- return SUCCESS;
|
||
|
+ if (!options->liq) {
|
||
|
+ fputs("SSE-capable CPU is required for this build.\n", stderr);
|
||
|
+ return WRONG_ARCHITECTURE;
|
||
|
+ }
|
||
|
|
||
|
- case 'V':
|
||
|
- puts(PNGQUANT_VERSION);
|
||
|
- return SUCCESS;
|
||
|
+ if (options->verbose) {
|
||
|
+ liq_set_log_callback(options->liq, log_callback, NULL);
|
||
|
+ options->log_callback = log_callback;
|
||
|
+ }
|
||
|
|
||
|
- case -1: break;
|
||
|
+ if (options->quality && !parse_quality(options->quality, 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;
|
||
|
+ }
|
||
|
|
||
|
- default:
|
||
|
- return INVALID_ARGUMENT;
|
||
|
- }
|
||
|
- } while (opt != -1);
|
||
|
+ if (options->iebug) {
|
||
|
+ // opacities above 238 will be rounded up to 255, because IE6 truncates <255 to 0.
|
||
|
+ liq_set_min_opacity(options->liq, 238);
|
||
|
+ fputs(" warning: the workaround for IE6 is deprecated\n", stderr);
|
||
|
+ }
|
||
|
|
||
|
- int argn = optind;
|
||
|
+ if (options->last_index_transparent) {
|
||
|
+ liq_set_last_index_transparent(options->liq, true);
|
||
|
+ }
|
||
|
|
||
|
- if (argn >= argc) {
|
||
|
- if (argn > 1) {
|
||
|
- fputs("No input files specified.\n", stderr);
|
||
|
- } else {
|
||
|
- print_full_version(stderr);
|
||
|
+ if (options->speed >= 10) {
|
||
|
+ options->fast_compression = true;
|
||
|
+ if (options->speed == 11) {
|
||
|
+ options->floyd = 0;
|
||
|
+ options->speed = 10;
|
||
|
}
|
||
|
- print_usage(stderr);
|
||
|
- return MISSING_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
- if (options.verbose) {
|
||
|
- liq_set_log_callback(options.liq, log_callback, NULL);
|
||
|
- options.log_callback = log_callback;
|
||
|
+ if (options->speed && LIQ_OK != liq_set_speed(options->liq, options->speed)) {
|
||
|
+ fputs("Speed should be between 1 (slow) and 11 (fast).\n", stderr);
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
+ if (options->colors && LIQ_OK != liq_set_max_colors(options->liq, options->colors)) {
|
||
|
+ fputs("Number of colors must be between 2 and 256.\n", stderr);
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
- 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 (options->posterize && LIQ_OK != liq_set_min_posterization(options->liq, options->posterize)) {
|
||
|
+ fputs("Posterization should be number of bits in range 0-4.\n", stderr);
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
- if (newext && output_file_path) {
|
||
|
+ if (options->extension && options->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 (options->extension == NULL) {
|
||
|
+ options->extension = options->floyd > 0 ? "-fs8.png" : "-or8.png";
|
||
|
}
|
||
|
|
||
|
- 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) {
|
||
|
+ if (options->output_file_path && options->num_files != 1) {
|
||
|
fputs("Only one input file is allowed when --output is used\n", stderr);
|
||
|
return INVALID_ARGUMENT;
|
||
|
}
|
||
|
- if (options.using_stdout && !options.using_stdin && num_files != 1) {
|
||
|
+
|
||
|
+ if (options->using_stdout && !options->using_stdin && options->num_files != 1) {
|
||
|
fputs("Only one input file is allowed when using the special output path \"-\" to write to stdout\n", stderr);
|
||
|
return INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
+ if (options->map_file) {
|
||
|
+ png24_image tmp = {.width=0};
|
||
|
+ if (SUCCESS != read_image(options->liq, options->map_file, false, &tmp, &options->fixed_palette_image, true, true, false)) {
|
||
|
+ fprintf(stderr, " error: unable to load %s", options->map_file);
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
+ liq_result *tmp_quantize = liq_quantize_image(options->liq, options->fixed_palette_image);
|
||
|
+ const liq_palette *pal = liq_get_palette(tmp_quantize);
|
||
|
+ if (!pal) {
|
||
|
+ fprintf(stderr, " error: unable to read colors from %s", options->map_file);
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
+ for(unsigned int i=0; i < pal->count; i++) {
|
||
|
+ liq_image_add_fixed_color(options->fixed_palette_image, pal->entries[i]);
|
||
|
+ }
|
||
|
+ liq_result_destroy(tmp_quantize);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (!options->num_files && !options->using_stdin) {
|
||
|
+ fputs("No input files specified.\n", stderr);
|
||
|
+ if (options->verbose) {
|
||
|
+ print_full_version(stderr);
|
||
|
+ }
|
||
|
+ print_usage(stderr);
|
||
|
+ return MISSING_ARGUMENT;
|
||
|
+ }
|
||
|
+
|
||
|
#ifdef _OPENMP
|
||
|
// if there's a lot of files, coarse parallelism can be used
|
||
|
- if (num_files > 2*omp_get_max_threads()) {
|
||
|
+ if (options->num_files > 2*omp_get_max_threads()) {
|
||
|
omp_set_nested(0);
|
||
|
omp_set_dynamic(1);
|
||
|
} else {
|
||
|
@@ -493,17 +362,20 @@ int main(int argc, char *argv[])
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
+ unsigned int error_count=0, skipped_count=0, file_count=0;
|
||
|
+ pngquant_error latest_error=SUCCESS;
|
||
|
+
|
||
|
#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);
|
||
|
+ for(int i=0; i < options->num_files; i++) {
|
||
|
+ const char *filename = options->using_stdin ? "stdin" : options->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) {
|
||
|
+ struct buffered_log buf = {0};
|
||
|
+ if (opts.log_callback && omp_get_num_threads() > 1 && opts.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);
|
||
|
opts.log_callback = log_callback_buferred;
|
||
|
@@ -514,11 +386,11 @@ int main(int argc, char *argv[])
|
||
|
|
||
|
pngquant_error retval = SUCCESS;
|
||
|
|
||
|
- const char *outname = output_file_path;
|
||
|
+ const char *outname = opts.output_file_path;
|
||
|
char *outname_free = NULL;
|
||
|
if (!opts.using_stdout) {
|
||
|
if (!outname) {
|
||
|
- outname = outname_free = add_filename_extension(filename, newext);
|
||
|
+ outname = outname_free = add_filename_extension(filename, opts.extension);
|
||
|
}
|
||
|
if (!opts.force && file_exists(outname)) {
|
||
|
fprintf(stderr, " error: '%s' exists; not overwriting\n", outname);
|
||
|
@@ -549,20 +421,20 @@ int main(int argc, char *argv[])
|
||
|
}
|
||
|
|
||
|
if (error_count) {
|
||
|
- verbose_printf(&options, "There were errors quantizing %d file%s out of a total of %d file%s.",
|
||
|
+ 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.",
|
||
|
+ 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, "Quantized %d image%s.",
|
||
|
+ verbose_printf(options, "Quantized %d image%s.",
|
||
|
file_count, (file_count == 1)? "" : "s");
|
||
|
}
|
||
|
|
||
|
- if (options.fixed_palette_image) liq_image_destroy(options.fixed_palette_image);
|
||
|
- liq_attr_destroy(options.liq);
|
||
|
+ if (options->fixed_palette_image) liq_image_destroy(options->fixed_palette_image);
|
||
|
+ liq_attr_destroy(options->liq);
|
||
|
|
||
|
return latest_error;
|
||
|
}
|
||
|
@@ -574,14 +446,14 @@ pngquant_error pngquant_file(const char *filename, const char *outname, struct p
|
||
|
verbose_printf(options, "%s:", filename);
|
||
|
|
||
|
liq_image *input_image = NULL;
|
||
|
- png24_image input_image_rwpng = {};
|
||
|
+ png24_image input_image_rwpng = {.width=0};
|
||
|
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->strip, options->verbose);
|
||
|
}
|
||
|
|
||
|
int quality_percent = 90; // quality on 0-100 scale, updated upon successful remap
|
||
|
- png8_image output_image = {};
|
||
|
+ png8_image output_image = {.width=0};
|
||
|
if (SUCCESS == retval) {
|
||
|
verbose_printf(options, " read %luKB file", (input_image_rwpng.file_size+1023UL)/1024UL);
|
||
|
|
||
|
@@ -728,7 +600,7 @@ static char *temp_filename(const char *basename) {
|
||
|
|
||
|
static void set_binary_mode(FILE *fp)
|
||
|
{
|
||
|
-#if defined(WIN32) || defined(__WIN32__)
|
||
|
+#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
|
||
|
setmode(fp == stdout ? 1 : 0, O_BINARY);
|
||
|
#endif
|
||
|
}
|
||
|
@@ -744,7 +616,7 @@ static const char *filename_part(const char *path)
|
||
|
}
|
||
|
|
||
|
static bool replace_file(const char *from, const char *to, const bool force) {
|
||
|
-#if defined(WIN32) || defined(__WIN32__)
|
||
|
+#if defined(_WIN32) || defined(WIN32) || defined(__WIN32__)
|
||
|
if (force) {
|
||
|
// On Windows rename doesn't replace
|
||
|
unlink(to);
|
||
|
--- /dev/null
|
||
|
+++ b/pngquant_opts.c
|
||
|
@@ -0,0 +1,183 @@
|
||
|
+#include <stdio.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <string.h>
|
||
|
+#include <stdbool.h>
|
||
|
+#include <getopt.h>
|
||
|
+
|
||
|
+#include "rwpng.h"
|
||
|
+#include "libimagequant.h" /* if you get compile error, add -Ilib to compiler flags */
|
||
|
+#include "pngquant_opts.h"
|
||
|
+
|
||
|
+extern char *optarg;
|
||
|
+extern int optind, opterr;
|
||
|
+
|
||
|
+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, arg_strip};
|
||
|
+
|
||
|
+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},
|
||
|
+ {"strip", no_argument, NULL, arg_strip},
|
||
|
+ {"map", required_argument, NULL, arg_map},
|
||
|
+ {"version", no_argument, NULL, 'V'},
|
||
|
+ {"help", no_argument, NULL, 'h'},
|
||
|
+ {NULL, 0, NULL, 0},
|
||
|
+};
|
||
|
+
|
||
|
+pngquant_error pngquant_parse_options(int argc, char *argv[], struct pngquant_options *options)
|
||
|
+{
|
||
|
+ 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.f;
|
||
|
+ 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: options->extension = optarg; break;
|
||
|
+ case 'o':
|
||
|
+ if (options->output_file_path) {
|
||
|
+ fputs("--output option can be used only once\n", stderr);
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
+ if (strcmp(optarg, "-") == 0) {
|
||
|
+ options->using_stdout = true;
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ options->output_file_path = optarg; break;
|
||
|
+
|
||
|
+ case arg_iebug:
|
||
|
+ options->iebug = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case arg_transbug:
|
||
|
+ options->last_index_transparent = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case arg_skip_larger:
|
||
|
+ options->skip_if_larger = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case 's':
|
||
|
+ options->speed = atoi(optarg);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case 'Q':
|
||
|
+ options->quality = optarg;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case arg_posterize:
|
||
|
+ options->posterize = atoi(optarg);
|
||
|
+ break;
|
||
|
+
|
||
|
+ case arg_strip:
|
||
|
+ options->strip = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case arg_map:
|
||
|
+ options->map_file = optarg;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case 'h':
|
||
|
+ options->print_help = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case 'V':
|
||
|
+ options->print_version = true;
|
||
|
+ break;
|
||
|
+
|
||
|
+ case -1: break;
|
||
|
+
|
||
|
+ default:
|
||
|
+ return INVALID_ARGUMENT;
|
||
|
+ }
|
||
|
+ } while (opt != -1);
|
||
|
+
|
||
|
+ int argn = optind;
|
||
|
+
|
||
|
+ if (argn < argc) {
|
||
|
+ char *colors_end;
|
||
|
+ unsigned long colors = strtoul(argv[argn], &colors_end, 10);
|
||
|
+ if (colors_end != argv[argn] && '\0' == colors_end[0]) {
|
||
|
+ options->colors = colors;
|
||
|
+ argn++;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (argn == argc || (argn == argc-1 && 0==strcmp(argv[argn],"-"))) {
|
||
|
+ options->using_stdin = true;
|
||
|
+ options->using_stdout = !options->output_file_path;
|
||
|
+ argn = argc-1;
|
||
|
+ }
|
||
|
+
|
||
|
+ options->num_files = argc-argn;
|
||
|
+ options->files = argv+argn;
|
||
|
+ } else if (argn <= 1) {
|
||
|
+ options->missing_arguments = true;
|
||
|
+ }
|
||
|
+
|
||
|
+ return SUCCESS;
|
||
|
+}
|
||
|
--- /dev/null
|
||
|
+++ b/pngquant_opts.h
|
||
|
@@ -0,0 +1,24 @@
|
||
|
+
|
||
|
+struct pngquant_options {
|
||
|
+ liq_attr *liq;
|
||
|
+ liq_image *fixed_palette_image;
|
||
|
+ liq_log_callback_function *log_callback;
|
||
|
+ void *log_callback_user_info;
|
||
|
+ const char *quality;
|
||
|
+ const char *extension;
|
||
|
+ const char *output_file_path;
|
||
|
+ const char *map_file;
|
||
|
+ char *const *files;
|
||
|
+ unsigned int num_files;
|
||
|
+ unsigned int colors;
|
||
|
+ unsigned int speed;
|
||
|
+ unsigned int posterize;
|
||
|
+ float floyd;
|
||
|
+ bool using_stdin, using_stdout, force, fast_compression,
|
||
|
+ min_quality_limit, skip_if_larger,
|
||
|
+ strip, iebug, last_index_transparent,
|
||
|
+ print_help, print_version, missing_arguments,
|
||
|
+ verbose;
|
||
|
+};
|
||
|
+
|
||
|
+pngquant_error pngquant_parse_options(int argc, char *argv[], struct pngquant_options *options);
|
||
|
--- /dev/null
|
||
|
+++ b/rust/bin.rs
|
||
|
@@ -0,0 +1,127 @@
|
||
|
+#![cfg_attr(feature="alloc_system", feature(alloc_system))]
|
||
|
+
|
||
|
+#[cfg(feature="alloc_system")]
|
||
|
+extern crate alloc_system;
|
||
|
+extern crate imagequant_sys;
|
||
|
+extern crate libpng_sys;
|
||
|
+extern crate getopts;
|
||
|
+
|
||
|
+#[cfg(feature = "lcms2")]
|
||
|
+extern crate lcms2_sys;
|
||
|
+
|
||
|
+use std::os::raw::{c_uint, c_char};
|
||
|
+use std::io;
|
||
|
+use std::io::Write;
|
||
|
+use std::process;
|
||
|
+use std::env;
|
||
|
+use std::ptr;
|
||
|
+use std::ffi::CString;
|
||
|
+
|
||
|
+mod ffi;
|
||
|
+use ffi::*;
|
||
|
+
|
||
|
+fn unwrap_ptr(opt: Option<&CString>) -> *const c_char {
|
||
|
+ opt.map(|c| c.as_ptr()).unwrap_or(ptr::null())
|
||
|
+}
|
||
|
+
|
||
|
+fn main() {
|
||
|
+ let mut opts = getopts::Options::new();
|
||
|
+
|
||
|
+ opts.optflag("v", "verbose", "");
|
||
|
+ opts.optflag("h", "help", "");
|
||
|
+ opts.optflag("q", "quiet", "");
|
||
|
+ opts.optflag("f", "force", "");
|
||
|
+ opts.optflag("", "no-force", "");
|
||
|
+ opts.optflag("", "ordered", "");
|
||
|
+ opts.optflag("", "nofs", "");
|
||
|
+ opts.optflag("", "iebug", "");
|
||
|
+ opts.optflag("", "transbug", "");
|
||
|
+ opts.optflag("", "skip-if-larger", "");
|
||
|
+ opts.optflag("", "strip", "");
|
||
|
+ opts.optflag("V", "version", "");
|
||
|
+ opts.optflag("", "floyd", ""); // https://github.com/rust-lang-nursery/getopts/issues/49
|
||
|
+ opts.optflag("", "ext", "");
|
||
|
+ opts.optopt("o", "output", "file", "");
|
||
|
+ opts.optopt("s", "speed", "3", "");
|
||
|
+ opts.optopt("Q", "quality", "0-100", "");
|
||
|
+ opts.optopt("", "posterize", "0", "");
|
||
|
+ opts.optopt("", "map", "png", "");
|
||
|
+
|
||
|
+ let has_some_explicit_args = env::args().skip(1).next().is_some();
|
||
|
+ let mut m = match opts.parse(env::args().skip(1)) {
|
||
|
+ Ok(m) => m,
|
||
|
+ Err(err) => {
|
||
|
+ writeln!(&mut io::stderr(), "{}", err).ok();
|
||
|
+ process::exit(2);
|
||
|
+ },
|
||
|
+ };
|
||
|
+
|
||
|
+ let posterize = m.opt_str("posterize").and_then(|p| p.parse().ok()).unwrap_or(0);
|
||
|
+ let speed = m.opt_str("speed").and_then(|p| p.parse().ok()).unwrap_or(0);
|
||
|
+ let floyd = m.opt_str("floyd").and_then(|p| p.parse().ok()).unwrap_or(1.);
|
||
|
+
|
||
|
+ let quality = m.opt_str("quality").and_then(|s| CString::new(s).ok());
|
||
|
+ let extension = m.opt_str("ext").and_then(|s| CString::new(s).ok());
|
||
|
+ let map_file = m.opt_str("map").and_then(|s| CString::new(s).ok());
|
||
|
+
|
||
|
+ let colors = if let Some(c) = m.free.get(0).and_then(|s| s.parse().ok()) {
|
||
|
+ m.free.remove(0);
|
||
|
+ if m.free.len() == 0 {
|
||
|
+ m.free.push("-".to_owned()); // stdin default
|
||
|
+ }
|
||
|
+ c
|
||
|
+ } else {0};
|
||
|
+ let using_stdin = m.free.len() == 1 && Some("-") == m.free.get(0).map(|s| s.as_str());
|
||
|
+ let mut using_stdout = using_stdin;
|
||
|
+ let output_file_path = m.opt_str("o").and_then(|s| {
|
||
|
+ if s == "-" {
|
||
|
+ using_stdout = true;
|
||
|
+ None
|
||
|
+ } else {
|
||
|
+ using_stdout = false;
|
||
|
+ CString::new(s).ok()
|
||
|
+ }
|
||
|
+ });
|
||
|
+
|
||
|
+ let files: Vec<_> = m.free.drain(..).filter_map(|s| CString::new(s).ok()).collect();
|
||
|
+ let file_ptrs: Vec<_> = files.iter().map(|s| s.as_ptr()).collect();
|
||
|
+
|
||
|
+ let mut options = pngquant_options {
|
||
|
+ quality: unwrap_ptr(quality.as_ref()),
|
||
|
+ extension: unwrap_ptr(extension.as_ref()),
|
||
|
+ output_file_path: unwrap_ptr(output_file_path.as_ref()),
|
||
|
+ map_file: unwrap_ptr(map_file.as_ref()),
|
||
|
+ files: file_ptrs.as_ptr(),
|
||
|
+ num_files: file_ptrs.len() as c_uint,
|
||
|
+ using_stdin,
|
||
|
+ using_stdout,
|
||
|
+ missing_arguments: !has_some_explicit_args,
|
||
|
+ colors,
|
||
|
+ speed,
|
||
|
+ posterize,
|
||
|
+ floyd,
|
||
|
+ force: m.opt_present("force") && !m.opt_present("no-force"),
|
||
|
+ skip_if_larger: m.opt_present("skip-if-larger"),
|
||
|
+ strip: m.opt_present("strip"),
|
||
|
+ iebug: m.opt_present("iebug"),
|
||
|
+ last_index_transparent: m.opt_present("transbug"),
|
||
|
+ print_help: m.opt_present("h"),
|
||
|
+ print_version: m.opt_present("V"),
|
||
|
+ verbose: m.opt_present("v"),
|
||
|
+
|
||
|
+ liq: ptr::null_mut(),
|
||
|
+ fixed_palette_image: ptr::null_mut(),
|
||
|
+ log_callback: None,
|
||
|
+ log_callback_user_info: ptr::null_mut(),
|
||
|
+ fast_compression: false,
|
||
|
+ min_quality_limit: false,
|
||
|
+ };
|
||
|
+
|
||
|
+ if m.opt_present("nofs") || m.opt_present("ordered") {
|
||
|
+ options.floyd = 0.;
|
||
|
+ }
|
||
|
+
|
||
|
+ process::exit(unsafe {pngquant_main(&mut options)});
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
--- /dev/null
|
||
|
+++ b/rust/build.rs
|
||
|
@@ -0,0 +1,57 @@
|
||
|
+extern crate gcc;
|
||
|
+
|
||
|
+use std::env;
|
||
|
+
|
||
|
+fn fudge_windows_unc_path(path: &str) -> &str {
|
||
|
+ if path.starts_with("\\\\?\\") {
|
||
|
+ &path[4..]
|
||
|
+ } else {
|
||
|
+ path
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+fn main() {
|
||
|
+ let mut cc = gcc::Config::new();
|
||
|
+
|
||
|
+ cc.define("PNGQUANT_NO_MAIN", Some("1"));
|
||
|
+
|
||
|
+ if cfg!(feature = "cocoa") {
|
||
|
+ if cfg!(feature = "lcms2") {
|
||
|
+ println!("cargo:warning=Don't use both lcms2 and cocoa features at the same time, see --no-default-features");
|
||
|
+ }
|
||
|
+ println!("cargo:rustc-link-lib=framework=Cocoa");
|
||
|
+
|
||
|
+ cc.define("USE_COCOA", Some("1"));
|
||
|
+ cc.file("rwpng_cocoa.m");
|
||
|
+ }
|
||
|
+ else if cfg!(feature = "lcms2") {
|
||
|
+ if let Ok(p) = env::var("DEP_LCMS2_INCLUDE") {
|
||
|
+ cc.include(fudge_windows_unc_path(&p));
|
||
|
+ }
|
||
|
+ cc.define("USE_LCMS", Some("1"));
|
||
|
+ }
|
||
|
+
|
||
|
+ if env::var("PROFILE").map(|p|p != "debug").unwrap_or(true) {
|
||
|
+ cc.define("NDEBUG", Some("1"));
|
||
|
+ }
|
||
|
+
|
||
|
+ if cfg!(target_arch="x86_64") ||
|
||
|
+ (cfg!(target_arch="x86") && cfg!(feature = "sse")) {
|
||
|
+ cc.define("USE_SSE", Some("1"));
|
||
|
+ }
|
||
|
+
|
||
|
+ cc.file("rwpng.c");
|
||
|
+ cc.file("pngquant.c");
|
||
|
+
|
||
|
+ if let Ok(p) = env::var("DEP_IMAGEQUANT_INCLUDE") {
|
||
|
+ cc.include(fudge_windows_unc_path(&p));
|
||
|
+ } else {
|
||
|
+ cc.include("lib");
|
||
|
+ }
|
||
|
+
|
||
|
+ if let Ok(p) = env::var("DEP_LIBPNG_INCLUDE") {
|
||
|
+ cc.include(fudge_windows_unc_path(&p));
|
||
|
+ }
|
||
|
+
|
||
|
+ cc.compile("libpngquant.a");
|
||
|
+}
|
||
|
--- /dev/null
|
||
|
+++ b/rust/ffi.rs
|
||
|
@@ -0,0 +1,39 @@
|
||
|
+#![allow(non_camel_case_types)]
|
||
|
+
|
||
|
+use std::os::raw::*;
|
||
|
+use imagequant_sys::*;
|
||
|
+
|
||
|
+extern "C" {
|
||
|
+ pub fn pngquant_main(options: &mut pngquant_options) -> c_int;
|
||
|
+}
|
||
|
+
|
||
|
+#[repr(C)]
|
||
|
+pub struct pngquant_options {
|
||
|
+ pub liq: *mut liq_attr,
|
||
|
+ pub fixed_palette_image: *mut liq_image,
|
||
|
+ pub log_callback: liq_log_callback_function,
|
||
|
+ pub log_callback_user_info: *mut c_void,
|
||
|
+ pub quality: *const c_char,
|
||
|
+ pub extension: *const c_char,
|
||
|
+ pub output_file_path: *const c_char,
|
||
|
+ pub map_file: *const c_char,
|
||
|
+ pub files: *const *const c_char,
|
||
|
+ pub num_files: c_uint,
|
||
|
+ pub colors: c_uint,
|
||
|
+ pub speed: c_uint,
|
||
|
+ pub posterize: c_uint,
|
||
|
+ pub floyd: f32,
|
||
|
+ pub using_stdin: bool,
|
||
|
+ pub using_stdout: bool,
|
||
|
+ pub force: bool,
|
||
|
+ pub fast_compression: bool,
|
||
|
+ pub min_quality_limit: bool,
|
||
|
+ pub skip_if_larger: bool,
|
||
|
+ pub strip: bool,
|
||
|
+ pub iebug: bool,
|
||
|
+ pub last_index_transparent: bool,
|
||
|
+ pub print_help: bool,
|
||
|
+ pub print_version: bool,
|
||
|
+ pub missing_arguments: bool,
|
||
|
+ pub verbose: bool,
|
||
|
+}
|
||
|
diff --git a/rwpng_cocoa.m b/rwpng_cocoa.m
|
||
|
index d1a5f24..4ea2d95 100644
|
||
|
--- a/rwpng_cocoa.m
|
||
|
+++ b/rwpng_cocoa.m
|
||
|
@@ -10,8 +10,10 @@
|
||
|
#import <Cocoa/Cocoa.h>
|
||
|
#import <CoreGraphics/CoreGraphics.h>
|
||
|
#include <stdio.h>
|
||
|
-#include "lib/libimagequant.h"
|
||
|
-#include "lib/pam.h"
|
||
|
+#include "libimagequant.h"
|
||
|
+typedef struct {
|
||
|
+ unsigned char r, g, b, a;
|
||
|
+} rgba_pixel;
|
||
|
|
||
|
int rwpng_read_image24_cocoa(FILE *fp, png24_image *out)
|
||
|
{
|
||
|
diff --git a/test/test.c b/test/test.c
|
||
|
index fabe0c7..6022629 100644
|
||
|
--- a/test/test.c
|
||
|
+++ b/test/test.c
|
||
|
@@ -1,6 +1,6 @@
|
||
|
#undef NDEBUG
|
||
|
#include <assert.h>
|
||
|
-#include "../lib/libimagequant.h"
|
||
|
+#include "libimagequant.h"
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|