Skip to content

Commit

Permalink
feat: update libimagequant to 2.18.0-1 (#2)
Browse files Browse the repository at this point in the history
Signed-off-by: lhdjply <[email protected]>
  • Loading branch information
lhdjply authored Jan 20, 2025
1 parent 7a0d66f commit ce1c055
Show file tree
Hide file tree
Showing 52 changed files with 3,226 additions and 634 deletions.
28 changes: 27 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,27 @@
.pc/
config.mk
imagequant.pc
*.lo
*.o
*.a
*.so.0
*.so
*.bz2
*.dylib
*.dylib.0
*.jnilib
*.dSYM
org/pngquant/*.class
org/pngquant/*.h
target/
msvc-dist/org/
msvc-dist/*.md
msvc-dist/Makefile*
msvc-dist/*.cs
msvc-dist/*.xml
msvc-dist/CHANGELOG
msvc-dist/COPYRIGHT
msvc-dist/configure
msvc-dist/.gitignore
quantized_example.png
example
lodepng.?
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ matrix:
include:
- os: linux
language: java
jdk: oraclejdk8
jdk: oraclejdk9
env: CFLAGS="-fPIC"
install: true
script: make java
Expand Down
43 changes: 43 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,46 @@
version 4
---------

- rewritten in Rust
- multi-threaded floyd-steinberg dithering gives 2x-3x remapping speed boost
- better handling of remapping on top of backgrounds (for GIFs, gif.ski)
- support for more than 256-colors (compile-time option)
- WASM compatibility
- the C API enables dithering by default

Newer v3/v4 versions of the library are on crates.io: https://crates.io/crates/imagequant

version 2.18
------------
- improved handling of images with very few pixels with very diverse colors
- added more perceptually-weighed color selection
- dropped problematic omp_set_nested()
- fixed a rare memory leak

version 2.17
------------
- quality improvement
- ARM64 build fix

version 2.16
------------
- fixed LCMS2 error handling

version 2.15
------------
- speed and quality improvements

version 2.14
------------
- improved Rust API
- quality improvements for remapping overlays over a background

version 2.13
------------
- support OpenMP in clang
- dropped old Internet Explorer workarounds
- speed and quality improvements

version 2.12
------------
- new liq_histogram_add_fixed_color()
Expand Down
56 changes: 56 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
cmake_minimum_required(VERSION 2.6)
file(READ version.txt VERSION)

project(imagequant C)

if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL ARM64)
option(BUILD_WITH_SSE "Use SSE" OFF)
else()
option(BUILD_WITH_SSE "Use SSE" ON)
endif()

if(BUILD_WITH_SSE)
add_definitions(-DUSE_SSE=1)
endif()

find_package(OpenMP)
if(OPENMP_FOUND)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()

include_directories(${CMAKE_SOURCE_DIR})

if(CMAKE_COMPILER_IS_GNUCC)
add_compile_options("-std=c99")
endif()

add_library(imagequant SHARED
libimagequant.c
blur.c
mediancut.c
mempool.c
nearest.c
pam.c
kmeans.c
)

add_library(imagequant_a STATIC
libimagequant.c
blur.c
mediancut.c
mempool.c
nearest.c
pam.c
kmeans.c
)
set_target_properties(imagequant PROPERTIES SOVERSION 0
VERSION 0.0)

set(PREFIX ${CMAKE_INSTALL_PREFIX})
configure_file(imagequant.pc.in imagequant.pc @ONLY)

install(TARGETS imagequant LIBRARY DESTINATION ${LIB_INSTALL_DIR})
install(FILES libimagequant.h DESTINATION include)
install(FILES ${CMAKE_BINARY_DIR}/libimagequant_a.a DESTINATION ${LIB_INSTALL_DIR} RENAME libimagequant.a)
install(FILES ${CMAKE_BINARY_DIR}/imagequant.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig)
29 changes: 19 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
# libimagequant is a pure C library.
# Rust/Cargo is entirely optional. You can also use ./configure && make
# Please upgrade to v4 of the library
[package]
version = "3.1.4+sys2.18.0"
authors = ["Kornel Lesiński <[email protected]>"]
build = "rust/build.rs"
build = "rust-sys/build.rs"
categories = ["external-ffi-bindings"]
homepage = "https://pngquant.org/lib"
include = ["COPYRIGHT", "rust/*", "*.c", "*.h", "README.md", "Cargo.toml"]
include = ["COPYRIGHT", "rust-sys/*", "*.c", "*.h", "README.md", "Cargo.toml"]
keywords = ["pngquant"]
license = "GPL-3.0+"
license = "GPL-3.0-or-later"
links = "imagequant"
name = "imagequant-sys"
readme = "README.md"
repository = "https://github.com/ImageOptim/libimagequant"
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"
edition = "2018"

[build-dependencies]
cc = "1.0.17"
cc = "1.0.71"

[dependencies]
rgb = "0.8.9"
rgb = "0.8.29"
bitflags = "1.3.2"

[dependencies.openmp-sys]
optional = true
version = "0.1.5"
version = "1.2.0"

[features]
default = ["sse"]
Expand All @@ -34,5 +35,13 @@ sse = []
[lib]
crate-type = ["cdylib", "staticlib", "lib"]
name = "imagequant_sys"
path = "rust/libimagequant.rs"
path = "rust-sys/libimagequant.rs"
doctest = false

[dev-dependencies]
lodepng = "3.4.7"
imagequant = { path = "./rust-api" }

[profile.bench]
debug = 1
split-debuginfo = 'unpacked'
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ JNIDLL=libimagequant.dll
JNIDLLIMP=libimagequant_dll.a
JNIDLLDEF=libimagequant_dll.def

OBJS = pam.o mediancut.o blur.o mempool.o kmeans.o nearest.o libimagequant.o
OBJS = pam.o mediancut.o blur.o remap.o mempool.o kmeans.o nearest.o libimagequant.o
SHAREDOBJS = $(subst .o,.lo,$(OBJS))

JAVACLASSES = org/pngquant/LiqObject.class org/pngquant/PngQuant.class org/pngquant/Image.class org/pngquant/Result.class
Expand Down Expand Up @@ -65,7 +65,7 @@ libimagequant.dylib: $(SHAREDOBJS)
$(OBJS): $(wildcard *.h) config.mk

$(JNILIB): $(JAVAHEADERS) $(STATICLIB) org/pngquant/PngQuant.c
$(CC) -g $(CFLAGS) $(LDFLAGS) $(JAVAINCLUDE) -shared -o $@ $(STATICLIB) org/pngquant/PngQuant.c
$(CC) -g $(CFLAGS) $(LDFLAGS) $(JAVAINCLUDE) -shared -o $@ org/pngquant/PngQuant.c $(STATICLIB)

$(JNIDLL) $(JNIDLLIMP): $(JAVAHEADERS) $(OBJS) org/pngquant/PngQuant.c
$(CC) -fPIC -shared -I. $(JAVAINCLUDE) -o $(JNIDLL) $^ $(LDFLAGS) -Wl,--out-implib,$(JNIDLLIMP),--output-def,$(JNIDLLDEF)
Expand Down Expand Up @@ -93,7 +93,7 @@ cargo:
cargo test

example: example.c lodepng.h lodepng.c $(STATICLIB)
$(CC) -g $(CFLAGS) -Wall example.c $(STATICLIB) -o example
$(CC) -g $(CFLAGS) -Wall example.c $(STATICLIB) -o example -lm

lodepng.h:
curl -o lodepng.h -L https://raw.githubusercontent.com/lvandeve/lodepng/master/lodepng.h
Expand All @@ -104,6 +104,7 @@ lodepng.c:
clean:
rm -f $(OBJS) $(SHAREDOBJS) $(SHAREDLIBVER) $(SHAREDLIB) $(STATICLIB) $(TARFILE) $(DLL) '$(DLLIMP)' '$(DLLDEF)'
rm -f $(JAVAHEADERS) $(JAVACLASSES) $(JNILIB) example
rm -rf target rust-api/target rust-sys/target

distclean: clean
rm -f config.mk
Expand All @@ -114,7 +115,7 @@ install: all $(PKGCONFIG)
install -d $(DESTDIR)$(PKGCONFIGDIR)
install -d $(DESTDIR)$(INCLUDEDIR)
install -m 644 $(STATICLIB) $(DESTDIR)$(LIBDIR)/$(STATICLIB)
install -m 644 $(SHAREDLIBVER) $(DESTDIR)$(LIBDIR)/$(SHAREDLIBVER)
install -m 755 $(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
Expand All @@ -133,7 +134,7 @@ ifeq ($(filter %clean %distclean, $(MAKECMDGOALS)), )
endif

$(PKGCONFIG): config.mk
sed 's|PREFIX|$(PREFIX)|;s|VERSION|$(VERSION)|' < imagequant.pc.in > $(PKGCONFIG)
sed 's|@PREFIX@|$(PREFIX)|;s|@VERSION@|$(VERSION)|' < imagequant.pc.in > $(PKGCONFIG)

.PHONY: all static shared clean dist distclean dll java cargo
.DELETE_ON_ERROR:
36 changes: 24 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ It's powering [pngquant2](https://pngquant.org).

Libimagequant is dual-licensed:

* For Free/Libre Open Source Software it's available under [GPL v3 or later](https://raw.github.com/ImageOptim/libimagequant/master/COPYRIGHT) with additional copyright notices for older parts of the code.

* For use in non-GPL software (e.g. closed-source or App Store distribution) please ask [email protected] for a commercial license.
* For Free/Libre Open Source Software it's available under GPL v3 or later with additional [copyright notices](https://raw.github.com/ImageOptim/libimagequant/master/COPYRIGHT) for older parts of the code.
* For use in closed-source software, AppStore distribution, and other non-GPL uses, you can [obtain a commercial license](https://supso.org/projects/pngquant). Feel free to ask [email protected] for details and custom licensing terms if you need them.

## Download

Expand Down Expand Up @@ -50,10 +49,23 @@ On Windows run `make java-dll` and it'll create `libimagequant.dll` instead.

### Compiling on Windows/Visual Studio

The library can be compiled with any C compiler that has at least basic support for C99 (GCC, clang, ICC, C++ Builder, even Tiny C Compiler), but Visual Studio 2012 and older are not up to date with the 1999 C standard. There are 2 options for using `libimagequant` on Windows:
The library can be compiled with any C compiler that has at least basic support for C99 (GCC, clang, ICC, C++ Builder, even Tiny C Compiler), but Visual Studio 2012 and older are not up to date with the 1999 C standard. Use Visual Studio **2015** and the [MSVC-compatible branch of the library](https://github.com/ImageOptim/libimagequant/tree/msvc).

To build on Windows, install CMake and use it to generate a makefile/project for your build system.

Build instructions

mkdir build
cd build
cmake ..
cmake --build .

* 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.
To generate a 64-bit Visual Studio project instead:

mkdir build
cd build
cmake -G "Visual Studio 15 2017 Win64" ..
cmake --build .

### Building as shared library

Expand Down Expand Up @@ -303,7 +315,7 @@ Freeing `liq_result` also frees any `liq_palette` obtained from it.

liq_error liq_set_speed(liq_attr* attr, int speed);

Higher speed levels disable expensive algorithms and reduce quantization precision. The default speed is `3`. Speed `1` gives marginally better quality at significant CPU cost. Speed `10` has usually 5% lower quality, but is 8 times faster than the default.
Higher speed levels disable expensive algorithms and reduce quantization precision. The default speed is `4`. Speed `1` gives marginally better quality at significant CPU cost. Speed `10` has usually 5% lower quality, but is 8 times faster than the default.

High speeds combined with `liq_set_quality()` will use more colors than necessary and will be less likely to meet minimum required quality.

Expand All @@ -326,15 +338,13 @@ Returns the value set by `liq_set_speed()`.

liq_error liq_set_min_opacity(liq_attr* attr, int min);

Alpha values higher than this will be rounded to opaque. This is a workaround for Internet Explorer 6, but because this browser is not used any more, this option is deprecated and will be removed. The default is `255` (no change).

Returns `LIQ_VALUE_OUT_OF_RANGE` if the value is outside the 0-255 range.
This was a workaround for Internet Explorer 6, but because this browser is not used any more, this option has been deprecated and removed.

----

int liq_get_min_opacity(liq_attr* attr);

Returns the value set by `liq_set_min_opacity()`.
This function has been deprecated.

----

Expand Down Expand Up @@ -667,7 +677,9 @@ The library needs to sort unique colors present in the image. Although the sorti

### OpenMP

The library will parallelize some operations if compiled with OpenMP.
The library can parallelize some operations if compiled with OpenMP.

GCC 9 or later is required for correct OpenMP support. Older compilers *will cause bugs* when OpenMP is enabled.

You must not increase number of maximum threads after `liq_image` has been created, as it allocates some per-thread buffers.

Expand Down
69 changes: 69 additions & 0 deletions benches/bench.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#![feature(test)]

extern crate test;
use test::Bencher;

use imagequant::*;

#[bench]
fn histogram(b: &mut Bencher) {
let img = lodepng::decode32_file("/Users/kornel/Desktop/canvas.png").unwrap();
let liq = Attributes::new();
b.iter(move || {
let mut img = liq.new_image(&img.buffer, img.width, img.height, 0.).unwrap();
let mut hist = Histogram::new(&liq);
hist.add_image(&mut img).unwrap();
})
}

#[bench]
fn remap_ord(b: &mut Bencher) {
let img = lodepng::decode32_file("/Users/kornel/Desktop/canvas.png").unwrap();
let mut buf = vec![std::mem::MaybeUninit::uninit(); img.width * img.height];
let mut liq = Attributes::new();
liq.set_speed(10);
let mut img = liq.new_image(&img.buffer, img.width, img.height, 0.).unwrap();
let mut res = liq.quantize(&mut img).unwrap();
res.set_dithering_level(0.);
b.iter(move || {
res.remap_into(&mut img, &mut buf).unwrap();
res.remap_into(&mut img, &mut buf).unwrap();
})
}

#[bench]
fn remap_floyd(b: &mut Bencher) {
let img = lodepng::decode32_file("/Users/kornel/Desktop/canvas.png").unwrap();
let mut buf = vec![std::mem::MaybeUninit::uninit(); img.width * img.height];
let mut liq = Attributes::new();
liq.set_speed(10);
let mut img = liq.new_image(&img.buffer, img.width, img.height, 0.).unwrap();
let mut res = liq.quantize(&mut img).unwrap();
res.set_dithering_level(1.);
b.iter(move || {
res.remap_into(&mut img, &mut buf).unwrap();
res.remap_into(&mut img, &mut buf).unwrap();
})
}

#[bench]
fn quantize_s8(b: &mut Bencher) {
let img = lodepng::decode32_file("/Users/kornel/Desktop/canvas.png").unwrap();
let mut liq = Attributes::new();
liq.set_speed(8);
b.iter(move || {
let mut img = liq.new_image(&img.buffer, img.width, img.height, 0.).unwrap();
liq.quantize(&mut img).unwrap();
})
}

#[bench]
fn quantize_s1(b: &mut Bencher) {
let img = lodepng::decode32_file("/Users/kornel/Desktop/canvas.png").unwrap();
let mut liq = Attributes::new();
liq.set_speed(1);
b.iter(move || {
let mut img = liq.new_image(&img.buffer, img.width, img.height, 0.).unwrap();
liq.quantize(&mut img).unwrap();
})
}
Loading

0 comments on commit ce1c055

Please sign in to comment.