1
0
mirror of https://github.com/imgproxy/imgproxy.git synced 2025-02-07 11:36:25 +02:00

Add option to keep metadata/tags in output image (#329)

* add env var to disable stripping metadata

by default, all metadata will be stripped (as before)

* always strip orientation tags when rotating the image

in case IMGPROXY_STRIP_METADATA is false

* document IMGPROXY_STRIP_METADATA env var

* remove ICC profile after importing it

needed, in case metadata aren't stripped from the output image
This commit is contained in:
sauerbraten 2020-01-30 16:43:08 +01:00 committed by GitHub
parent aa8cff62f4
commit 89f8a4e11c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 63 additions and 43 deletions

View File

@ -166,6 +166,7 @@ type config struct {
PngQuantizationColors int PngQuantizationColors int
Quality int Quality int
GZipCompression int GZipCompression int
StripMetadata bool
EnableWebpDetection bool EnableWebpDetection bool
EnforceWebp bool EnforceWebp bool
@ -242,6 +243,7 @@ var conf = config{
SignatureSize: 32, SignatureSize: 32,
PngQuantizationColors: 256, PngQuantizationColors: 256,
Quality: 80, Quality: 80,
StripMetadata: true,
UserAgent: fmt.Sprintf("imgproxy/%s", version), UserAgent: fmt.Sprintf("imgproxy/%s", version),
Presets: make(presets), Presets: make(presets),
WatermarkOpacity: 1, WatermarkOpacity: 1,
@ -300,6 +302,7 @@ func configure() {
intEnvConfig(&conf.PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS") 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")
boolEnvConfig(&conf.StripMetadata, "IMGPROXY_STRIP_METADATA")
boolEnvConfig(&conf.EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION") boolEnvConfig(&conf.EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION")
boolEnvConfig(&conf.EnforceWebp, "IMGPROXY_ENFORCE_WEBP") boolEnvConfig(&conf.EnforceWebp, "IMGPROXY_ENFORCE_WEBP")

View File

@ -253,3 +253,4 @@ imgproxy can send logs to syslog, but this feature is disabled by default. To en
* `IMGPROXY_USE_LINEAR_COLORSPACE`: when `true`, imgproxy will process images in linear colorspace. This will slow down processing. Note that images won't be fully processed in linear colorspace while shrink-on-load is enabled (see below). * `IMGPROXY_USE_LINEAR_COLORSPACE`: when `true`, imgproxy will process images in linear colorspace. This will slow down processing. Note that images won't be fully processed in linear colorspace while shrink-on-load is enabled (see below).
* `IMGPROXY_DISABLE_SHRINK_ON_LOAD`: when `true`, disables shrink-on-load for JPEG and WebP. Allows to process the whole image in linear colorspace but dramatically slows down resizing and increases memory usage when working with large images. * `IMGPROXY_DISABLE_SHRINK_ON_LOAD`: when `true`, disables shrink-on-load for JPEG and WebP. Allows to process the whole image in linear colorspace but dramatically slows down resizing and increases memory usage when working with large images.
* `IMGPROXY_APPLY_UNSHARPEN_MASKING`: <img class="pro-badge" src="assets/pro.svg" alt="pro" /> when `true`, imgproxy will apply unsharpen masking to the resulting image if one is smaller than the source. Default: `true`. * `IMGPROXY_APPLY_UNSHARPEN_MASKING`: <img class="pro-badge" src="assets/pro.svg" alt="pro" /> when `true`, imgproxy will apply unsharpen masking to the resulting image if one is smaller than the source. Default: `true`.
* `IMGPROXY_STRIP_METADATA`: whether to strip all metadata (EXIF, IPTC, etc.) from JPEG and WebP output images. Default: `true`.

View File

@ -609,7 +609,7 @@ func saveImageToFitBytes(po *processingOptions, img *vipsImage) ([]byte, context
img.CopyMemory() img.CopyMemory()
for { for {
result, cancel, err := img.Save(po.Format, quality) result, cancel, err := img.Save(po.Format, quality, po.StripMetadata)
if len(result) <= po.MaxBytes || quality <= 10 || err != nil { if len(result) <= po.MaxBytes || quality <= 10 || err != nil {
return result, cancel, err return result, cancel, err
} }
@ -737,5 +737,5 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) {
return saveImageToFitBytes(po, img) return saveImageToFitBytes(po, img)
} }
return img.Save(po.Format, po.Quality) return img.Save(po.Format, po.Quality, po.StripMetadata)
} }

View File

@ -125,6 +125,7 @@ type processingOptions struct {
Trim trimOptions Trim trimOptions
Format imageType Format imageType
Quality int Quality int
StripMetadata bool
MaxBytes int MaxBytes int
Flatten bool Flatten bool
Background rgbColor Background rgbColor
@ -206,6 +207,7 @@ func newProcessingOptions() *processingOptions {
Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}}, Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}},
Trim: trimOptions{Enabled: false, Threshold: 10}, Trim: trimOptions{Enabled: false, Threshold: 10},
Quality: conf.Quality, Quality: conf.Quality,
StripMetadata: conf.StripMetadata,
MaxBytes: 0, MaxBytes: 0,
Format: imageTypeUnknown, Format: imageTypeUnknown,
Background: rgbColor{255, 255, 255}, Background: rgbColor{255, 255, 255},

15
vips.c
View File

@ -338,7 +338,12 @@ vips_support_builtin_icc() {
int int
vips_icc_import_go(VipsImage *in, VipsImage **out, char *profile) { vips_icc_import_go(VipsImage *in, VipsImage **out, char *profile) {
return vips_icc_import(in, out, "input_profile", profile, "embedded", TRUE, "pcs", VIPS_PCS_XYZ, NULL); if (vips_icc_import(in, out, "input_profile", profile, "embedded", TRUE, "pcs", VIPS_PCS_XYZ, NULL))
return 1;
vips_image_remove(*out, VIPS_META_ICC_NAME);
return 0;
} }
int int
@ -512,8 +517,8 @@ vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n) {
} }
int int
vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interlace) { vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interlace, gboolean strip) {
return vips_jpegsave_buffer(in, buf, len, "profile", "none", "Q", quality, "strip", TRUE, "optimize_coding", TRUE, "interlace", interlace, NULL); return vips_jpegsave_buffer(in, buf, len, "profile", "none", "Q", quality, "strip", strip, "optimize_coding", TRUE, "interlace", interlace, NULL);
} }
int int
@ -531,8 +536,8 @@ vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace, int quant
} }
int int
vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality) { vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality, gboolean strip) {
return vips_webpsave_buffer(in, buf, len, "Q", quality, "strip", TRUE, NULL); return vips_webpsave_buffer(in, buf, len, "Q", quality, "strip", strip, NULL);
} }
int int

15
vips.go
View File

@ -130,6 +130,13 @@ func vipsLoadWatermark() (err error) {
return return
} }
func gbool(b bool) C.gboolean {
if b {
return C.gboolean(1)
}
return C.gboolean(0)
}
func (img *vipsImage) Width() int { func (img *vipsImage) Width() int {
return int(img.VipsImage.Xsize) return int(img.VipsImage.Xsize)
} }
@ -170,7 +177,7 @@ func (img *vipsImage) Load(data []byte, imgtype imageType, shrink int, scale flo
return nil return nil
} }
func (img *vipsImage) Save(imgtype imageType, quality int) ([]byte, context.CancelFunc, error) { func (img *vipsImage) Save(imgtype imageType, quality int, stripMeta bool) ([]byte, context.CancelFunc, error) {
var ptr unsafe.Pointer var ptr unsafe.Pointer
cancel := func() { cancel := func() {
@ -183,11 +190,11 @@ func (img *vipsImage) Save(imgtype imageType, quality int) ([]byte, context.Canc
switch imgtype { switch imgtype {
case imageTypeJPEG: case imageTypeJPEG:
err = C.vips_jpegsave_go(img.VipsImage, &ptr, &imgsize, C.int(quality), vipsConf.JpegProgressive) err = C.vips_jpegsave_go(img.VipsImage, &ptr, &imgsize, C.int(quality), vipsConf.JpegProgressive, gbool(stripMeta))
case imageTypePNG: case imageTypePNG:
err = C.vips_pngsave_go(img.VipsImage, &ptr, &imgsize, vipsConf.PngInterlaced, vipsConf.PngQuantize, vipsConf.PngQuantizationColors) err = C.vips_pngsave_go(img.VipsImage, &ptr, &imgsize, vipsConf.PngInterlaced, vipsConf.PngQuantize, vipsConf.PngQuantizationColors)
case imageTypeWEBP: case imageTypeWEBP:
err = C.vips_webpsave_go(img.VipsImage, &ptr, &imgsize, C.int(quality)) err = C.vips_webpsave_go(img.VipsImage, &ptr, &imgsize, C.int(quality), gbool(stripMeta))
case imageTypeGIF: case imageTypeGIF:
err = C.vips_gifsave_go(img.VipsImage, &ptr, &imgsize) err = C.vips_gifsave_go(img.VipsImage, &ptr, &imgsize)
case imageTypeICO: case imageTypeICO:
@ -312,6 +319,8 @@ func (img *vipsImage) Rotate(angle int) error {
return vipsError() return vipsError()
} }
C.vips_autorot_remove_angle(tmp)
C.swap_and_clear(&img.VipsImage, tmp) C.swap_and_clear(&img.VipsImage, tmp)
return nil return nil
} }

4
vips.h
View File

@ -82,9 +82,9 @@ 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, gboolean strip);
int vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace, int quantize, int colors); 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, gboolean strip);
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);
int vips_heifsave_go(VipsImage *in, void **buf, size_t *len, int quality); int vips_heifsave_go(VipsImage *in, void **buf, size_t *len, int quality);