mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-02-02 11:34:20 +02:00
PNG quantization
This commit is contained in:
parent
e99241aea0
commit
4ba970bdf6
@ -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/
|
||||||
|
19
config.go
19
config.go
@ -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 {
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
16
process.go
16
process.go
@ -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
16
vips.c
@ -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
2
vips.h
@ -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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user