mirror of
https://github.com/imgproxy/imgproxy.git
synced 2025-02-02 11:34:20 +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:
parent
aa8cff62f4
commit
89f8a4e11c
@ -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")
|
||||
|
@ -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`: <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`.
|
@ -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)
|
||||
}
|
||||
|
@ -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}},
|
||||
}
|
||||
})
|
||||
|
||||
|
15
vips.c
15
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
|
||||
|
15
vips.go
15
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
|
||||
}
|
||||
|
4
vips.h
4
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user