1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-02-02 11:34:20 +02:00

PNG quantization

This commit is contained in:
DarthSim 2019-04-05 16:30:16 +06:00
parent e99241aea0
commit 4ba970bdf6
6 changed files with 46 additions and 13 deletions

View File

@ -11,7 +11,7 @@ WORKDIR /go/src/github.com/DarthSim/imgproxy
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk --no-cache upgrade \ && apk --no-cache upgrade \
&& apk add --no-cache curl ca-certificates go gcc g++ make musl-dev fftw-dev glib-dev expat-dev \ && apk add --no-cache curl ca-certificates go gcc g++ make musl-dev fftw-dev glib-dev expat-dev \
libjpeg-turbo-dev libpng-dev libwebp-dev giflib-dev librsvg-dev libexif-dev lcms2-dev libjpeg-turbo-dev libpng-dev libwebp-dev giflib-dev librsvg-dev libexif-dev lcms2-dev libimagequant-dev
# Build ImageMagick # Build ImageMagick
RUN cd /root \ RUN cd /root \
@ -76,7 +76,7 @@ LABEL maintainer="Sergey Alexandrovich <darthsim@gmail.com>"
RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \ RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk --no-cache upgrade \ && apk --no-cache upgrade \
&& apk add --no-cache bash ca-certificates fftw glib expat libjpeg-turbo libpng \ && apk add --no-cache bash ca-certificates fftw glib expat libjpeg-turbo libpng \
libwebp giflib librsvg libgsf libexif lcms2 \ libwebp giflib librsvg libgsf libexif lcms2 libimagequant\
&& rm -rf /var/cache/apk* && rm -rf /var/cache/apk*
COPY --from=0 /usr/local/bin/imgproxy /usr/local/bin/ COPY --from=0 /usr/local/bin/imgproxy /usr/local/bin/

View File

@ -143,10 +143,12 @@ type config struct {
MaxSrcFileSize int MaxSrcFileSize int
MaxGifFrames int MaxGifFrames int
JpegProgressive bool JpegProgressive bool
PngInterlaced bool PngInterlaced bool
Quality int PngQuantize bool
GZipCompression int PngQuantizationColors int
Quality int
GZipCompression int
EnableWebpDetection bool EnableWebpDetection bool
EnforceWebp bool EnforceWebp bool
@ -215,6 +217,7 @@ var conf = config{
MaxGifFrames: 1, MaxGifFrames: 1,
AllowInsecure: false, AllowInsecure: false,
SignatureSize: 32, SignatureSize: 32,
PngQuantizationColors: 256,
Quality: 80, Quality: 80,
GZipCompression: 5, GZipCompression: 5,
UserAgent: fmt.Sprintf("imgproxy/%s", version), UserAgent: fmt.Sprintf("imgproxy/%s", version),
@ -263,6 +266,8 @@ func init() {
boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE") boolEnvConfig(&conf.JpegProgressive, "IMGPROXY_JPEG_PROGRESSIVE")
boolEnvConfig(&conf.PngInterlaced, "IMGPROXY_PNG_INTERLACED") boolEnvConfig(&conf.PngInterlaced, "IMGPROXY_PNG_INTERLACED")
boolEnvConfig(&conf.PngQuantize, "IMGPROXY_PNG_QUANTIZE")
intEnvConfig(&conf.PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS")
intEnvConfig(&conf.Quality, "IMGPROXY_QUALITY") intEnvConfig(&conf.Quality, "IMGPROXY_QUALITY")
intEnvConfig(&conf.GZipCompression, "IMGPROXY_GZIP_COMPRESSION") intEnvConfig(&conf.GZipCompression, "IMGPROXY_GZIP_COMPRESSION")
@ -388,6 +393,12 @@ func init() {
logFatal("Max GIF frames should be greater than 0, now - %d\n", conf.MaxGifFrames) logFatal("Max GIF frames should be greater than 0, now - %d\n", conf.MaxGifFrames)
} }
if conf.PngQuantizationColors < 2 {
logFatal("Png quantization colors should be greater than 1, now - %d\n", conf.PngQuantizationColors)
} else if conf.PngQuantizationColors > 256 {
logFatal("Png quantization colors can't be greater than 256, now - %d\n", conf.PngQuantizationColors)
}
if conf.Quality <= 0 { if conf.Quality <= 0 {
logFatal("Quality should be greater than 0, now - %d\n", conf.Quality) logFatal("Quality should be greater than 0, now - %d\n", conf.Quality)
} else if conf.Quality > 100 { } else if conf.Quality > 100 {

View File

@ -67,6 +67,8 @@ When you use imgproxy in a development environment, it can be useful to ignore S
* `IMGPROXY_GZIP_COMPRESSION`: GZip compression level. Default: `5`; * `IMGPROXY_GZIP_COMPRESSION`: GZip compression level. Default: `5`;
* `IMGPROXY_JPEG_PROGRESSIVE` : when true, enables progressive JPEG compression. Default: false; * `IMGPROXY_JPEG_PROGRESSIVE` : when true, enables progressive JPEG compression. Default: false;
* `IMGPROXY_PNG_INTERLACED`: when true, enables interlaced PNG compression. Default: false; * `IMGPROXY_PNG_INTERLACED`: when true, enables interlaced PNG compression. Default: false;
* `IMGPROXY_PNG_QUANTIZE`: when true, enables PNG quantization. libvips should be built with libimagequant support. Default: false;
* `IMGPROXY_PNG_QUANTIZATION_COLORS`: maximum number of quantization palette entries. Should be between 2 and 256. Default: 256;
## WebP support detection ## WebP support detection

View File

@ -31,9 +31,11 @@ var (
) )
type cConfig struct { type cConfig struct {
JpegProgressive C.int JpegProgressive C.int
PngInterlaced C.int PngInterlaced C.int
WatermarkOpacity C.double PngQuantize C.int
PngQuantizationColors C.int
WatermarkOpacity C.double
} }
var cConf cConfig var cConf cConfig
@ -109,6 +111,12 @@ func initVips() {
cConf.PngInterlaced = C.int(1) cConf.PngInterlaced = C.int(1)
} }
if conf.PngQuantize {
cConf.PngQuantize = C.int(1)
}
cConf.PngQuantizationColors = C.int(conf.PngQuantizationColors)
cConf.WatermarkOpacity = C.double(conf.WatermarkOpacity) cConf.WatermarkOpacity = C.double(conf.WatermarkOpacity)
if err := vipsPrepareWatermark(); err != nil { if err := vipsPrepareWatermark(); err != nil {
@ -667,7 +675,7 @@ func vipsSaveImage(img *C.VipsImage, imgtype imageType, quality int) ([]byte, co
case imageTypeJPEG: case imageTypeJPEG:
err = C.vips_jpegsave_go(img, &ptr, &imgsize, C.int(quality), cConf.JpegProgressive) err = C.vips_jpegsave_go(img, &ptr, &imgsize, C.int(quality), cConf.JpegProgressive)
case imageTypePNG: case imageTypePNG:
err = C.vips_pngsave_go(img, &ptr, &imgsize, cConf.PngInterlaced) err = C.vips_pngsave_go(img, &ptr, &imgsize, cConf.PngInterlaced, cConf.PngQuantize, cConf.PngQuantizationColors)
case imageTypeWEBP: case imageTypeWEBP:
err = C.vips_webpsave_go(img, &ptr, &imgsize, C.int(quality)) err = C.vips_webpsave_go(img, &ptr, &imgsize, C.int(quality))
case imageTypeGIF: case imageTypeGIF:

16
vips.c
View File

@ -15,6 +15,9 @@
#define VIPS_SUPPORT_MAGICK \ #define VIPS_SUPPORT_MAGICK \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7)) (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7))
#define VIPS_SUPPORT_PNG_QUANTIZATION \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7))
#define EXIF_ORIENTATION "exif-ifd0-Orientation" #define EXIF_ORIENTATION "exif-ifd0-Orientation"
int int
@ -456,8 +459,17 @@ vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interl
} }
int int
vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace) { vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace, int quantize, int colors) {
return vips_pngsave_buffer(in, buf, len, "profile", "none", "filter", VIPS_FOREIGN_PNG_FILTER_NONE, "interlace", interlace, NULL); return vips_pngsave_buffer(
in, buf, len,
"profile", "none",
"filter", VIPS_FOREIGN_PNG_FILTER_NONE,
"interlace", interlace,
#if VIPS_SUPPORT_PNG_QUANTIZATION
"palette", quantize,
"colours", colors,
#endif // VIPS_SUPPORT_PNG_QUANTIZATION
NULL);
} }
int int

2
vips.h
View File

@ -73,7 +73,7 @@ int vips_apply_watermark(VipsImage *in, VipsImage *watermark, VipsImage **out, d
int vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n); int vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n);
int vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interlace); int vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interlace);
int vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace); int vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace, int quantize, int colors);
int vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality); int vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality);
int vips_gifsave_go(VipsImage *in, void **buf, size_t *len); int vips_gifsave_go(VipsImage *in, void **buf, size_t *len);
int vips_icosave_go(VipsImage *in, void **buf, size_t *len); int vips_icosave_go(VipsImage *in, void **buf, size_t *len);