Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package libimagequant for openSUSE:Factory 
checked in at 2021-06-05 23:30:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/libimagequant (Old)
 and      /work/SRC/openSUSE:Factory/.libimagequant.new.1898 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "libimagequant"

Sat Jun  5 23:30:48 2021 rev:7 rq:896625 version:2.14.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/libimagequant/libimagequant.changes      
2020-12-30 17:12:14.364832334 +0100
+++ /work/SRC/openSUSE:Factory/.libimagequant.new.1898/libimagequant.changes    
2021-06-05 23:31:10.956401503 +0200
@@ -1,0 +2,7 @@
+Sat May  8 18:10:01 UTC 2021 - Dirk M??ller <[email protected]>
+
+- update to 2.14.1:
+  * improved Rust API
+  * quality improvements for remapping overlays over a background
+
+-------------------------------------------------------------------

Old:
----
  libimagequant-2.13.1.tar.gz

New:
----
  libimagequant-2.14.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ libimagequant.spec ++++++
--- /var/tmp/diff_new_pack.eNJyQa/_old  2021-06-05 23:31:11.440402345 +0200
+++ /var/tmp/diff_new_pack.eNJyQa/_new  2021-06-05 23:31:11.444402351 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package libimagequant
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2021 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %define sover   0
 %define libname %{name}%{sover}
 Name:           libimagequant
-Version:        2.13.1
+Version:        2.14.1
 Release:        0
 Summary:        Palette quantization library
 License:        GPL-3.0-or-later

++++++ libimagequant-2.13.1.tar.gz -> libimagequant-2.14.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/CHANGELOG 
new/libimagequant-2.14.1/CHANGELOG
--- old/libimagequant-2.13.1/CHANGELOG  2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/CHANGELOG  2021-02-28 19:12:44.000000000 +0100
@@ -1,3 +1,14 @@
+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()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/CMakeLists.txt 
new/libimagequant-2.14.1/CMakeLists.txt
--- old/libimagequant-2.13.1/CMakeLists.txt     1970-01-01 01:00:00.000000000 
+0100
+++ new/libimagequant-2.14.1/CMakeLists.txt     2021-02-28 19:12:44.000000000 
+0100
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 2.6)
+
+project(imagequant C)
+
+option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
+option(BUILD_WITH_SSE "Use SSE" ON)
+
+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
+)
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/Cargo.toml 
new/libimagequant-2.14.1/Cargo.toml
--- old/libimagequant-2.13.1/Cargo.toml 2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/Cargo.toml 2021-02-28 19:12:44.000000000 +0100
@@ -1,7 +1,7 @@
 # libimagequant is a pure C library.
 # Rust/Cargo is entirely optional. You can also use ./configure && make
 [package]
-version = "2.13.1"
+version = "3.0.5+sys2.14.1"
 authors = ["Kornel Lesin??ski <[email protected]>"]
 build = "rust-sys/build.rs"
 categories = ["external-ffi-bindings"]
@@ -21,10 +21,11 @@
 
 [dependencies]
 rgb = "0.8.25"
+bitflags = "1.2.1"
 
 [dependencies.openmp-sys]
 optional = true
-version = "1.0.0"
+version = "1.2.0-alpha.1"
 
 [features]
 default = ["sse"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/Makefile 
new/libimagequant-2.14.1/Makefile
--- old/libimagequant-2.13.1/Makefile   2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/Makefile   2021-02-28 19:12:44.000000000 +0100
@@ -93,7 +93,7 @@
        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
@@ -104,6 +104,7 @@
 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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/README.md 
new/libimagequant-2.14.1/README.md
--- old/libimagequant-2.13.1/README.md  2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/README.md  2021-02-28 19:12:44.000000000 +0100
@@ -49,10 +49,23 @@
 
 ### 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).
 
- * 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 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 .
+
+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
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/kmeans.c 
new/libimagequant-2.14.1/kmeans.c
--- old/libimagequant-2.13.1/kmeans.c   2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/kmeans.c   2021-02-28 19:12:44.000000000 +0100
@@ -61,11 +61,12 @@
                     .b = b / total,
                 };
             } else {
-                unsigned int r = (i + rand()%7);
-                map->palette[i].acolor.a = 
map->palette[r%map->colors].acolor.a;
-                map->palette[i].acolor.r = 
map->palette[r%map->colors].acolor.r;
-                map->palette[i].acolor.g = 
map->palette[(r+1)%map->colors].acolor.g;
-                map->palette[i].acolor.b = 
map->palette[(r+2)%map->colors].acolor.b;
+                // if a color is useless, make a new one
+                // (it was supposed to be random, but Android NDK has 
problematic stdlib headers)
+                map->palette[i].acolor.a = 
map->palette[(i+1)%map->colors].acolor.a;
+                map->palette[i].acolor.r = 
map->palette[(i+2)%map->colors].acolor.r;
+                map->palette[i].acolor.g = 
map->palette[(i+3)%map->colors].acolor.g;
+                map->palette[i].acolor.b = 
map->palette[(i+4)%map->colors].acolor.b;
             }
         }
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/libimagequant.c 
new/libimagequant-2.14.1/libimagequant.c
--- old/libimagequant-2.13.1/libimagequant.c    2020-11-22 14:18:54.000000000 
+0100
+++ new/libimagequant-2.14.1/libimagequant.c    2021-02-28 19:12:44.000000000 
+0100
@@ -626,6 +626,7 @@
 }
 
 LIQ_NONNULL static void liq_image_free_maps(liq_image *input_image);
+LIQ_NONNULL static void liq_image_free_dither_map(liq_image *input_image);
 LIQ_NONNULL static void liq_image_free_importance_map(liq_image *input_image);
 
 LIQ_EXPORT LIQ_NONNULL liq_error liq_image_set_importance_map(liq_image *img, 
unsigned char importance_map[], size_t buffer_size, enum liq_ownership 
ownership) {
@@ -671,7 +672,7 @@
     }
 
     img->background = background;
-    liq_image_free_maps(img); // Force them to be re-analyzed with the 
background
+    liq_image_free_dither_map(img); // Force it to be re-analyzed with the 
background
 
     return LIQ_OK;
 }
@@ -848,7 +849,16 @@
 
 typedef void free_func(void*);
 
-LIQ_NONNULL static free_func *get_default_free_func(liq_image *img)
+LIQ_NONNULL static free_func *get_default_image_free_func(liq_image *img)
+{
+    // When default allocator is used then user-supplied pointers must be 
freed with free()
+    if (img->free != liq_aligned_free) {
+        return img->free;
+    }
+    return free;
+}
+
+LIQ_NONNULL static free_func *get_default_rows_free_func(liq_image *img)
 {
     // When default allocator is used then user-supplied pointers must be 
freed with free()
     if (img->free_rows_internal || img->free != liq_aligned_free) {
@@ -860,12 +870,12 @@
 LIQ_NONNULL static void liq_image_free_rgba_source(liq_image *input_image)
 {
     if (input_image->free_pixels && input_image->pixels) {
-        get_default_free_func(input_image)(input_image->pixels);
+        get_default_image_free_func(input_image)(input_image->pixels);
         input_image->pixels = NULL;
     }
 
     if (input_image->free_rows && input_image->rows) {
-        get_default_free_func(input_image)(input_image->rows);
+        get_default_rows_free_func(input_image)(input_image->rows);
         input_image->rows = NULL;
     }
 }
@@ -884,7 +894,10 @@
         input_image->free(input_image->edges);
         input_image->edges = NULL;
     }
+    liq_image_free_dither_map(input_image);
+}
 
+LIQ_NONNULL static void liq_image_free_dither_map(liq_image *input_image) {
     if (input_image->dither_map) {
         input_image->free(input_image->dither_map);
         input_image->dither_map = NULL;
@@ -968,6 +981,7 @@
     }
     liq_error err = liq_histogram_add_image(hist, attr, img);
     if (LIQ_OK != err) {
+        liq_histogram_destroy(hist);
         return err;
     }
 
@@ -1251,7 +1265,12 @@
     const colormap_item *acolormap = map->palette;
 
     struct nearest_map *const n = nearest_init(map);
-    const int transparent_index = input_image->background ? nearest_search(n, 
&(f_pixel){0,0,0,0}, 0, NULL) : 0;
+    liq_image *background = input_image->background;
+    const int transparent_index = background ? nearest_search(n, 
&(f_pixel){0,0,0,0}, 0, NULL) : -1;
+    if (background && acolormap[transparent_index].acolor.a > 1.f/256.f) {
+        // palette unsuitable for using the bg
+        background = NULL;
+    }
 
 
     const unsigned int max_threads = omp_get_max_threads();
@@ -1260,26 +1279,29 @@
 
 #if __GNUC__ >= 9 || __clang__
     #pragma omp parallel for if (rows*cols > 3000) \
-        schedule(static) default(none) 
shared(acolormap,average_color,cols,input_image,map,n,output_pixels,rows,transparent_index)
 reduction(+:remapping_error)
-#else
-    #pragma omp parallel for if (rows*cols > 3000) \
-        schedule(static) default(none) shared(acolormap) shared(average_color) 
reduction(+:remapping_error)
+        schedule(static) default(none) 
shared(background,acolormap,average_color,cols,input_image,map,n,output_pixels,rows,transparent_index)
 reduction(+:remapping_error)
 #endif
     for(int row = 0; row < rows; ++row) {
         const f_pixel *const row_pixels = liq_image_get_row_f(input_image, 
row);
-        const f_pixel *const bg_pixels = input_image->background && 
acolormap[transparent_index].acolor.a < 1.f/256.f ? 
liq_image_get_row_f(input_image->background, row) : NULL;
+        const f_pixel *const bg_pixels = background && 
acolormap[transparent_index].acolor.a < 1.f/256.f ? 
liq_image_get_row_f(background, row) : NULL;
 
         unsigned int last_match=0;
         for(unsigned int col = 0; col < cols; ++col) {
             float diff;
             last_match = nearest_search(n, &row_pixels[col], last_match, 
&diff);
-            if (bg_pixels && colordifference(bg_pixels[col], 
acolormap[last_match].acolor) <= diff) {
-                last_match = transparent_index;
+            if (bg_pixels) {
+                float bg_diff = colordifference(bg_pixels[col], 
acolormap[last_match].acolor);
+                if (bg_diff <= diff) {
+                    diff = bg_diff;
+                    last_match = transparent_index;
+                }
             }
             output_pixels[row][col] = last_match;
 
             remapping_error += diff;
-            kmeans_update_color(row_pixels[col], 1.0, map, last_match, 
omp_get_thread_num(), average_color);
+            if (last_match != transparent_index) {
+                kmeans_update_color(row_pixels[col], 1.0, map, last_match, 
omp_get_thread_num(), average_color);
+            }
         }
     }
 
@@ -1361,7 +1383,12 @@
 
     bool ok = true;
     struct nearest_map *const n = nearest_init(map);
-    const int transparent_index = input_image->background ? nearest_search(n, 
&(f_pixel){0,0,0,0}, 0, NULL) : 0;
+    liq_image *background = input_image->background;
+    const int transparent_index = background ? nearest_search(n, 
&(f_pixel){0,0,0,0}, 0, NULL) : -1;
+    if (background && acolormap[transparent_index].acolor.a > 1.f/256.f) {
+        // palette unsuitable for using the bg
+        background = NULL;
+    }
 
     // response to this value is non-linear and without it any value < 0.8 
would give almost no dithering
     float base_dithering_level = quant->dither_level;
@@ -1384,7 +1411,8 @@
 
         int col = (fs_direction > 0) ? 0 : (cols - 1);
         const f_pixel *const row_pixels = liq_image_get_row_f(input_image, 
row);
-        const f_pixel *const bg_pixels = input_image->background && 
acolormap[transparent_index].acolor.a < 1.f/256.f ? 
liq_image_get_row_f(input_image->background, row) : NULL;
+        const f_pixel *const bg_pixels = background && 
acolormap[transparent_index].acolor.a < 1.f/256.f ? 
liq_image_get_row_f(background, row) : NULL;
+        int undithered_bg_used = 0;
 
         do {
             float dither_level = base_dithering_level;
@@ -1395,16 +1423,42 @@
             const f_pixel spx = get_dithered_pixel(dither_level, 
max_dither_error, thiserr[col + 1], row_pixels[col]);
 
             const unsigned int guessed_match = output_image_is_remapped ? 
output_pixels[row][col] : last_match;
-            float diff;
-            last_match = nearest_search(n, &spx, guessed_match, &diff);
+            float dither_diff;
+            last_match = nearest_search(n, &spx, guessed_match, &dither_diff);
             f_pixel output_px = acolormap[last_match].acolor;
-            if (bg_pixels && colordifference(bg_pixels[col], output_px) <= 
diff) {
-                output_px = bg_pixels[col];
-                output_pixels[row][col] = transparent_index;
-            } else {
-                output_pixels[row][col] = last_match;
+            // this is for animgifs
+            if (bg_pixels) {
+                // if the background makes better match *with* dithering, it's 
a definitive win
+                float bg_for_dither_diff = colordifference(spx, 
bg_pixels[col]);
+                if (bg_for_dither_diff <= dither_diff) {
+                    output_px = bg_pixels[col];
+                    last_match = transparent_index;
+                } else if (undithered_bg_used > 1) {
+                    // the undithered fallback can cause artifacts when too 
many undithered pixels accumulate a big dithering error
+                    // so periodically ignore undithered fallback to prevent 
that
+                    undithered_bg_used = 0;
+                } else {
+                    // if dithering is not applied, there's a high risk of 
creating artifacts (flat areas, error accumulating badly),
+                    // OTOH poor dithering disturbs static backgrounds and 
creates oscilalting frames that break backgrounds
+                    // back and forth in two differently bad ways
+                    float max_diff = colordifference(row_pixels[col], 
bg_pixels[col]);
+                    float dithered_diff = colordifference(row_pixels[col], 
output_px);
+                    // if dithering is worse than natural difference between 
frames
+                    // (this rule dithers moving areas, but does not dither 
static areas)
+                    if (dithered_diff > max_diff) {
+                        // then see if an undithered color is closer to the 
ideal
+                        float undithered_diff = 
colordifference(row_pixels[col], acolormap[guessed_match].acolor);
+                        if (undithered_diff < max_diff) {
+                            undithered_bg_used++;
+                            output_px = acolormap[guessed_match].acolor;
+                            last_match = guessed_match;
+                        }
+                    }
+                }
             }
 
+            output_pixels[row][col] = last_match;
+
             f_pixel err = {
                 .r = (spx.r - output_px.r),
                 .g = (spx.g - output_px.g),
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/libimagequant.h 
new/libimagequant-2.14.1/libimagequant.h
--- old/libimagequant-2.13.1/libimagequant.h    2020-11-22 14:18:54.000000000 
+0100
+++ new/libimagequant-2.14.1/libimagequant.h    2021-02-28 19:12:44.000000000 
+0100
@@ -13,8 +13,8 @@
 #define LIQ_EXPORT extern
 #endif
 
-#define LIQ_VERSION 21301
-#define LIQ_VERSION_STRING "2.13.1"
+#define LIQ_VERSION 21401
+#define LIQ_VERSION_STRING "2.14.1"
 
 #ifndef LIQ_PRIVATE
 #if defined(__GNUC__) || defined (__llvm__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/pam.c 
new/libimagequant-2.14.1/pam.c
--- old/libimagequant-2.13.1/pam.c      2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/pam.c      2021-02-28 19:12:44.000000000 +0100
@@ -178,7 +178,7 @@
 
 ALWAYS_INLINE static float pam_add_to_hist(const float *gamma_lut, hist_item 
*achv, unsigned int *j, const struct acolorhist_arr_item *entry, const float 
max_perceptual_weight)
 {
-    if (entry->perceptual_weight == 0) {
+    if (entry->perceptual_weight == 0 && *j > 0) {
         return 0;
     }
     const float w = MIN(entry->perceptual_weight/128.f, max_perceptual_weight);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/pam.h 
new/libimagequant-2.14.1/pam.h
--- old/libimagequant-2.13.1/pam.h      2020-11-22 14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/pam.h      2021-02-28 19:12:44.000000000 +0100
@@ -182,8 +182,17 @@
 inline static float colordifference(f_pixel px, f_pixel py)
 {
 #if USE_SSE
+#ifdef _MSC_VER
+    /* In MSVC we cannot use the align attribute in parameters.
+     * This is used a lot, so we just use an unaligned load.
+     * Also the compiler incorrectly inlines vpx and vpy without
+     * the volatile when optimization is applied for x86_64. */
+    const volatile __m128 vpx = _mm_loadu_ps((const float*)&px);
+    const volatile __m128 vpy = _mm_loadu_ps((const float*)&py);
+#else
     const __m128 vpx = _mm_load_ps((const float*)&px);
     const __m128 vpy = _mm_load_ps((const float*)&py);
+#endif
 
     // y.a - x.a
     __m128 alphas = _mm_sub_ss(vpy, vpx);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/rust-api/Cargo.toml 
new/libimagequant-2.14.1/rust-api/Cargo.toml
--- old/libimagequant-2.13.1/rust-api/Cargo.toml        2020-11-22 
14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/rust-api/Cargo.toml        2021-02-28 
19:12:44.000000000 +0100
@@ -10,12 +10,13 @@
 name = "imagequant"
 readme = "README.md"
 repository = "https://github.com/ImageOptim/libimagequant";
-version = "2.13.0"
+version = "3.0.4-alpha.2"
 edition = "2018"
 
 [dependencies]
-imagequant-sys = { version = "2.13.0", path = "../" }
+imagequant-sys = { version = "3.0.4-alpha.2", path = "../" }
 libc = "0.2.60"
+rgb = "0.8.25"
 
 [features]
 default = ["sse"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/rust-api/examples/basic.rs 
new/libimagequant-2.14.1/rust-api/examples/basic.rs
--- old/libimagequant-2.13.1/rust-api/examples/basic.rs 2020-11-22 
14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/rust-api/examples/basic.rs 2021-02-28 
19:12:44.000000000 +0100
@@ -4,7 +4,7 @@
     // Image loading/saving is outside scope of this library
     let width = 10usize;
     let height = 10usize;
-    let fakebitmap = vec![255u8; 4 * width * height];
+    let fakebitmap = vec![imagequant::RGBA {r:0, g:0, b:0, a:0}; width * 
height];
 
     // http://pngquant.org/lib/
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/rust-api/src/lib.rs 
new/libimagequant-2.14.1/rust-api/src/lib.rs
--- old/libimagequant-2.13.1/rust-api/src/lib.rs        2020-11-22 
14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/rust-api/src/lib.rs        2021-02-28 
19:12:44.000000000 +0100
@@ -8,16 +8,19 @@
 #![doc(html_logo_url = "https://pngquant.org/pngquant-logo.png";)]
 #![warn(missing_docs)]
 
-extern crate imagequant_sys as ffi;
-
 pub use crate::ffi::liq_error;
 pub use crate::ffi::liq_error::*;
+
+use imagequant_sys as ffi;
 use std::fmt;
-use std::marker;
+use std::marker::PhantomData;
 use std::mem;
+use std::mem::MaybeUninit;
 use std::os::raw::c_int;
 use std::ptr;
 
+pub use rgb::RGBA8 as RGBA;
+
 /// 8-bit RGBA. This is the only color format used by the library.
 pub type Color = ffi::liq_color;
 
@@ -26,7 +29,7 @@
 /// Used if you're building histogram manually. Otherwise see `add_image()`
 pub type HistogramEntry = ffi::liq_histogram_entry;
 
-/// Settings for the conversion proces. Start here.
+/// Settings for the conversion process. Start here.
 pub struct Attributes {
     handle: *mut ffi::liq_attr,
 }
@@ -35,7 +38,7 @@
 pub struct Image<'a> {
     handle: *mut ffi::liq_image,
     /// Holds row pointers for images with stride
-    _marker: marker::PhantomData<&'a [u8]>,
+    _marker: PhantomData<&'a [u8]>,
 }
 
 /// Palette inside.
@@ -50,6 +53,7 @@
 }
 
 impl Drop for Attributes {
+    #[inline]
     fn drop(&mut self) {
         unsafe {
             if !self.handle.is_null() {
@@ -60,6 +64,7 @@
 }
 
 impl<'a> Drop for Image<'a> {
+    #[inline]
     fn drop(&mut self) {
         unsafe {
             ffi::liq_image_destroy(&mut *self.handle);
@@ -68,6 +73,7 @@
 }
 
 impl Drop for QuantizationResult {
+    #[inline]
     fn drop(&mut self) {
         unsafe {
             ffi::liq_result_destroy(&mut *self.handle);
@@ -76,6 +82,7 @@
 }
 
 impl<'a> Drop for Histogram<'a> {
+    #[inline]
     fn drop(&mut self) {
         unsafe {
             ffi::liq_histogram_destroy(&mut *self.handle);
@@ -84,12 +91,14 @@
 }
 
 impl Clone for Attributes {
+    #[inline]
     fn clone(&self) -> Attributes {
         unsafe { Attributes { handle: ffi::liq_attr_copy(&*self.handle) } }
     }
 }
 
 impl Default for Attributes {
+    #[inline(always)]
     fn default() -> Attributes {
         Attributes::new()
     }
@@ -99,6 +108,8 @@
     /// New handle for library configuration
     ///
     /// See also `new_image()`
+    #[inline]
+    #[must_use]
     pub fn new() -> Self {
         let handle = unsafe { ffi::liq_attr_create() };
         assert!(!handle.is_null(), "SSE-capable CPU is required for this 
build.");
@@ -106,6 +117,7 @@
     }
 
     /// It's better to use `set_quality()`
+    #[inline]
     pub fn set_max_colors(&mut self, value: i32) -> liq_error {
         unsafe { ffi::liq_set_max_colors(&mut *self.handle, value) }
     }
@@ -113,11 +125,13 @@
     /// Number of least significant bits to ignore.
     ///
     /// Useful for generating palettes for VGA, 15-bit textures, or other 
retro platforms.
+    #[inline]
     pub fn set_min_posterization(&mut self, value: i32) -> liq_error {
         unsafe { ffi::liq_set_min_posterization(&mut *self.handle, value) }
     }
 
     /// Returns number of bits of precision truncated
+    #[inline]
     pub fn min_posterization(&mut self) -> i32 {
         unsafe { ffi::liq_get_min_posterization(&*self.handle) }
     }
@@ -127,11 +141,13 @@
     /// If minimum quality can't be met, quantization will fail.
     ///
     /// Default is min 0, max 100.
+    #[inline]
     pub fn set_quality(&mut self, min: u32, max: u32) -> liq_error {
         unsafe { ffi::liq_set_quality(&mut *self.handle, min as c_int, max as 
c_int) }
     }
 
     /// Reads values set with `set_quality`
+    #[inline]
     pub fn quality(&mut self) -> (u32, u32) {
         unsafe {
             (ffi::liq_get_min_quality(&*self.handle) as u32,
@@ -143,6 +159,7 @@
     ///
     /// Faster speeds generate images of lower quality, but may be useful
     /// for real-time generation of images.
+    #[inline]
     pub fn set_speed(&mut self, value: i32) -> liq_error {
         unsafe { ffi::liq_set_speed(&mut *self.handle, value) }
     }
@@ -150,16 +167,21 @@
     /// Move transparent color to the last entry in the palette
     ///
     /// This is less efficient for PNG, but required by some broken software
+    #[inline]
     pub fn set_last_index_transparent(&mut self, value: bool) {
         unsafe { ffi::liq_set_last_index_transparent(&mut *self.handle, value 
as c_int) }
     }
 
     /// Return currently set speed/quality trade-off setting
+    #[inline(always)]
+    #[must_use]
     pub fn speed(&mut self) -> i32 {
         unsafe { ffi::liq_get_speed(&*self.handle) }
     }
 
     /// Return max number of colors set
+    #[inline(always)]
+    #[must_use]
     pub fn max_colors(&mut self) -> i32 {
         unsafe { ffi::liq_get_max_colors(&*self.handle) }
     }
@@ -167,18 +189,28 @@
     /// Describe dimensions of a slice of RGBA pixels
     ///
     /// Use 0.0 for gamma if the image is sRGB (most images are).
-    pub fn new_image<'a, RGBA: Copy>(&self, bitmap: &'a [RGBA], width: usize, 
height: usize, gamma: f64) -> Result<Image<'a>, liq_error> {
+    #[inline]
+    pub fn new_image<'a>(&self, bitmap: &'a [RGBA], width: usize, height: 
usize, gamma: f64) -> Result<Image<'a>, liq_error> {
         Image::new(self, bitmap, width, height, gamma)
     }
 
     /// Stride is in pixels. Allows defining regions of larger images or 
images with padding without copying.
-    pub fn new_image_stride<'a, RGBA: Copy>(&self, bitmap: &'a [RGBA], width: 
usize, height: usize, stride: usize, gamma: f64) -> Result<Image<'a>, 
liq_error> {
+    #[inline]
+    pub fn new_image_stride<'a>(&self, bitmap: &'a [RGBA], width: usize, 
height: usize, stride: usize, gamma: f64) -> Result<Image<'a>, liq_error> {
         Image::new_stride(self, bitmap, width, height, stride, gamma)
     }
 
+    /// Like `new_image_stride`, but makes a copy of the pixels
+    #[inline]
+    pub fn new_image_stride_copy(&self, bitmap: &[RGBA], width: usize, height: 
usize, stride: usize, gamma: f64) -> Result<Image<'static>, liq_error> {
+        Image::new_stride_copy(self, bitmap, width, height, stride, gamma)
+    }
+
     /// Create new histogram
     ///
     /// Use to make one palette suitable for many images
+    #[inline(always)]
+    #[must_use]
     pub fn new_histogram(&self) -> Histogram<'_> {
         Histogram::new(&self)
     }
@@ -196,6 +228,8 @@
 }
 
 /// Start here: creates new handle for library configuration
+#[inline(always)]
+#[must_use]
 pub fn new() -> Attributes {
     Attributes::new()
 }
@@ -204,6 +238,8 @@
     /// Creates histogram object that will be used to collect color statistics 
from multiple images.
     ///
     /// All options should be set on `attr` before the histogram object is 
created. Options changed later may not have effect.
+    #[inline]
+    #[must_use]
     pub fn new(attr: &'a Attributes) -> Self {
         Histogram {
             attr,
@@ -214,6 +250,7 @@
     /// "Learns" colors from the image, which will be later used to generate 
the palette.
     ///
     /// Fixed colors added to the image are also added to the histogram. If 
total number of fixed colors exceeds 256, this function will fail with 
`LIQ_BUFFER_TOO_SMALL`.
+    #[inline]
     pub fn add_image(&mut self, image: &mut Image<'_>) -> liq_error {
         unsafe { ffi::liq_histogram_add_image(&mut *self.handle, 
&*self.attr.handle, &mut *image.handle) }
     }
@@ -221,6 +258,7 @@
     /// Alternative to `add_image()`. Intead of counting colors in an image, 
it directly takes an array of colors and their counts.
     ///
     /// This function is only useful if you already have a histogram of the 
image from another source.
+    #[inline]
     pub fn add_colors(&mut self, colors: &[HistogramEntry], gamma: f64) -> 
liq_error {
         unsafe {
             ffi::liq_histogram_add_colors(&mut *self.handle, 
&*self.attr.handle, colors.as_ptr(), colors.len() as c_int, gamma)
@@ -231,6 +269,7 @@
     ///
     /// Palette generated using this function won't be improved during 
remapping.
     /// If you're generating palette for only one image, it's better not to 
use the `Histogram`.
+    #[inline]
     pub fn quantize(&mut self) -> Result<QuantizationResult, liq_error> {
         unsafe {
             let mut h = ptr::null_mut();
@@ -255,8 +294,8 @@
     /// `bitmap` must be either `&[u8]` or a slice with one element per pixel 
(`&[RGBA]`).
     ///
     /// Use `0.` for gamma if the image is sRGB (most images are).
-    #[inline]
-    pub fn new<PixelType: Copy>(attr: &Attributes, bitmap: &'bitmap 
[PixelType], width: usize, height: usize, gamma: f64) -> Result<Self, 
liq_error> {
+    #[inline(always)]
+    pub fn new(attr: &Attributes, bitmap: &'bitmap [RGBA], width: usize, 
height: usize, gamma: f64) -> Result<Self, liq_error> {
         Self::new_stride(attr, bitmap, width, height, width, gamma)
     }
 
@@ -267,62 +306,85 @@
     ///
     /// The user data must be compatible with a primitive pointer
     /// (i.e. not a slice, not a Trait object. `Box` it if you must).
+    #[inline]
     pub fn new_unsafe_fn<CustomData: Send + Sync + 'bitmap>(attr: &Attributes, 
convert_row_fn: ConvertRowUnsafeFn<CustomData>, user_data: *mut CustomData, 
width: usize, height: usize, gamma: f64) -> Result<Self, liq_error> {
         unsafe {
-            match ffi::liq_image_create_custom(&*attr.handle, 
mem::transmute(convert_row_fn), user_data as *mut _, width as c_int, height as 
c_int, gamma) {
-                handle if !handle.is_null() => Ok(Image { handle, _marker: 
marker::PhantomData }),
+            match ffi::liq_image_create_custom(&*attr.handle, 
mem::transmute(convert_row_fn), user_data.cast(), width as c_int, height as 
c_int, gamma) {
+                handle if !handle.is_null() => Ok(Image { handle, _marker: 
PhantomData }),
                 _ => Err(LIQ_INVALID_POINTER),
             }
         }
     }
 
     /// Stride is in pixels. Allows defining regions of larger images or 
images with padding without copying.
-    pub fn new_stride<PixelType: Copy>(attr: &Attributes, bitmap: &'bitmap 
[PixelType], width: usize, height: usize, stride: usize, gamma: f64) -> 
Result<Self, liq_error> {
-        let bytes_per_pixel = mem::size_of::<PixelType>();
-        match bytes_per_pixel {
-            1 | 4 => {}
-            _ => return Err(LIQ_UNSUPPORTED),
-        }
-        if bitmap.len() * bytes_per_pixel < (stride * height + width - stride) 
* 4 {
-            eprintln!("Buffer length is {}??{} bytes, which is not enough for 
{}??{}??4 RGBA bytes", bitmap.len(), bytes_per_pixel, stride, height);
+    #[inline(always)]
+    pub fn new_stride(attr: &Attributes, bitmap: &'bitmap [RGBA], width: 
usize, height: usize, stride: usize, gamma: f64) -> Result<Self, liq_error> {
+        // Type definition preserves the lifetime, so it's not unsafe
+        unsafe { Self::new_stride_internal(attr, bitmap, width, height, 
stride, gamma, false) }
+    }
+
+    /// Create new image by copying `bitmap` to an internal buffer, so that it 
makes a self-contained type.
+    #[inline(always)]
+    pub fn new_stride_copy(attr: &Attributes, bitmap: &[RGBA], width: usize, 
height: usize, stride: usize, gamma: f64) -> Result<Image<'static>, liq_error> {
+        // copy guarantees the image doesn't reference the bitmap any more
+        unsafe { Self::new_stride_internal(attr, bitmap, width, height, 
stride, gamma, true) }
+    }
+
+    unsafe fn new_stride_internal<'varies>(attr: &Attributes, bitmap: &[RGBA], 
width: usize, height: usize, stride: usize, gamma: f64, copy: bool) -> 
Result<Image<'varies>, liq_error> {
+        if bitmap.len() < (stride * height + width - stride) {
+            eprintln!("Buffer length is {} bytes, which is not enough for 
{}??{}??4 RGBA bytes", bitmap.len()*4, stride, height);
             return Err(LIQ_BUFFER_TOO_SMALL);
         }
-        unsafe {
-            let rows = Self::malloc_image_rows(bitmap, stride, height, 
bytes_per_pixel);
-            match ffi::liq_image_create_rgba_rows(&*attr.handle, rows, width 
as c_int, height as c_int, gamma) {
-                h if !h.is_null() && ffi::liq_image_set_memory_ownership(&*h, 
ffi::liq_ownership::LIQ_OWN_ROWS).is_ok() => {
-                    Ok(Image {
-                        handle: h,
-                        _marker: marker::PhantomData,
-                    })
-                },
-                _ => {
-                    libc::free(rows as *mut _);
-                    Err(LIQ_INVALID_POINTER)
-                }
-            }
+        let (bitmap, ownership) = if copy {
+            let copied = libc::malloc(4 * bitmap.len()) as *mut RGBA;
+            ptr::copy_nonoverlapping(bitmap.as_ptr(), copied, bitmap.len());
+            (copied as *const _, ffi::liq_ownership::LIQ_OWN_ROWS | 
ffi::liq_ownership::LIQ_OWN_PIXELS)
+        } else {
+            (bitmap.as_ptr(), ffi::liq_ownership::LIQ_OWN_ROWS)
+        };
+        let rows = Self::malloc_image_rows(bitmap, stride, height);
+        let h = ffi::liq_image_create_rgba_rows(&*attr.handle, rows, width as 
c_int, height as c_int, gamma);
+        if h.is_null() {
+            libc::free(rows.cast());
+            return Err(LIQ_INVALID_POINTER);
+        }
+        let img = Image {
+            handle: h,
+            _marker: PhantomData,
+        };
+        match ffi::liq_image_set_memory_ownership(&*h, ownership) {
+            LIQ_OK => Ok(img),
+            err => {
+                drop(img);
+                libc::free(rows.cast());
+                Err(err)
+            },
         }
     }
 
     /// For arbitrary stride libimagequant requires rows. It's most convenient 
if they're allocated using libc,
     /// so they can be owned and freed automatically by the C library.
-    unsafe fn malloc_image_rows<PixelType: Copy>(bitmap: &'bitmap [PixelType], 
stride: usize, height: usize, bytes_per_pixel: usize) -> *mut *const u8 {
-        let mut byte_ptr = bitmap.as_ptr() as *const u8;
-        let stride_bytes = (stride * bytes_per_pixel) as isize;
+    unsafe fn malloc_image_rows(bitmap: *const RGBA, stride: usize, height: 
usize) -> *mut *const u8 {
+        let mut byte_ptr = bitmap as *const u8;
+        let stride_bytes = stride * 4;
         let rows = libc::malloc(mem::size_of::<*const u8>() * height) as *mut 
*const u8;
-        for y in 0..height as isize {
-            *rows.offset(y) = byte_ptr;
-            byte_ptr = byte_ptr.offset(stride_bytes);
+        for y in 0..height {
+            *rows.add(y) = byte_ptr;
+            byte_ptr = byte_ptr.add(stride_bytes);
         }
         rows
     }
 
     /// Width of the image in pixels
+    #[inline]
+    #[must_use]
     pub fn width(&self) -> usize {
         unsafe { ffi::liq_image_get_width(&*self.handle) as usize }
     }
 
     /// Height of the image in pixels
+    #[inline]
+    #[must_use]
     pub fn height(&self) -> usize {
         unsafe { ffi::liq_image_get_height(&*self.handle) as usize }
     }
@@ -334,10 +396,9 @@
     /// 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.
+    #[inline]
     pub fn add_fixed_color(&mut self, color: ffi::liq_color) -> liq_error {
-        unsafe {
-            ffi::liq_image_add_fixed_color(&mut *self.handle, color)
-        }
+        unsafe { ffi::liq_image_add_fixed_color(&mut *self.handle, color) }
     }
 
     /// Remap pixels assuming they will be displayed on this background.
@@ -345,6 +406,7 @@
     /// Pixels that match the background color will be made transparent if 
there's a fully transparent color available in the palette.
     ///
     /// The background image's pixels must outlive this image
+    #[inline]
     pub fn set_background<'own, 'bg: 'own>(&'own mut self, background: 
Image<'bg>) -> Result<(), liq_error> {
         unsafe {
             ffi::liq_image_set_background(&mut *self.handle, 
background.into_raw()).ok()
@@ -354,12 +416,14 @@
     /// Set which pixels are more important (and more likely to get a palette 
entry)
     ///
     /// The map must be `width`??`height` pixels large. Higher numbers = more 
important.
+    #[inline]
     pub fn set_importance_map(&mut self, map: &[u8]) -> Result<(), liq_error> {
         unsafe {
             ffi::liq_image_set_importance_map(&mut *self.handle, map.as_ptr() 
as *mut _, map.len(), ffi::liq_ownership::LIQ_COPY_PIXELS).ok()
         }
     }
 
+    #[inline]
     fn into_raw(mut self) -> *mut ffi::liq_image {
         let handle = self.handle;
         self.handle = ptr::null_mut();
@@ -369,11 +433,13 @@
 
 impl QuantizationResult {
     /// Set to 1.0 to get nice smooth image
+    #[inline]
     pub fn set_dithering_level(&mut self, value: f32) -> liq_error {
         unsafe { ffi::liq_set_dithering_level(&mut *self.handle, value) }
     }
 
     /// The default is sRGB gamma (~1/2.2)
+    #[inline]
     pub fn set_output_gamma(&mut self, value: f64) -> liq_error {
         unsafe { ffi::liq_set_output_gamma(&mut *self.handle, value) }
     }
@@ -381,16 +447,22 @@
     /// Approximate gamma correction value used for the output
     ///
     /// Colors are converted from input gamma to this gamma
+    #[inline]
+    #[must_use]
     pub fn output_gamma(&mut self) -> f64 {
         unsafe { ffi::liq_get_output_gamma(&*self.handle) }
     }
 
     /// Number 0-100 guessing how nice the input image will look if remapped 
to this palette
+    #[inline]
+    #[must_use]
     pub fn quantization_quality(&self) -> i32 {
         unsafe { ffi::liq_get_quantization_quality(&*self.handle) as i32 }
     }
 
     /// Approximate mean square error of the palette
+    #[inline]
+    #[must_use]
     pub fn quantization_error(&self) -> Option<f64> {
         match unsafe { ffi::liq_get_quantization_error(&*self.handle) } {
             x if x < 0. => None,
@@ -401,23 +473,52 @@
     /// Final palette
     ///
     /// It's slighly better if you get palette from the `remapped()` call 
instead
+    #[must_use]
     pub fn palette(&mut self) -> Vec<Color> {
+        self.palette_ref().to_vec()
+    }
+
+    /// Final palette (as a temporary slice)
+    ///
+    /// It's slighly better if you get palette from the `remapped()` call 
instead
+    ///
+    /// Use when ownership of the palette colors is not needed
+    #[inline]
+    pub fn palette_ref(&mut self) -> &[Color] {
         unsafe {
             let pal = &*ffi::liq_get_palette(&mut *self.handle);
-            pal.entries.iter().cloned().take(pal.count as usize).collect()
+            std::slice::from_raw_parts(pal.entries.as_ptr(), (pal.count as 
usize).min(pal.entries.len()))
         }
     }
 
-    /// Remap image
+    /// Remap image into a `Vec`
     ///
-    /// Returns palette and 1-byte-per-pixel uncompresed bitmap
+    /// Returns the palette and a 1-byte-per-pixel uncompressed bitmap
     pub fn remapped(&mut self, image: &mut Image<'_>) -> Result<(Vec<Color>, 
Vec<u8>), liq_error> {
         let len = image.width() * image.height();
+        // Capacity is essential here, as it creates uninitialized buffer
         let mut buf = Vec::with_capacity(len);
         unsafe {
-            buf.set_len(len); // Creates uninitialized buffer
-            match ffi::liq_write_remapped_image(&mut *self.handle, &mut 
*image.handle, buf.as_mut_ptr(), buf.len()) {
-                LIQ_OK => Ok((self.palette(), buf)),
+            let uninit_slice = std::slice::from_raw_parts_mut(buf.as_ptr() as 
*mut _, buf.capacity());
+            self.remap_into(image, uninit_slice)?;
+            buf.set_len(uninit_slice.len());
+        }
+        Ok((self.palette(), buf))
+    }
+
+    /// Remap image into an existing buffer.
+    ///
+    /// This is a low-level call for use when existing memory has to be 
reused. Use `remapped()` if possible.
+    ///
+    /// Writes 1-byte-per-pixel uncompressed bitmap into the pre-allocated 
buffer.
+    ///
+    /// You should call `palette()` or `palette_ref()` _after_ this call, but 
not before it,
+    /// because remapping changes the palette.
+    #[inline]
+    pub fn remap_into(&mut self, image: &mut Image<'_>, output_buf: &mut 
[MaybeUninit<u8>]) -> Result<(), liq_error> {
+        unsafe {
+            match ffi::liq_write_remapped_image(&mut *self.handle, &mut 
*image.handle, output_buf.as_mut_ptr().cast(), output_buf.len()) {
+                LIQ_OK => Ok(()),
                 err => Err(err),
             }
         }
@@ -425,6 +526,7 @@
 }
 
 impl fmt::Debug for QuantizationResult {
+    #[cold]
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "QuantizationResult(q={})", self.quantization_quality())
     }
@@ -436,12 +538,17 @@
 unsafe impl<'a> Send for Histogram<'a> {}
 
 #[test]
+fn copy_img() {
+    let tmp = vec![RGBA::new(1,2,3,4); 10*100];
+    let liq = Attributes::new();
+    let _ = liq.new_image_stride_copy(&tmp, 10, 100, 10, 0.).unwrap();
+}
+
+#[test]
 fn takes_rgba() {
     let liq = Attributes::new();
 
-    #[allow(dead_code)]
-    #[derive(Copy, Clone)]
-    struct RGBA {r:u8, g:u8, b:u8, a:u8};
+    use rgb::RGBA8 as RGBA;
     let img = vec![RGBA {r:0, g:0, b:0, a:0}; 8];
 
 
@@ -450,13 +557,6 @@
     liq.new_image(&img, 8, 1, 0.0).unwrap();
     assert!(liq.new_image(&img, 9, 1, 0.0).is_err());
     assert!(liq.new_image(&img, 4, 3, 0.0).is_err());
-
-    #[allow(dead_code)]
-    #[derive(Copy, Clone)]
-    struct RGB {r:u8, g:u8, b:u8};
-    let badimg = vec![RGB {r:0, g:0, b:0}; 8];
-    assert!(liq.new_image(&badimg, 1, 1, 0.0).is_err());
-    assert!(liq.new_image(&badimg, 100, 100, 0.0).is_err());
 }
 
 #[test]
@@ -464,11 +564,11 @@
     let attr = Attributes::new();
     let mut hist = attr.new_histogram();
 
-    let bitmap1 = vec![0u8; 4];
+    let bitmap1 = vec![RGBA {r:0, g:0, b:0, a:0}; 1];
     let mut image1 = attr.new_image(&bitmap1[..], 1, 1, 0.0).unwrap();
     hist.add_image(&mut image1);
 
-    let bitmap2 = vec![255u8; 4];
+    let bitmap2 = vec![RGBA {r:255, g:255, b:255, a:255}; 1];
     let mut image2 = attr.new_image(&bitmap2[..], 1, 1, 0.0).unwrap();
     hist.add_image(&mut image2);
 
@@ -486,11 +586,11 @@
 fn poke_it() {
     let width = 10usize;
     let height = 10usize;
-    let mut fakebitmap = vec![255u8; 4*width*height];
+    let mut fakebitmap = vec![RGBA::new(255,255,255,255); width*height];
 
-    fakebitmap[0] = 0x55;
-    fakebitmap[1] = 0x66;
-    fakebitmap[2] = 0x77;
+    fakebitmap[0].r = 0x55;
+    fakebitmap[0].g = 0x66;
+    fakebitmap[0].b = 0x77;
 
     // Configure the library
     let mut liq = Attributes::new();
@@ -539,7 +639,7 @@
 fn thread() {
     let liq = Attributes::new();
     std::thread::spawn(move || {
-        let b = vec![0u8;4];
+        let b = vec![RGBA::new(0,0,0,0);1];
         liq.new_image(&b, 1, 1, 0.).unwrap();
     }).join().unwrap();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/rust-sys/build.rs 
new/libimagequant-2.14.1/rust-sys/build.rs
--- old/libimagequant-2.13.1/rust-sys/build.rs  2020-11-22 14:18:54.000000000 
+0100
+++ new/libimagequant-2.14.1/rust-sys/build.rs  2021-02-28 19:12:44.000000000 
+0100
@@ -19,7 +19,8 @@
     }
 
     if cfg!(feature = "openmp") {
-        cc.flag(&env::var("DEP_OPENMP_FLAG").unwrap());
+        env::var("DEP_OPENMP_FLAG").expect("openmp-sys failed")
+            .split(" ").for_each(|f| { cc.flag(f); });
     }
 
     let target_arch = env::var("CARGO_CFG_TARGET_ARCH").expect("Needs 
CARGO_CFG_TARGET_ARCH");
@@ -60,4 +61,12 @@
     }
 
     cc.compile("libimagequant.a");
+
+    if cfg!(feature = "openmp") {
+        if let Some(link) = env::var_os("DEP_OPENMP_CARGO_LINK_INSTRUCTIONS") {
+            for i in env::split_paths(&link) {
+                println!("cargo:{}", i.display());
+            }
+        }
+    }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/libimagequant-2.13.1/rust-sys/libimagequant.rs 
new/libimagequant-2.14.1/rust-sys/libimagequant.rs
--- old/libimagequant-2.13.1/rust-sys/libimagequant.rs  2020-11-22 
14:18:54.000000000 +0100
+++ new/libimagequant-2.14.1/rust-sys/libimagequant.rs  2021-02-28 
19:12:44.000000000 +0100
@@ -60,12 +60,16 @@
     LIQ_UNSUPPORTED,
 }
 
-#[repr(C)]
-#[derive(Copy, Clone)]
-pub enum liq_ownership {
-    LIQ_OWN_ROWS = 4,
-    LIQ_OWN_PIXELS = 8,
-    LIQ_COPY_PIXELS = 16,
+bitflags::bitflags! {
+    #[repr(C)]
+    pub struct liq_ownership: c_int {
+        /// Moves ownership of the rows array. It will free it using `free()` 
or custom allocator.
+        const LIQ_OWN_ROWS = 4;
+        /// Moves ownership of the pixel data. It will free it using `free()` 
or custom allocator.
+        const LIQ_OWN_PIXELS = 8;
+        /// Makes a copy of the pixels, so the `liq_image` is not tied to 
pixel's lifetime.
+        const LIQ_COPY_PIXELS = 16;
+    }
 }
 
 #[repr(C)]
@@ -286,6 +290,11 @@
 }
 
 #[test]
+fn ownership_bitflags() {
+    assert_eq!(4+16, (liq_ownership::LIQ_OWN_ROWS | 
liq_ownership::LIQ_COPY_PIXELS).bits());
+}
+
+#[test]
 fn links_and_runs() {
     use std::ptr;
     unsafe {

Reply via email to