Hello community, here is the log from the commit of package libimagequant for openSUSE:Factory checked in at 2019-03-22 14:54:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/libimagequant (Old) and /work/SRC/openSUSE:Factory/.libimagequant.new.25356 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libimagequant" Fri Mar 22 14:54:14 2019 rev:3 rq:686988 version:2.12.2 Changes: -------- --- /work/SRC/openSUSE:Factory/libimagequant/libimagequant.changes 2019-02-24 20:46:23.487886899 +0100 +++ /work/SRC/openSUSE:Factory/.libimagequant.new.25356/libimagequant.changes 2019-03-22 14:54:18.094062869 +0100 @@ -1,0 +2,7 @@ +Fri Feb 15 07:37:14 UTC 2019 - mun...@googlemail.com + +- update to version 2.12.2 + * new liq_histogram_add_fixed_color() + * faster for large/complex images + +------------------------------------------------------------------- Old: ---- libimagequant-2.11.3.tar.gz New: ---- libimagequant-2.12.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libimagequant.spec ++++++ --- /var/tmp/diff_new_pack.UQaNhr/_old 2019-03-22 14:54:18.950062351 +0100 +++ /var/tmp/diff_new_pack.UQaNhr/_new 2019-03-22 14:54:18.950062351 +0100 @@ -12,20 +12,22 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# Please submit bugfixes or comments via http://bugs.opensuse.org/ # %define sover 0 %define libname %{name}%{sover} Name: libimagequant -Version: 2.11.3 +Version: 2.12.2 Release: 0 Summary: Palette quantization library License: GPL-3.0-or-later Group: Development/Languages/C and C++ -URL: https://github.com/ImageOptim/libimagequant +Url: https://pngquant.org/lib/ Source: https://github.com/ImageOptim/libimagequant/archive/%{version}/%{name}-%{version}.tar.gz +BuildRequires: pkgconfig +BuildRequires: pkgconfig(lcms2) %description C library for conversion of RGBA images to 8-bit indexed-color @@ -53,14 +55,14 @@ %build # This is not an autoconf configure, but the script simply ignores parameters it does not know -%configure -make %{?_smp_mflags} shared +%configure --with-openmp +make %{?_smp_mflags} %install -# Manual installation, the Makefile has no install target -install -Dpm 0755 %{name}.so.0 %{buildroot}%{_libdir}/%{name}.so.0 -ln -s %{name}.so.0 %{buildroot}%{_libdir}/%{name}.so -install -Dpm 0644 %{name}.h %{buildroot}%{_includedir}/%{name}.h +%make_install + +# work around --disable-static not working +find %{buildroot} \( -name '*.a' -o -name '*.la' \) -print -delete %post -n libimagequant0 -p /sbin/ldconfig %postun -n libimagequant0 -p /sbin/ldconfig @@ -73,5 +75,6 @@ %files devel %{_libdir}/%{name}.so %{_includedir}/%{name}.h +%{_libdir}/pkgconfig/imagequant.pc %changelog ++++++ libimagequant-2.11.3.tar.gz -> libimagequant-2.12.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/.gitignore new/libimagequant-2.12.2/.gitignore --- old/libimagequant-2.11.3/.gitignore 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/.gitignore 2018-10-28 22:39:27.000000000 +0100 @@ -1,8 +1,10 @@ config.mk +imagequant.pc *.lo *.o *.a *.so.0 +*.so *.bz2 *.dylib *.dylib.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/.travis.yml new/libimagequant-2.12.2/.travis.yml --- old/libimagequant-2.11.3/.travis.yml 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/.travis.yml 2018-10-28 22:39:27.000000000 +0100 @@ -1,5 +1,17 @@ -language: rust -script: - - cargo build --verbose --all - - cargo test --verbose --all - +matrix: + include: + - os: linux + language: java + jdk: oraclejdk8 + env: CFLAGS="-fPIC" + install: true + script: make java + - os: linux + language: rust + script: cargo build --verbose --all && cargo test --verbose --all + - os: linux + language: generic + script: make static + - os: linux + language: generic + script: ./configure --prefix=/tmp && make libimagequant.so && make install diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/CHANGELOG new/libimagequant-2.12.2/CHANGELOG --- old/libimagequant-2.11.3/CHANGELOG 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/CHANGELOG 2018-10-28 22:39:27.000000000 +0100 @@ -1,3 +1,9 @@ +version 2.12 +------------ + - new liq_histogram_add_fixed_color() + - faster for large/complex images + - workarounds for Microsoft's outdated C compiler + version 2.11 ------------ - new liq_image_set_background() for high-quality remapping of GIF frames @@ -7,7 +13,6 @@ version 2.10 ----------- - supports building with Rust/Cargo - - new liq_histogram_add_fixed_color() version 2.9 ----------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/COPYRIGHT new/libimagequant-2.12.2/COPYRIGHT --- old/libimagequant-2.11.3/COPYRIGHT 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/COPYRIGHT 2018-10-28 22:39:27.000000000 +0100 @@ -6,7 +6,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -libimagequant © 2009-2017 by Kornel Lesiński. +libimagequant © 2009-2018 by Kornel Lesiński. GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/Cargo.toml new/libimagequant-2.12.2/Cargo.toml --- old/libimagequant-2.11.3/Cargo.toml 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/Cargo.toml 2018-10-28 22:39:27.000000000 +0100 @@ -12,18 +12,18 @@ name = "imagequant-sys" readme = "README.md" repository = "https://github.com/ImageOptim/libimagequant" -version = "2.11.3" +version = "2.12.2" description = "Statically linked C part of imagequant library powering tools such as pngquant.\n\nThis library is dual-licensed like pngquant: either GPL or a commercial license. See website for details: https://pngquant.org" [build-dependencies] -cc = "1.0.3" +cc = "1.0.17" [dependencies] -rgb = "0.8" +rgb = "0.8.9" [dependencies.openmp-sys] optional = true -version = "0.1.1" +version = "0.1.5" [features] default = ["sse"] @@ -32,7 +32,7 @@ sse = [] [lib] -crate-type = ["cdylib", "rlib", "staticlib"] +crate-type = ["cdylib", "staticlib", "lib"] name = "imagequant_sys" path = "rust/libimagequant.rs" doctest = false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/Makefile new/libimagequant-2.12.2/Makefile --- old/libimagequant-2.11.3/Makefile 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/Makefile 2018-10-28 22:39:27.000000000 +0100 @@ -3,6 +3,13 @@ STATICLIB=libimagequant.a SHAREDLIB=libimagequant.$(SOLIBSUFFIX) SOVER=0 +ifeq ($(SOLIBSUFFIX),dylib) + SHAREDLIBVER=libimagequant.$(SOVER).$(SOLIBSUFFIX) + FIX_INSTALL_NAME=install_name_tool -id $(LIBDIR)/$(SHAREDLIBVER) $(DESTDIR)$(LIBDIR)/$(SHAREDLIBVER) +else + SHAREDLIBVER=libimagequant.$(SOLIBSUFFIX).$(SOVER) + FIX_INSTALL_NAME= +endif JNILIB=libimagequant.jnilib DLL=imagequant.dll @@ -19,23 +26,24 @@ JAVAHEADERS = $(JAVACLASSES:.class=.h) JAVAINCLUDE = -I'$(JAVA_HOME)/include' -I'$(JAVA_HOME)/include/linux' -I'$(JAVA_HOME)/include/win32' -I'$(JAVA_HOME)/include/darwin' -DISTFILES = $(OBJS:.o=.c) *.h README.md CHANGELOG COPYRIGHT Makefile configure +DISTFILES = $(OBJS:.o=.c) *.h README.md CHANGELOG COPYRIGHT Makefile configure imagequant.pc.in TARNAME = libimagequant-$(VERSION) TARFILE = $(TARNAME)-src.tar.bz2 +PKGCONFIG = imagequant.pc -all: static +all: static shared static: $(STATICLIB) shared: $(SHAREDLIB) dll: - $(MAKE) CFLAGSADD="-DIMAGEQUANT_EXPORTS" $(DLL) + $(MAKE) CFLAGS="$(CFLAGS) -DIMAGEQUANT_EXPORTS" $(DLL) java: $(JNILIB) java-dll: - $(MAKE) CFLAGSADD="-DIMAGEQUANT_EXPORTS" $(JNIDLL) + $(MAKE) CFLAGS="$(CFLAGS) -DIMAGEQUANT_EXPORTS" $(JNIDLL) $(DLL) $(DLLIMP): $(OBJS) $(CC) -fPIC -shared -o $(DLL) $^ $(LDFLAGS) -Wl,--out-implib,$(DLLIMP),--output-def,$(DLLDEF) @@ -47,12 +55,12 @@ $(CC) -fPIC $(CFLAGS) -c $(@:.lo=.c) -o $@ libimagequant.so: $(SHAREDOBJS) - $(CC) -shared -Wl,-soname,$(SHAREDLIB).$(SOVER) -o $(SHAREDLIB).$(SOVER) $^ $(LDFLAGS) - ln -fs $(SHAREDLIB).$(SOVER) $(SHAREDLIB) + $(CC) -shared -Wl,-soname,$(SHAREDLIBVER) -o $(SHAREDLIBVER) $^ $(LDFLAGS) + ln -fs $(SHAREDLIBVER) $(SHAREDLIB) libimagequant.dylib: $(SHAREDOBJS) - $(CC) -shared -o $(SHAREDLIB).$(SOVER) $^ $(LDFLAGS) - ln -fs $(SHAREDLIB).$(SOVER) $(SHAREDLIB) + $(CC) -shared -o $(SHAREDLIBVER) $^ $(LDFLAGS) + ln -fs $(SHAREDLIBVER) $(SHAREDLIB) $(OBJS): $(wildcard *.h) config.mk @@ -94,16 +102,38 @@ curl -o lodepng.c -L https://raw.githubusercontent.com/lvandeve/lodepng/master/lodepng.cpp clean: - rm -f $(OBJS) $(SHAREDOBJS) $(SHAREDLIB).$(SOVER) $(SHAREDLIB) $(STATICLIB) $(TARFILE) $(DLL) '$(DLLIMP)' '$(DLLDEF)' + rm -f $(OBJS) $(SHAREDOBJS) $(SHAREDLIBVER) $(SHAREDLIB) $(STATICLIB) $(TARFILE) $(DLL) '$(DLLIMP)' '$(DLLDEF)' rm -f $(JAVAHEADERS) $(JAVACLASSES) $(JNILIB) example distclean: clean rm -f config.mk + rm -f imagequant.pc + +install: all $(PKGCONFIG) + install -d $(DESTDIR)$(LIBDIR) + install -d $(DESTDIR)$(PKGCONFIGDIR) + install -d $(DESTDIR)$(INCLUDEDIR) + install -m 644 $(STATICLIB) $(DESTDIR)$(LIBDIR)/$(STATICLIB) + install -m 644 $(SHAREDLIBVER) $(DESTDIR)$(LIBDIR)/$(SHAREDLIBVER) + ln -sf $(SHAREDLIBVER) $(DESTDIR)$(LIBDIR)/$(SHAREDLIB) + install -m 644 $(PKGCONFIG) $(DESTDIR)$(PKGCONFIGDIR)/$(PKGCONFIG) + install -m 644 libimagequant.h $(DESTDIR)$(INCLUDEDIR)/libimagequant.h + $(FIX_INSTALL_NAME) + +uninstall: + rm -f $(DESTDIR)$(LIBDIR)/$(STATICLIB) + rm -f $(DESTDIR)$(LIBDIR)/$(SHAREDLIBVER) + rm -f $(DESTDIR)$(LIBDIR)/$(SHAREDLIB) + rm -f $(DESTDIR)$(PKGCONFIGDIR)/$(PKGCONFIG) + rm -f $(DESTDIR)$(INCLUDEDIR)/libimagequant.h config.mk: ifeq ($(filter %clean %distclean, $(MAKECMDGOALS)), ) ./configure endif +$(PKGCONFIG): config.mk + sed 's|PREFIX|$(PREFIX)|;s|VERSION|$(VERSION)|' < imagequant.pc.in > $(PKGCONFIG) + .PHONY: all static shared clean dist distclean dll java cargo .DELETE_ON_ERROR: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/README.md new/libimagequant-2.12.2/README.md --- old/libimagequant-2.11.3/README.md 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/README.md 2018-10-28 22:39:27.000000000 +0100 @@ -17,7 +17,7 @@ ## Compiling and Linking -The library can be linked with ANSI C, C++, [C#](https://github.com/ImageOptim/libimagequant/blob/master/libimagequant.cs), [Rust](https://github.com/pornel/libimagequant-rust), [Java](https://github.com/ImageOptim/libimagequant/tree/master/org/pngquant) and [Go](https://code.ivysaur.me/go-imagequant/) programs. It has no external dependencies. +The library can be linked with ANSI C, C++, [C#](https://github.com/ImageOptim/libimagequant/blob/master/libimagequant.cs), [Rust](https://github.com/pornel/libimagequant-rust), [Java](https://github.com/ImageOptim/libimagequant/tree/master/org/pngquant) and [Golang](https://github.com/larrabee/go-imagequant) programs. It has no external dependencies. To build on Unix-like systems run: @@ -55,6 +55,19 @@ * Use Visual Studio **2015** and an [MSVC-compatible branch of the library](https://github.com/ImageOptim/libimagequant/tree/msvc) * Or use GCC from [MinGW](http://www.mingw.org) or [MSYS2](http://www.msys2.org/). Use GCC to build `libimagequant.a` (using the instructions above for Unix) and add it along with `libgcc.a` (shipped with the MinGW compiler) to your VC project. +### Building as shared library + +To build on Unix-like systems run: + + ./configure --prefix=/usr + make libimagequant.so + +To install on Unix-like systems run: + + make install + + + ## Overview The basic flow is: @@ -177,7 +190,7 @@ `width` and `height` are dimensions in pixels. An image 10x10 pixel large will need a 400-byte array. -`gamma` can be `0` for images with the typical 1/2.2 [gamma](https://en.wikipedia.org/wiki/Gamma_correction). +If the `gamma` argument is `0`, then the default of 1/2.2 [gamma](https://en.wikipedia.org/wiki/Gamma_correction) is assumed, which is good for most sRGB images. Otherwise `gamma` must be > 0 and < 1, e.g. `0.45455` (1/2.2) or `0.55555` (1/1.8). Generated palette will use the same gamma unless `liq_set_output_gamma()` is used. If `liq_set_output_gamma` is not used, then it only affects whether brighter or darker areas of the image will get more palette colors allocated. Returns `NULL` on failure, e.g. if `pixels` is `NULL` or `width`/`height` is <= 0. @@ -558,16 +571,18 @@ --- liq_error liq_image_add_fixed_color(liq_image* img, liq_color color); - liq_error liq_histogram_add_fixed_color(liq_histogram *hist, liq_color color); + liq_error liq_histogram_add_fixed_color(liq_histogram* hist, liq_color color, double gamma); Reserves a color in the output palette created from this image. It behaves as if the given color was used in the image and was very important. -RGB values of `liq_color` are assumed to have the same gamma as the image. +RGB values of `liq_color` are assumed to have the same gamma as the image. For the histogram function, the `gamma` can be `0` (see `liq_image_create_rgba()`). It must be called before the image is quantized. Returns error if more than 256 colors are added. If image is quantized to fewer colors than the number of fixed colors added, then excess fixed colors will be ignored. +For histograms see also a more flexible `liq_histogram_add_colors()`. + --- int liq_version(); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/configure new/libimagequant-2.12.2/configure --- old/libimagequant-2.11.3/configure 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/configure 2018-10-28 22:39:27.000000000 +0100 @@ -2,6 +2,9 @@ CONFIG="config.mk" PREFIX="/usr/local" +LIBDIR="$PREFIX/lib" +INCLUDEDIR="$PREFIX/include" +PKGCONFIGDIR="$LIBDIR/pkgconfig" VERSION=$(grep LIQ_VERSION_STRING libimagequant.h | grep -Eo "2\.[0-9.]+") DEBUG= @@ -23,6 +26,9 @@ --help|-h) echo help "--prefix=<dir> installation directory [$PREFIX]" + help "--libdir=<dir> installation directory [$LIBDIR]" + help "--includedir=<dir> installation directory [$INCLUDEDIR]" + help "--pkgconfigdir=<dir> installation directory [$PKGCONFIGDIR]" help "--extra-cflags=<flags> append to CFLAGS" help "--extra-ldflags=<flags> append to LDFLAGS" echo @@ -70,6 +76,19 @@ ;; --prefix=*) PREFIX=${i#*=} + LIBDIR="$PREFIX/lib" + INCLUDEDIR="$PREFIX/include" + PKGCONFIGDIR="$LIBDIR/pkgconfig" + ;; + --libdir=*) + LIBDIR=${i#*=} + PKGCONFIGDIR="$LIBDIR/pkgconfig" + ;; + --includedir=*) + INCLUDEDIR=${i#*=} + ;; + --pkgconfigdir=*) + PKGCONFIGDIR=${i#*=} ;; # can be used multiple times or in quotes to set multiple flags --extra-cflags=*) @@ -123,10 +142,12 @@ echo fi -# /tmp, because mingw has problems opening /dev/null and gives false negative -if ! echo "int main(){}" | "$CC" -xc -std=c99 -o /tmp/gcccheck - > /dev/null; then +echo > pngquant-gcccheck.c "int main(){}" +if ! "$CC" -std=c99 -o pngquant-gcccheck pngquant-gcccheck.c; then + rm -f pngquant-gcccheck pngquant-gcccheck.c error "Compiler" "$CC failed to compile anything (make sure it's installed and supports C99)" fi +rm -f pngquant-gcccheck pngquant-gcccheck.c status "Compiler" "$CC" @@ -192,8 +213,8 @@ # Cocoa if [[ "$OSTYPE" =~ "darwin" ]]; then - cflags "-mmacosx-version-min=10.6" - lflags "-mmacosx-version-min=10.6" + cflags "-mmacosx-version-min=10.7" + lflags "-mmacosx-version-min=10.7" fi if [[ "$OSTYPE" =~ "darwin" ]]; then @@ -244,6 +265,9 @@ echo " # auto-generated by configure PREFIX = $PREFIX +LIBDIR = $LIBDIR +INCLUDEDIR = $INCLUDEDIR +PKGCONFIGDIR = $PKGCONFIGDIR VERSION = $VERSION CC = $CC CFLAGS = $CFLAGS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/example.c new/libimagequant-2.12.2/example.c --- old/libimagequant-2.11.3/example.c 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/example.c 2018-10-28 22:39:27.000000000 +0100 @@ -81,8 +81,8 @@ state.info_png.color.bitdepth = 8; for(int i=0; i < palette->count; i++) { - lodepng_palette_add(&state.info_png.color, palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, palette->entries[i].a); - lodepng_palette_add(&state.info_raw, palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, palette->entries[i].a); + lodepng_palette_add(&state.info_png.color, palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, palette->entries[i].a); + lodepng_palette_add(&state.info_raw, palette->entries[i].r, palette->entries[i].g, palette->entries[i].b, palette->entries[i].a); } unsigned char *output_file_data; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/imagequant.pc.in new/libimagequant-2.12.2/imagequant.pc.in --- old/libimagequant-2.11.3/imagequant.pc.in 1970-01-01 01:00:00.000000000 +0100 +++ new/libimagequant-2.12.2/imagequant.pc.in 2018-10-28 22:39:27.000000000 +0100 @@ -0,0 +1,10 @@ +prefix=PREFIX +includedir=${prefix}/include +libdir=${prefix}/lib + +Name: imagequant +Description: Small, portable C library for high-quality conversion of RGBA images to 8-bit indexed-color (palette) images. +URL: https://pngquant.org/lib/ +Version: VERSION +Libs: -L${libdir} -limagequant +Cflags: -I${includedir} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/kmeans.c new/libimagequant-2.12.2/kmeans.c --- old/libimagequant-2.11.3/kmeans.c 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/kmeans.c 2018-10-28 22:39:27.000000000 +0100 @@ -66,7 +66,7 @@ LIQ_PRIVATE double kmeans_do_iteration(histogram *hist, colormap *const map, kmeans_callback callback) { const unsigned int max_threads = omp_get_max_threads(); - kmeans_state average_color[(KMEANS_CACHE_LINE_GAP+map->colors) * max_threads]; + LIQ_ARRAY(kmeans_state, average_color, (KMEANS_CACHE_LINE_GAP+map->colors) * max_threads); kmeans_init(map, max_threads, average_color); struct nearest_map *const n = nearest_init(map); hist_item *const achv = hist->achv; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/libimagequant.c new/libimagequant-2.12.2/libimagequant.c --- old/libimagequant-2.11.3/libimagequant.c 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/libimagequant.c 2018-10-28 22:39:27.000000000 +0100 @@ -1,5 +1,5 @@ /* -** © 2009-2017 by Kornel Lesiński. +** © 2009-2018 by Kornel Lesiński. ** © 1989, 1991 by Jef Poskanzer. ** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider. ** @@ -21,7 +21,9 @@ #ifdef _OPENMP #include <omp.h> +#define LIQ_TEMP_ROW_WIDTH(img_width) (((img_width) | 15) + 1) /* keep alignment & leave space between rows to avoid cache line contention */ #else +#define LIQ_TEMP_ROW_WIDTH(img_width) (img_width) #define omp_get_max_threads() 1 #define omp_get_thread_num() 0 #endif @@ -56,7 +58,8 @@ unsigned int max_colors, max_histogram_entries; unsigned int min_posterization_output /* user setting */, min_posterization_input /* speed setting */; unsigned int kmeans_iterations, feedback_loop_trials; - bool last_index_transparent, use_contrast_maps, use_dither_map; + bool last_index_transparent, use_contrast_maps; + unsigned char use_dither_map; unsigned char speed; unsigned char progress_stage1, progress_stage2, progress_stage3; @@ -103,7 +106,8 @@ liq_palette int_palette; double gamma, palette_error; float dither_level; - bool use_dither_map; unsigned char progress_stage1; + unsigned char use_dither_map; + unsigned char progress_stage1; } liq_remapping_result; struct liq_result { @@ -120,7 +124,7 @@ float dither_level; double gamma, palette_error; int min_posterization_output; - bool use_dither_map; + unsigned char use_dither_map; }; struct liq_histogram { @@ -140,6 +144,7 @@ static void contrast_maps(liq_image *image) LIQ_NONNULL; static liq_error finalize_histogram(liq_histogram *input_hist, liq_attr *options, histogram **hist_output) LIQ_NONNULL; static const rgba_pixel *liq_image_get_row_rgba(liq_image *input_image, unsigned int row) LIQ_NONNULL; +static bool liq_image_get_row_f_init(liq_image *img) LIQ_NONNULL; static const f_pixel *liq_image_get_row_f(liq_image *input_image, unsigned int row) LIQ_NONNULL; static void liq_remapping_result_destroy(liq_remapping_result *result) LIQ_NONNULL; static liq_error pngquant_quantize(histogram *hist, const liq_attr *options, const int fixed_colors_count, const f_pixel fixed_colors[], const double gamma, bool fixed_result_colors, liq_result **) LIQ_NONNULL; @@ -153,7 +158,7 @@ int required_space = vsnprintf(NULL, 0, fmt, va)+1; // +\0 va_end(va); - char buf[required_space]; + LIQ_ARRAY(char, buf, required_space); va_start(va, fmt); vsnprintf(buf, required_space, fmt, va); va_end(va); @@ -189,8 +194,13 @@ #if USE_SSE inline static bool is_sse_available() { -#if (defined(__x86_64__) || defined(__amd64)) +#if (defined(__x86_64__) || defined(__amd64) || defined(_WIN64)) return true; +#elif _MSC_VER + int info[4]; + __cpuid(info, 1); + /* bool is implemented as a built-in type of size 1 in MSVC */ + return info[3] & (1<<26) ? true : false; #else int a,b,c,d; cpuid(1, a, b, c, d); @@ -327,7 +337,8 @@ if (!CHECK_STRUCT_TYPE(attr, liq_attr)) return LIQ_INVALID_POINTER; if (speed < 1 || speed > 10) return LIQ_VALUE_OUT_OF_RANGE; - unsigned int iterations = MAX(8-speed, 0); iterations += iterations * iterations/2; + unsigned int iterations = MAX(8-speed, 0); + iterations += iterations * iterations/2; attr->kmeans_iterations = iterations; attr->kmeans_iteration_limit = 1.0/(double)(1<<(23-speed)); attr->feedback_loop_trials = MAX(56-9*speed, 0); @@ -335,11 +346,16 @@ attr->max_histogram_entries = (1<<17) + (1<<18)*(10-speed); attr->min_posterization_input = (speed >= 8) ? 1 : 0; attr->use_dither_map = (speed <= (omp_get_max_threads() > 1 ? 7 : 5)); // parallelized dither map might speed up floyd remapping + if (attr->use_dither_map && speed < 3) { + attr->use_dither_map = 2; // always + } attr->use_contrast_maps = (speed <= 7) || attr->use_dither_map; attr->speed = speed; attr->progress_stage1 = attr->use_contrast_maps ? 20 : 8; - if (attr->feedback_loop_trials < 2) attr->progress_stage1 += 30; + if (attr->feedback_loop_trials < 2) { + attr->progress_stage1 += 30; + } attr->progress_stage3 = 50 / (1+speed); attr->progress_stage2 = 100 - attr->progress_stage1 - attr->progress_stage3; return LIQ_OK; @@ -499,7 +515,7 @@ .target_mse = 0, .max_mse = MAX_DIFF, }; - liq_set_speed(attr, 3); + liq_set_speed(attr, 4); return attr; } @@ -519,7 +535,7 @@ return LIQ_OK; } -LIQ_NONNULL liq_error liq_histogram_add_fixed_color(liq_histogram *hist, f_pixel color) +LIQ_NONNULL static liq_error liq_histogram_add_fixed_color_f(liq_histogram *hist, f_pixel color) { if (hist->fixed_colors_count > 255) return LIQ_UNSUPPORTED; @@ -527,9 +543,24 @@ return LIQ_OK; } +LIQ_EXPORT LIQ_NONNULL liq_error liq_histogram_add_fixed_color(liq_histogram *hist, liq_color color, double gamma) +{ + if (!CHECK_STRUCT_TYPE(hist, liq_histogram)) return LIQ_INVALID_POINTER; + + float gamma_lut[256]; + to_f_set_gamma(gamma_lut, gamma ? gamma : 0.45455); + const f_pixel px = rgba_to_f(gamma_lut, (rgba_pixel){ + .r = color.r, + .g = color.g, + .b = color.b, + .a = color.a, + }); + return liq_histogram_add_fixed_color_f(hist, px); +} + LIQ_NONNULL static bool liq_image_use_low_memory(liq_image *img) { - img->temp_f_row = img->malloc(sizeof(img->f_pixels[0]) * img->width * omp_get_max_threads()); + img->temp_f_row = img->malloc(sizeof(img->f_pixels[0]) * LIQ_TEMP_ROW_WIDTH(img->width) * omp_get_max_threads()); return img->temp_f_row != NULL; } @@ -565,7 +596,7 @@ }; if (!rows || attr->min_opaque_val < 1.f) { - img->temp_row = attr->malloc(sizeof(img->temp_row[0]) * width * omp_get_max_threads()); + img->temp_row = attr->malloc(sizeof(img->temp_row[0]) * LIQ_TEMP_ROW_WIDTH(width) * omp_get_max_threads()); if (!img->temp_row) return NULL; } @@ -760,7 +791,7 @@ } assert(img->temp_row); - rgba_pixel *temp_row = img->temp_row + img->width * omp_get_thread_num(); + rgba_pixel *temp_row = img->temp_row + LIQ_TEMP_ROW_WIDTH(img->width) * omp_get_thread_num(); if (img->rows) { memcpy(temp_row, img->rows[row], img->width * sizeof(temp_row[0])); } else { @@ -783,31 +814,40 @@ } } -LIQ_NONNULL static const f_pixel *liq_image_get_row_f(liq_image *img, unsigned int row) +LIQ_NONNULL static bool liq_image_get_row_f_init(liq_image *img) { + assert(omp_get_thread_num() == 0); + if (img->f_pixels) { + return true; + } + if (!liq_image_should_use_low_memory(img, false)) { + img->f_pixels = img->malloc(sizeof(img->f_pixels[0]) * img->width * img->height); + } if (!img->f_pixels) { - if (img->temp_f_row) { - float gamma_lut[256]; - to_f_set_gamma(gamma_lut, img->gamma); - f_pixel *row_for_thread = img->temp_f_row + img->width * omp_get_thread_num(); - convert_row_to_f(img, row_for_thread, row, gamma_lut); - return row_for_thread; - } + return liq_image_use_low_memory(img); + } - assert(omp_get_thread_num() == 0); - if (!liq_image_should_use_low_memory(img, false)) { - img->f_pixels = img->malloc(sizeof(img->f_pixels[0]) * img->width * img->height); - } - if (!img->f_pixels) { - if (!liq_image_use_low_memory(img)) return NULL; - return liq_image_get_row_f(img, row); - } + if (!liq_image_has_rgba_pixels(img)) { + return false; + } + + float gamma_lut[256]; + to_f_set_gamma(gamma_lut, img->gamma); + for(unsigned int i=0; i < img->height; i++) { + convert_row_to_f(img, &img->f_pixels[i*img->width], i, gamma_lut); + } + return true; +} +LIQ_NONNULL static const f_pixel *liq_image_get_row_f(liq_image *img, unsigned int row) +{ + if (!img->f_pixels) { + assert(img->temp_f_row); // init should have done that float gamma_lut[256]; to_f_set_gamma(gamma_lut, img->gamma); - for(unsigned int i=0; i < img->height; i++) { - convert_row_to_f(img, &img->f_pixels[i*img->width], i, gamma_lut); - } + f_pixel *row_for_thread = img->temp_f_row + LIQ_TEMP_ROW_WIDTH(img->width) * omp_get_thread_num(); + convert_row_to_f(img, row_for_thread, row, gamma_lut); + return row_for_thread; } return img->f_pixels + img->width * row; } @@ -1219,7 +1259,10 @@ const unsigned int cols = input_image->width; double remapping_error=0; - if (!liq_image_get_row_f(input_image, 0)) { // trigger lazy conversion + if (!liq_image_get_row_f_init(input_image)) { + return -1; + } + if (input_image->background && !liq_image_get_row_f_init(input_image->background)) { return -1; } @@ -1230,7 +1273,7 @@ const unsigned int max_threads = omp_get_max_threads(); - kmeans_state average_color[(KMEANS_CACHE_LINE_GAP+map->colors) * max_threads]; + LIQ_ARRAY(kmeans_state, average_color, (KMEANS_CACHE_LINE_GAP+map->colors) * max_threads); kmeans_init(map, max_threads, average_color); #pragma omp parallel for if (rows*cols > 3000) \ @@ -1292,14 +1335,14 @@ } else if (dither_error < 2.f/256.f/256.f) { // don't dither areas that don't have noticeable error — makes file smaller return px; - } + } - return (f_pixel){ - .r=px.r + sr * ratio, - .g=px.g + sg * ratio, - .b=px.b + sb * ratio, - .a=a, - }; + return (f_pixel) { + .r=px.r + sr * ratio, + .g=px.g + sg * ratio, + .b=px.b + sb * ratio, + .a=a, + }; } /** @@ -1315,6 +1358,13 @@ const colormap *map = quant->palette; const colormap_item *acolormap = map->palette; + if (!liq_image_get_row_f_init(input_image)) { + return false; + } + if (input_image->background && !liq_image_get_row_f_init(input_image->background)) { + return false; + } + /* Initialize Floyd-Steinberg error vectors. */ const size_t errwidth = cols+2; f_pixel *restrict thiserr = input_image->malloc(errwidth * sizeof(thiserr[0]) * 2); // +2 saves from checking out of bounds access @@ -1531,19 +1581,21 @@ input_hist->gamma = input_image->gamma; for(int i = 0; i < input_image->fixed_colors_count; i++) { - liq_error res = liq_histogram_add_fixed_color(input_hist, input_image->fixed_colors[i]); + liq_error res = liq_histogram_add_fixed_color_f(input_hist, input_image->fixed_colors[i]); if (res != LIQ_OK) { return res; } } - /* - ** Step 2: attempt to make a histogram of the colors, unclustered. - ** If at first we don't succeed, increase ignorebits to increase color - ** coherence and try again. - */ + /* + ** Step 2: attempt to make a histogram of the colors, unclustered. + ** If at first we don't succeed, increase ignorebits to increase color + ** coherence and try again. + */ - if (liq_progress(options, options->progress_stage1 * 0.4f)) return LIQ_ABORTED; + if (liq_progress(options, options->progress_stage1 * 0.4f)) { + return LIQ_ABORTED; + } const bool all_rows_at_once = liq_image_can_use_rgba_rows(input_image); @@ -1655,7 +1707,7 @@ unsigned char *restrict tmp = image->malloc(cols*rows); - if (!noise || !edges || !tmp) { + if (!noise || !edges || !tmp || !liq_image_get_row_f_init(image)) { image->free(noise); image->free(edges); image->free(tmp); @@ -1822,6 +1874,10 @@ // at this point actual gamma is not set, so very conservative posterization estimate is used const double target_mse = MIN(max_mse, MAX(options->target_mse, pow((1<<options->min_posterization_output)/1024.0, 2))); int feedback_loop_trials = options->feedback_loop_trials; + if (hist->size > 5000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;} + if (hist->size > 25000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;} + if (hist->size > 50000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;} + if (hist->size > 100000) {feedback_loop_trials = (feedback_loop_trials*3 + 3)/4;} colormap *acolormap = NULL; double least_error = MAX_DIFF; double target_mse_overshoot = feedback_loop_trials>0 ? 1.05 : 1.0; @@ -1831,7 +1887,7 @@ colormap *newmap; if (hist->size && fixed_colors_count < max_colors) { newmap = mediancut(hist, max_colors-fixed_colors_count, target_mse * target_mse_overshoot, MAX(MAX(45.0/65536.0, target_mse), least_error)*1.2, - options->malloc, options->free); + options->malloc, options->free); } else { feedback_loop_trials = 0; newmap = NULL; @@ -1928,7 +1984,7 @@ } // K-Means iteration approaches local minimum for the palette - const double iteration_limit = options->kmeans_iteration_limit; + double iteration_limit = options->kmeans_iteration_limit; unsigned int iterations = options->kmeans_iterations; if (!iterations && palette_error < 0 && max_mse < MAX_DIFF) iterations = 1; // otherwise total error is never calculated and MSE limit won't work @@ -1941,6 +1997,11 @@ } } + if (hist->size > 5000) {iterations = (iterations*3 + 3)/4;} + if (hist->size > 25000) {iterations = (iterations*3 + 3)/4;} + if (hist->size > 50000) {iterations = (iterations*3 + 3)/4;} + if (hist->size > 100000) {iterations = (iterations*3 + 3)/4; iteration_limit *= 2;} + verbose_print(options, " moving colormap towards local minimum"); double previous_palette_error = MAX_DIFF; @@ -2022,7 +2083,7 @@ return LIQ_BUFFER_TOO_SMALL; } - unsigned char *rows[input_image->height]; + LIQ_ARRAY(unsigned char *, rows, input_image->height); unsigned char *buffer_bytes = buffer; for(unsigned int i=0; i < input_image->height; i++) { rows[i] = &buffer_bytes[input_image->width * i]; @@ -2062,7 +2123,9 @@ set_rounded_palette(&result->int_palette, result->palette, result->gamma, quant->min_posterization_output); remapping_error = remap_to_palette(input_image, row_pointers, result->palette); } else { - const bool generate_dither_map = result->use_dither_map && (input_image->edges && !input_image->dither_map); + const bool is_image_huge = (input_image->width * input_image->height) > 2000 * 2000; + const bool allow_dither_map = result->use_dither_map == 2 || (!is_image_huge && result->use_dither_map); + const bool generate_dither_map = allow_dither_map && (input_image->edges && !input_image->dither_map); if (generate_dither_map) { // If dithering (with dither map) is required, this image is used to find areas that require dithering remapping_error = remap_to_palette(input_image, row_pointers, result->palette); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/libimagequant.h new/libimagequant-2.12.2/libimagequant.h --- old/libimagequant-2.11.3/libimagequant.h 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/libimagequant.h 2018-10-28 22:39:27.000000000 +0100 @@ -13,8 +13,8 @@ #define LIQ_EXPORT extern #endif -#define LIQ_VERSION 21102 -#define LIQ_VERSION_STRING "2.11.2" +#define LIQ_VERSION 21200 +#define LIQ_VERSION_STRING "2.12.2" #ifndef LIQ_PRIVATE #if defined(__GNUC__) || defined (__llvm__) @@ -79,6 +79,7 @@ LIQ_EXPORT LIQ_USERESULT liq_histogram* liq_histogram_create(const liq_attr* attr); LIQ_EXPORT liq_error liq_histogram_add_image(liq_histogram *hist, const liq_attr *attr, liq_image* image) LIQ_NONNULL; LIQ_EXPORT liq_error liq_histogram_add_colors(liq_histogram *hist, const liq_attr *attr, const liq_histogram_entry entries[], int num_entries, double gamma) LIQ_NONNULL; +LIQ_EXPORT liq_error liq_histogram_add_fixed_color(liq_histogram *hist, liq_color color, double gamma) LIQ_NONNULL; LIQ_EXPORT void liq_histogram_destroy(liq_histogram *hist) LIQ_NONNULL; LIQ_EXPORT liq_error liq_set_max_colors(liq_attr* attr, int colors) LIQ_NONNULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/mediancut.c new/libimagequant-2.12.2/mediancut.c --- old/libimagequant-2.11.3/mediancut.c 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/mediancut.c 2018-10-28 22:39:27.000000000 +0100 @@ -1,5 +1,5 @@ /* -** © 2009-2017 by Kornel Lesiński. +** © 2009-2018 by Kornel Lesiński. ** © 1989, 1991 by Jef Poskanzer. ** © 1997, 2000, 2002 by Greg Roelofs; based on an idea by Stefan Schneider. ** @@ -175,7 +175,7 @@ static int comparevariance(const void *ch1, const void *ch2) { return ((const channelvariance*)ch1)->variance > ((const channelvariance*)ch2)->variance ? -1 : - (((const channelvariance*)ch1)->variance < ((const channelvariance*)ch2)->variance ? 1 : 0); + (((const channelvariance*)ch1)->variance < ((const channelvariance*)ch2)->variance ? 1 : 0); } /** Finds which channels need to be sorted first and preproceses achv for fast sort */ @@ -202,7 +202,7 @@ // Only the first channel really matters. When trying median cut many times // with different histogram weights, I don't want sort randomness to influence outcome. achv[ind1 + i].tmp.sort_value = ((unsigned int)(chans[channels[0].chan]*65535.0)<<16) | - (unsigned int)((chans[channels[2].chan] + chans[channels[1].chan]/2.0 + chans[channels[3].chan]/4.0)*65535.0); + (unsigned int)((chans[channels[2].chan] + chans[channels[1].chan]/2.0 + chans[channels[3].chan]/4.0)*65535.0); } const f_pixel median = get_median(b, achv); @@ -325,7 +325,7 @@ LIQ_PRIVATE colormap *mediancut(histogram *hist, unsigned int newcolors, const double target_mse, const double max_mse, void* (*malloc)(size_t), void (*free)(void*)) { hist_item *achv = hist->achv; - struct box bv[newcolors]; + LIQ_ARRAY(struct box, bv, newcolors); unsigned int boxes = 1; /* @@ -353,8 +353,9 @@ // later raises the limit to allow large smooth areas/gradients get colors. const double current_max_mse = max_mse + (boxes/(double)newcolors)*16.0*max_mse; const int bi = best_splittable_box(bv, boxes, current_max_mse); - if (bi < 0) - break; /* ran out of colors! */ + if (bi < 0) { + break; /* ran out of colors! */ + } unsigned int indx = bv[bi].ind; unsigned int clrs = bv[bi].colors; @@ -387,8 +388,7 @@ #pragma omp taskgroup { - #pragma omp task if (break_at > 2000) - box_init(&bv[bi], achv, bv[bi].ind, break_at, lowersum); + box_init(&bv[bi], achv, indx, break_at, lowersum); box_init(&bv[boxes], achv, indx + break_at, clrs - break_at, sm - lowersum); } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/nearest.c new/libimagequant-2.12.2/nearest.c --- old/libimagequant-2.11.3/nearest.c 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/nearest.c 2018-10-28 22:39:27.000000000 +0100 @@ -110,7 +110,7 @@ mempoolptr m = NULL; struct nearest_map *handle = mempool_create(&m, sizeof(handle[0]), sizeof(handle[0]) + sizeof(vp_node)*map->colors+16, map->malloc, map->free); - vp_sort_tmp indexes[map->colors]; + LIQ_ARRAY(vp_sort_tmp, indexes, map->colors); for(unsigned int i=0; i < map->colors; i++) { indexes[i].idx = i; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/pam.h new/libimagequant-2.12.2/pam.h --- old/libimagequant-2.11.3/pam.h 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/pam.h 2018-10-28 22:39:27.000000000 +0100 @@ -62,6 +62,12 @@ # define SSE_ALIGN #endif +#ifndef _MSC_VER +#define LIQ_ARRAY(type, var, count) type var[count] +#else +#define LIQ_ARRAY(type, var, count) type* var = (type*)_alloca(sizeof(type)*(count)) +#endif + #if defined(__GNUC__) || defined (__llvm__) #define ALWAYS_INLINE __attribute__((always_inline)) inline #define NEVER_INLINE __attribute__ ((noinline)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/rust/build.rs new/libimagequant-2.12.2/rust/build.rs --- old/libimagequant-2.11.3/rust/build.rs 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/rust/build.rs 2018-10-28 22:39:27.000000000 +0100 @@ -9,6 +9,7 @@ fn main() { let mut cc = cc::Build::new(); + let compiler = cc.get_compiler(); cc.warnings(false); if env::var("PROFILE").map(|p|p != "debug").unwrap_or(true) { @@ -16,12 +17,13 @@ } if cfg!(feature = "openmp") { - cc.flag("-fopenmp"); + cc.flag(&env::var("DEP_OPENMP_FLAG").unwrap()); } - if cfg!(target_arch="x86_64") || - (cfg!(target_arch="x86") && cfg!(feature = "sse")) { - cc.flag("-msse"); + let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("Needs CARGO_CFG_TARGET_ARCH"); + if target_arch =="x86_64" || + (target_arch == "x86" && cfg!(feature = "sse")) { + cc.flag(if compiler.is_like_msvc() {"/arch:SSE2"} else {"-msse"}); cc.define("USE_SSE", Some("1")); } @@ -43,7 +45,9 @@ println!("cargo:warning=msvc-dist/ directory not present. MSVC builds may fail"); } println!("cargo:include={}", canonicalize(".").unwrap().display()); - cc.flag("-std=c99"); + if !compiler.is_like_msvc() { + cc.flag("-std=c99"); + } cc.file("libimagequant.c") .file("nearest.c") .file("kmeans.c") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/libimagequant-2.11.3/rust/libimagequant.rs new/libimagequant-2.12.2/rust/libimagequant.rs --- old/libimagequant-2.11.3/rust/libimagequant.rs 2017-11-11 15:20:18.000000000 +0100 +++ new/libimagequant-2.12.2/rust/libimagequant.rs 2018-10-28 22:39:27.000000000 +0100 @@ -124,6 +124,15 @@ } } + #[inline] + pub fn ok_or<E>(self, err: E) -> Result<(), E> { + if self.is_ok() { + Ok(()) + } else { + Err(err) + } + } + pub fn unwrap(&self) { assert!(self.is_ok(), "{}", self); } @@ -136,10 +145,8 @@ pub type liq_log_callback_function = Option<unsafe extern "C" fn(arg1: &liq_attr, message: *const c_char, user_info: *mut c_void)>; pub type liq_log_flush_callback_function = Option<unsafe extern "C" fn(arg1: &liq_attr, user_info: *mut c_void)>; pub type liq_progress_callback_function = Option<unsafe extern "C" fn(progress_percent: f32, user_info: *mut c_void) -> c_int>; -pub type liq_image_get_rgba_row_callback = Option<unsafe extern "C" fn(row_out: &mut liq_color, - row: c_int, - width: c_int, - user_info: *mut c_void)>; +pub type liq_image_get_rgba_row_callback = unsafe extern "C" fn(row_out: *mut liq_color, row: c_int, width: c_int, user_info: *mut c_void); + #[link(name="imagequant", kind="static")] extern "C" {