diff --git a/config.go b/config.go index b1925c56..221d7c65 100644 --- a/config.go +++ b/config.go @@ -166,6 +166,7 @@ type config struct { PngQuantizationColors int Quality int GZipCompression int + StripMetadata bool EnableWebpDetection bool EnforceWebp bool @@ -242,6 +243,7 @@ var conf = config{ SignatureSize: 32, PngQuantizationColors: 256, Quality: 80, + StripMetadata: true, UserAgent: fmt.Sprintf("imgproxy/%s", version), Presets: make(presets), WatermarkOpacity: 1, @@ -300,6 +302,7 @@ func configure() { intEnvConfig(&conf.PngQuantizationColors, "IMGPROXY_PNG_QUANTIZATION_COLORS") intEnvConfig(&conf.Quality, "IMGPROXY_QUALITY") intEnvConfig(&conf.GZipCompression, "IMGPROXY_GZIP_COMPRESSION") + boolEnvConfig(&conf.StripMetadata, "IMGPROXY_STRIP_METADATA") boolEnvConfig(&conf.EnableWebpDetection, "IMGPROXY_ENABLE_WEBP_DETECTION") boolEnvConfig(&conf.EnforceWebp, "IMGPROXY_ENFORCE_WEBP") diff --git a/docs/configuration.md b/docs/configuration.md index 7e600cef..394f2672 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -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_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`: 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`. \ No newline at end of file diff --git a/process.go b/process.go index af205f65..8299d7c0 100644 --- a/process.go +++ b/process.go @@ -609,7 +609,7 @@ func saveImageToFitBytes(po *processingOptions, img *vipsImage) ([]byte, context img.CopyMemory() 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 { return result, cancel, err } @@ -737,5 +737,5 @@ func processImage(ctx context.Context) ([]byte, context.CancelFunc, error) { return saveImageToFitBytes(po, img) } - return img.Save(po.Format, po.Quality) + return img.Save(po.Format, po.Quality, po.StripMetadata) } diff --git a/processing_options.go b/processing_options.go index a66337a5..df7b99e4 100644 --- a/processing_options.go +++ b/processing_options.go @@ -114,22 +114,23 @@ type watermarkOptions struct { } type processingOptions struct { - ResizingType resizeType - Width int - Height int - Dpr float64 - Gravity gravityOptions - Enlarge bool - Extend extendOptions - Crop cropOptions - Trim trimOptions - Format imageType - Quality int - MaxBytes int - Flatten bool - Background rgbColor - Blur float32 - Sharpen float32 + ResizingType resizeType + Width int + Height int + Dpr float64 + Gravity gravityOptions + Enlarge bool + Extend extendOptions + Crop cropOptions + Trim trimOptions + Format imageType + Quality int + StripMetadata bool + MaxBytes int + Flatten bool + Background rgbColor + Blur float32 + Sharpen float32 CacheBuster string @@ -198,21 +199,22 @@ var ( func newProcessingOptions() *processingOptions { newProcessingOptionsOnce.Do(func() { _newProcessingOptions = processingOptions{ - ResizingType: resizeFit, - Width: 0, - Height: 0, - Gravity: gravityOptions{Type: gravityCenter}, - Enlarge: false, - Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}}, - Trim: trimOptions{Enabled: false, Threshold: 10}, - Quality: conf.Quality, - MaxBytes: 0, - Format: imageTypeUnknown, - Background: rgbColor{255, 255, 255}, - Blur: 0, - Sharpen: 0, - Dpr: 1, - Watermark: watermarkOptions{Opacity: 1, Replicate: false, Gravity: gravityOptions{Type: gravityCenter}}, + ResizingType: resizeFit, + Width: 0, + Height: 0, + Gravity: gravityOptions{Type: gravityCenter}, + Enlarge: false, + Extend: extendOptions{Enabled: false, Gravity: gravityOptions{Type: gravityCenter}}, + Trim: trimOptions{Enabled: false, Threshold: 10}, + Quality: conf.Quality, + StripMetadata: conf.StripMetadata, + MaxBytes: 0, + Format: imageTypeUnknown, + Background: rgbColor{255, 255, 255}, + Blur: 0, + Sharpen: 0, + Dpr: 1, + Watermark: watermarkOptions{Opacity: 1, Replicate: false, Gravity: gravityOptions{Type: gravityCenter}}, } }) diff --git a/vips.c b/vips.c index d6a24229..f45014c6 100644 --- a/vips.c +++ b/vips.c @@ -338,7 +338,12 @@ vips_support_builtin_icc() { int 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 @@ -512,8 +517,8 @@ vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n) { } int -vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interlace) { - return vips_jpegsave_buffer(in, buf, len, "profile", "none", "Q", quality, "strip", TRUE, "optimize_coding", TRUE, "interlace", interlace, NULL); +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", strip, "optimize_coding", TRUE, "interlace", interlace, NULL); } int @@ -531,8 +536,8 @@ vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace, int quant } int -vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality) { - return vips_webpsave_buffer(in, buf, len, "Q", quality, "strip", TRUE, NULL); +vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality, gboolean strip) { + return vips_webpsave_buffer(in, buf, len, "Q", quality, "strip", strip, NULL); } int diff --git a/vips.go b/vips.go index 66939ad5..47d91283 100644 --- a/vips.go +++ b/vips.go @@ -130,6 +130,13 @@ func vipsLoadWatermark() (err error) { return } +func gbool(b bool) C.gboolean { + if b { + return C.gboolean(1) + } + return C.gboolean(0) +} + func (img *vipsImage) Width() int { return int(img.VipsImage.Xsize) } @@ -170,7 +177,7 @@ func (img *vipsImage) Load(data []byte, imgtype imageType, shrink int, scale flo 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 cancel := func() { @@ -183,11 +190,11 @@ func (img *vipsImage) Save(imgtype imageType, quality int) ([]byte, context.Canc switch imgtype { 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: err = C.vips_pngsave_go(img.VipsImage, &ptr, &imgsize, vipsConf.PngInterlaced, vipsConf.PngQuantize, vipsConf.PngQuantizationColors) 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: err = C.vips_gifsave_go(img.VipsImage, &ptr, &imgsize) case imageTypeICO: @@ -312,6 +319,8 @@ func (img *vipsImage) Rotate(angle int) error { return vipsError() } + C.vips_autorot_remove_angle(tmp) + C.swap_and_clear(&img.VipsImage, tmp) return nil } diff --git a/vips.h b/vips.h index c52d3964..9cf2ee2f 100644 --- a/vips.h +++ b/vips.h @@ -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_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_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_icosave_go(VipsImage *in, void **buf, size_t *len); int vips_heifsave_go(VipsImage *in, void **buf, size_t *len, int quality);