Compare commits
	
		
			6 Commits
		
	
	
		
			v2.12.2-go
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bdcc2f09a6 | |||
| 5971f07878 | |||
| 28784d66f3 | |||
| e6b7d94a14 | |||
| 4b569d0798 | |||
| 1c8bc73943 | 
							
								
								
									
										15
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								README.md
									
									
									
									
									
								
							@@ -6,8 +6,6 @@ Go bindings for libimagequant
 | 
			
		||||
 | 
			
		||||
This binding was written by hand. The result is somewhat more idiomatic than an automated conversion, but some `defer foo.Release()` calls are required for memory management.
 | 
			
		||||
 | 
			
		||||
Written in Golang
 | 
			
		||||
 | 
			
		||||
## Usage
 | 
			
		||||
 | 
			
		||||
Usage example is provided by a sample utility `cmd/gopngquant` which mimics some functionality of the upstream `pngquant`.
 | 
			
		||||
@@ -28,13 +26,12 @@ Usage of gopngquant:
 | 
			
		||||
## Building
 | 
			
		||||
 | 
			
		||||
This package can be installed via go get: `go get code.ivysaur.me/imagequant`
 | 
			
		||||
[go-get]code.ivysaur.me/imagequant git https://git.ivysaur.me/code.ivysaur.me/imagequant.git[/go-get]
 | 
			
		||||
 | 
			
		||||
The expected package path is `code.ivysaur.me/imagequant`. Build via `go build`.
 | 
			
		||||
Import the package as `code.ivysaur.me/imagequant/v2` and compile via `go build`.
 | 
			
		||||
 | 
			
		||||
This is a CGO package and requires a C compiler installed. However, if you use `go install` then future invocations of `go build` do not require the C compiler to be present.
 | 
			
		||||
 | 
			
		||||
The `imagequant.go` file also declares a number of `CFLAGS` for GCC that allow the included libimagequant (2.8 git-a425e83) to build in an optimal way without using the upstream configure/make scripts.
 | 
			
		||||
The `imagequant.go` file also declares a number of `CFLAGS` for GCC that allow the included libimagequant to build in a reasonably optimal way without using the upstream configure/make scripts.
 | 
			
		||||
 | 
			
		||||
## License
 | 
			
		||||
 | 
			
		||||
@@ -42,6 +39,10 @@ I am releasing this binding under the ISC license, however, `libimagequant` itse
 | 
			
		||||
 | 
			
		||||
## Changelog
 | 
			
		||||
 | 
			
		||||
2020-07-25 v2.12.6
 | 
			
		||||
- Update bundled libimagequant from 2.12.2 to 2.12.6
 | 
			
		||||
- Fix missing v2 in go.mod file causing failure to import in Modules mode
 | 
			
		||||
 | 
			
		||||
2018-12-31 v2.12.2-go1.2
 | 
			
		||||
- go-imagequant: Update bundled libimagequant from 2.9.0 to 2.12.2
 | 
			
		||||
- build: Switch to Go Modules
 | 
			
		||||
@@ -53,10 +54,14 @@ I am releasing this binding under the ISC license, however, `libimagequant` itse
 | 
			
		||||
- go-imagequant: Update bundled libimagequant from 2.8.0 to 2.9.0
 | 
			
		||||
- go-imagequant: Separate `CGO_LDFLAGS` for Linux and Windows targets
 | 
			
		||||
- gopngquant: Fix an issue with non-square images
 | 
			
		||||
- [⬇️ go-imagequant-2.9go1.1-src.zip](https://git.ivysaur.me/attachments/381bbeac-c50f-4235-b61a-54785cf49b11) *(56.13 KiB)*
 | 
			
		||||
- [⬇️ gopngquant-2.9go1.1-win64.7z](https://git.ivysaur.me/attachments/ced44b97-4666-43cc-a578-44f4272be686) *(497.54 KiB)*
 | 
			
		||||
 | 
			
		||||
2016-11-24 v2.8.0-go1.0
 | 
			
		||||
- *Previously tagged as 2.8go1.0*
 | 
			
		||||
- Initial public release
 | 
			
		||||
- [⬇️ go-imagequant-2.8go1.0-src.zip](https://git.ivysaur.me/attachments/0f45207f-aeb8-4dd7-a62c-499a3f378f1a) *(55.40 KiB)*
 | 
			
		||||
- [⬇️ gopngquant-2.8go1.0-win64.7z](https://git.ivysaur.me/attachments/46229661-fa5d-418d-92ff-d6c4f72a5204) *(497.98 KiB)*
 | 
			
		||||
 | 
			
		||||
## See also
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										4
									
								
								blur.h
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								blur.h
									
									
									
									
									
								
							@@ -1,4 +1,8 @@
 | 
			
		||||
#ifndef BLUR_H
 | 
			
		||||
#define BLUR_H
 | 
			
		||||
 | 
			
		||||
LIQ_PRIVATE void liq_blur(unsigned char *src, unsigned char *tmp, unsigned char *dst, unsigned int width, unsigned int height, unsigned int size);
 | 
			
		||||
LIQ_PRIVATE void liq_max3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height);
 | 
			
		||||
LIQ_PRIVATE void liq_min3(unsigned char *src, unsigned char *dst, unsigned int width, unsigned int height);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ import (
 | 
			
		||||
	"image/png"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"code.ivysaur.me/imagequant"
 | 
			
		||||
	"code.ivysaur.me/imagequant/v2"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func GoImageToRgba32(im image.Image) []byte {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								doc/sample.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								doc/sample.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 12 KiB  | 
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@@ -1 +1,3 @@
 | 
			
		||||
module code.ivysaur.me/imagequant
 | 
			
		||||
module code.ivysaur.me/imagequant/v2
 | 
			
		||||
 | 
			
		||||
go 1.13
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										5
									
								
								kmeans.c
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								kmeans.c
									
									
									
									
									
								
							@@ -73,8 +73,13 @@ LIQ_PRIVATE double kmeans_do_iteration(histogram *hist, colormap *const map, kme
 | 
			
		||||
    const int hist_size = hist->size;
 | 
			
		||||
 | 
			
		||||
    double total_diff=0;
 | 
			
		||||
#if __GNUC__ >= 9
 | 
			
		||||
    #pragma omp parallel for if (hist_size > 2000) \
 | 
			
		||||
        schedule(static) default(none) shared(achv,average_color,callback,hist_size,map,n) reduction(+:total_diff)
 | 
			
		||||
#else
 | 
			
		||||
    #pragma omp parallel for if (hist_size > 2000) \
 | 
			
		||||
        schedule(static) default(none) shared(average_color,callback) reduction(+:total_diff)
 | 
			
		||||
#endif
 | 
			
		||||
    for(int j=0; j < hist_size; j++) {
 | 
			
		||||
        float diff;
 | 
			
		||||
        unsigned int match = nearest_search(n, &achv[j].acolor, achv[j].tmp.likely_colormap_index, &diff);
 | 
			
		||||
 
 | 
			
		||||
@@ -566,7 +566,7 @@ LIQ_NONNULL static bool liq_image_use_low_memory(liq_image *img)
 | 
			
		||||
 | 
			
		||||
LIQ_NONNULL static bool liq_image_should_use_low_memory(liq_image *img, const bool low_memory_hint)
 | 
			
		||||
{
 | 
			
		||||
    return img->width * img->height > (low_memory_hint ? LIQ_HIGH_MEMORY_LIMIT/8 : LIQ_HIGH_MEMORY_LIMIT) / sizeof(f_pixel); // Watch out for integer overflow
 | 
			
		||||
    return (size_t)img->width * (size_t)img->height > (low_memory_hint ? LIQ_HIGH_MEMORY_LIMIT/8 : LIQ_HIGH_MEMORY_LIMIT) / sizeof(f_pixel); // Watch out for integer overflow
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static liq_image *liq_image_create_internal(const liq_attr *attr, rgba_pixel* rows[], liq_image_get_rgba_row_callback *row_callback, void *row_callback_user_info, int width, int height, double gamma)
 | 
			
		||||
@@ -647,7 +647,7 @@ LIQ_EXPORT LIQ_NONNULL liq_error liq_image_set_importance_map(liq_image *img, un
 | 
			
		||||
    if (!CHECK_STRUCT_TYPE(img, liq_image)) return LIQ_INVALID_POINTER;
 | 
			
		||||
    if (!CHECK_USER_POINTER(importance_map)) return LIQ_INVALID_POINTER;
 | 
			
		||||
 | 
			
		||||
    const size_t required_size = img->width * img->height;
 | 
			
		||||
    const size_t required_size = (size_t)img->width * (size_t)img->height;
 | 
			
		||||
    if (buffer_size < required_size) {
 | 
			
		||||
        return LIQ_BUFFER_TOO_SMALL;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1030,7 +1030,7 @@ LIQ_EXPORT LIQ_NONNULL liq_error liq_set_dithering_level(liq_result *res, float
 | 
			
		||||
        res->remapping = NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (res->dither_level < 0 || res->dither_level > 1.0f) return LIQ_VALUE_OUT_OF_RANGE;
 | 
			
		||||
    if (dither_level < 0 || dither_level > 1.0f) return LIQ_VALUE_OUT_OF_RANGE;
 | 
			
		||||
    res->dither_level = dither_level;
 | 
			
		||||
    return LIQ_OK;
 | 
			
		||||
}
 | 
			
		||||
@@ -1276,8 +1276,13 @@ LIQ_NONNULL static float remap_to_palette(liq_image *const input_image, unsigned
 | 
			
		||||
    LIQ_ARRAY(kmeans_state, average_color, (KMEANS_CACHE_LINE_GAP+map->colors) * max_threads);
 | 
			
		||||
    kmeans_init(map, max_threads, average_color);
 | 
			
		||||
 | 
			
		||||
#if __GNUC__ >= 9
 | 
			
		||||
    #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)
 | 
			
		||||
#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;
 | 
			
		||||
@@ -2078,7 +2083,7 @@ LIQ_EXPORT LIQ_NONNULL liq_error liq_write_remapped_image(liq_result *result, li
 | 
			
		||||
        return LIQ_INVALID_POINTER;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const size_t required_size = input_image->width * input_image->height;
 | 
			
		||||
    const size_t required_size = (size_t)input_image->width * (size_t)input_image->height;
 | 
			
		||||
    if (buffer_size < required_size) {
 | 
			
		||||
        return LIQ_BUFFER_TOO_SMALL;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,8 @@
 | 
			
		||||
#define LIQ_EXPORT extern
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define LIQ_VERSION 21200
 | 
			
		||||
#define LIQ_VERSION_STRING "2.12.2"
 | 
			
		||||
#define LIQ_VERSION 21206
 | 
			
		||||
#define LIQ_VERSION_STRING "2.12.6"
 | 
			
		||||
 | 
			
		||||
#ifndef LIQ_PRIVATE
 | 
			
		||||
#if defined(__GNUC__) || defined (__llvm__)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										21
									
								
								mediancut.c
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								mediancut.c
									
									
									
									
									
								
							@@ -195,8 +195,13 @@ static double prepare_sort(struct box *b, hist_item achv[])
 | 
			
		||||
 | 
			
		||||
    const unsigned int ind1 = b->ind;
 | 
			
		||||
    const unsigned int colors = b->colors;
 | 
			
		||||
#if __GNUC__ >= 9
 | 
			
		||||
    #pragma omp parallel for if (colors > 25000) \
 | 
			
		||||
        schedule(static) default(none) shared(achv, channels, colors, ind1)
 | 
			
		||||
#else
 | 
			
		||||
    #pragma omp parallel for if (colors > 25000) \
 | 
			
		||||
        schedule(static) default(none) shared(achv, channels)
 | 
			
		||||
#endif
 | 
			
		||||
    for(unsigned int i=0; i < colors; i++) {
 | 
			
		||||
        const float *chans = (const float *)&achv[ind1 + i].acolor;
 | 
			
		||||
        // Only the first channel really matters. When trying median cut many times
 | 
			
		||||
@@ -311,9 +316,7 @@ static void box_init(struct box *box, const hist_item *achv, const unsigned int
 | 
			
		||||
    box->total_error = -1;
 | 
			
		||||
 | 
			
		||||
    box->color = averagepixels(colors, &achv[ind]);
 | 
			
		||||
    #pragma omp task if (colors > 5000)
 | 
			
		||||
    box->variance = box_variance(achv, box);
 | 
			
		||||
    #pragma omp task if (colors > 8000)
 | 
			
		||||
    box->max_error = box_max_error(achv, box);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -331,17 +334,12 @@ LIQ_PRIVATE colormap *mediancut(histogram *hist, unsigned int newcolors, const d
 | 
			
		||||
    /*
 | 
			
		||||
     ** Set up the initial box.
 | 
			
		||||
     */
 | 
			
		||||
    #pragma omp parallel
 | 
			
		||||
    #pragma omp single
 | 
			
		||||
    {
 | 
			
		||||
        double sum = 0;
 | 
			
		||||
        for(unsigned int i=0; i < hist->size; i++) {
 | 
			
		||||
            sum += achv[i].adjusted_weight;
 | 
			
		||||
        }
 | 
			
		||||
        #pragma omp taskgroup
 | 
			
		||||
        {
 | 
			
		||||
            box_init(&bv[0], achv, 0, hist->size, sum);
 | 
			
		||||
        }
 | 
			
		||||
        box_init(&bv[0], achv, 0, hist->size, sum);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /*
 | 
			
		||||
@@ -386,11 +384,8 @@ LIQ_PRIVATE colormap *mediancut(histogram *hist, unsigned int newcolors, const d
 | 
			
		||||
            double lowersum = 0;
 | 
			
		||||
            for(unsigned int i=0; i < break_at; i++) lowersum += achv[indx + i].adjusted_weight;
 | 
			
		||||
 | 
			
		||||
            #pragma omp taskgroup
 | 
			
		||||
            {
 | 
			
		||||
                box_init(&bv[bi], achv, indx, break_at, lowersum);
 | 
			
		||||
                box_init(&bv[boxes], achv, indx + break_at, clrs - break_at, sm - lowersum);
 | 
			
		||||
            }
 | 
			
		||||
            box_init(&bv[bi], achv, indx, break_at, lowersum);
 | 
			
		||||
            box_init(&bv[boxes], achv, indx + break_at, clrs - break_at, sm - lowersum);
 | 
			
		||||
 | 
			
		||||
            ++boxes;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,2 +1,6 @@
 | 
			
		||||
#ifndef MEDIANCUT_H
 | 
			
		||||
#define MEDIANCUT_H
 | 
			
		||||
 | 
			
		||||
LIQ_PRIVATE colormap *mediancut(histogram *hist, unsigned int newcolors, const double target_mse, const double max_mse, void* (*malloc)(size_t), void (*free)(void*));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,13 @@
 | 
			
		||||
//  nearest.h
 | 
			
		||||
//  pngquant
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#ifndef NEAREST_H
 | 
			
		||||
#define NEAREST_H
 | 
			
		||||
 | 
			
		||||
struct nearest_map;
 | 
			
		||||
LIQ_PRIVATE struct nearest_map *nearest_init(const colormap *palette);
 | 
			
		||||
LIQ_PRIVATE unsigned int nearest_search(const struct nearest_map *map, const f_pixel *px, const int palette_index_guess, float *diff);
 | 
			
		||||
LIQ_PRIVATE void nearest_free(struct nearest_map *map);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								pam.c
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								pam.c
									
									
									
									
									
								
							@@ -225,6 +225,9 @@ LIQ_PRIVATE histogram *pam_acolorhashtoacolorhist(const struct acolorhash_table
 | 
			
		||||
    }
 | 
			
		||||
    hist->size = j;
 | 
			
		||||
    hist->total_perceptual_weight = total_weight;
 | 
			
		||||
    for(unsigned int k=0; k < hist->size; k++) {
 | 
			
		||||
        hist->achv[k].tmp.likely_colormap_index = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (!j) {
 | 
			
		||||
        pam_freeacolorhist(hist);
 | 
			
		||||
        return NULL;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								pam.h
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								pam.h
									
									
									
									
									
								
							@@ -16,6 +16,12 @@
 | 
			
		||||
#ifndef PAM_H
 | 
			
		||||
#define PAM_H
 | 
			
		||||
 | 
			
		||||
// accidental debug assertions make color search much slower,
 | 
			
		||||
// so force assertions off if there's no explicit setting
 | 
			
		||||
#if !defined(NDEBUG) && !defined(DEBUG)
 | 
			
		||||
#define NDEBUG
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <math.h>
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user