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
|
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")
|
||||||
|
@ -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`.
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -114,22 +114,23 @@ type watermarkOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type processingOptions struct {
|
type processingOptions struct {
|
||||||
ResizingType resizeType
|
ResizingType resizeType
|
||||||
Width int
|
Width int
|
||||||
Height int
|
Height int
|
||||||
Dpr float64
|
Dpr float64
|
||||||
Gravity gravityOptions
|
Gravity gravityOptions
|
||||||
Enlarge bool
|
Enlarge bool
|
||||||
Extend extendOptions
|
Extend extendOptions
|
||||||
Crop cropOptions
|
Crop cropOptions
|
||||||
Trim trimOptions
|
Trim trimOptions
|
||||||
Format imageType
|
Format imageType
|
||||||
Quality int
|
Quality int
|
||||||
MaxBytes int
|
StripMetadata bool
|
||||||
Flatten bool
|
MaxBytes int
|
||||||
Background rgbColor
|
Flatten bool
|
||||||
Blur float32
|
Background rgbColor
|
||||||
Sharpen float32
|
Blur float32
|
||||||
|
Sharpen float32
|
||||||
|
|
||||||
CacheBuster string
|
CacheBuster string
|
||||||
|
|
||||||
@ -198,21 +199,22 @@ var (
|
|||||||
func newProcessingOptions() *processingOptions {
|
func newProcessingOptions() *processingOptions {
|
||||||
newProcessingOptionsOnce.Do(func() {
|
newProcessingOptionsOnce.Do(func() {
|
||||||
_newProcessingOptions = processingOptions{
|
_newProcessingOptions = processingOptions{
|
||||||
ResizingType: resizeFit,
|
ResizingType: resizeFit,
|
||||||
Width: 0,
|
Width: 0,
|
||||||
Height: 0,
|
Height: 0,
|
||||||
Gravity: gravityOptions{Type: gravityCenter},
|
Gravity: gravityOptions{Type: gravityCenter},
|
||||||
Enlarge: false,
|
Enlarge: false,
|
||||||
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,
|
||||||
MaxBytes: 0,
|
StripMetadata: conf.StripMetadata,
|
||||||
Format: imageTypeUnknown,
|
MaxBytes: 0,
|
||||||
Background: rgbColor{255, 255, 255},
|
Format: imageTypeUnknown,
|
||||||
Blur: 0,
|
Background: rgbColor{255, 255, 255},
|
||||||
Sharpen: 0,
|
Blur: 0,
|
||||||
Dpr: 1,
|
Sharpen: 0,
|
||||||
Watermark: watermarkOptions{Opacity: 1, Replicate: false, Gravity: gravityOptions{Type: gravityCenter}},
|
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
|
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
15
vips.go
@ -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
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_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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user