Skip to content

Commit

Permalink
feat(vips): strip_metadata() filter and vips-strip-metadata config (#475
Browse files Browse the repository at this point in the history
)

* strip metadata if `strip_exif` for webp and avif

TODO: add support for other format

* strip_metadata() filter and vips-strip-metadata config

* test cases

* test: update golden files

---------

Co-authored-by: Liu Dongmiao <[email protected]>
  • Loading branch information
cshum and liudongmiao authored Aug 28, 2024
1 parent d11d821 commit c64221a
Show file tree
Hide file tree
Showing 16 changed files with 58 additions and 5 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ imagor supports the following filters:
- `sharpen(sigma)` sharpens the image
- `strip_exif()` removes Exif metadata from the resulting image
- `strip_icc()` removes ICC profile information from the resulting image
- `strip_metadata()` removes all metadata from the resulting image
- `upscale()` upscale the image if `fit-in` is used
- `watermark(image, x, y, alpha [, w_ratio [, h_ratio]])` adds a watermark to the image. It can be positioned inside the image with the alpha channel specified and optionally resized based on the image size by specifying the ratio
- `image` watermark image URI, using the same image loader configured for imagor
Expand Down Expand Up @@ -811,4 +812,6 @@ Usage of imagor:
VIPS enable maximum compression with MozJPEG. Requires mozjpeg to be installed
-vips-avif-speed int
VIPS avif speed, the lowest is at 0 and the fastest is at 9 (Default 5).
-vips-strip-metadata
VIPS strips all metadata from the resulting image
```
3 changes: 3 additions & 0 deletions config/vipsconfig/vipsconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ func WithVips(fs *flag.FlagSet, cb func() (*zap.Logger, bool)) imagor.Option {
"VIPS enable maximum compression with MozJPEG. Requires mozjpeg to be installed")
vipsAvifSpeed = fs.Int("vips-avif-speed", 5,
"VIPS avif speed, the lowest is at 0 and the fastest is at 9 (Default 5).")
vipsStripMetadata = fs.Bool("vips-strip-metadata", false,
"VIPS strips all metadata from the resulting image")

logger, isDebug = cb()
)
Expand All @@ -54,6 +56,7 @@ func WithVips(fs *flag.FlagSet, cb func() (*zap.Logger, bool)) imagor.Option {
vips.WithMaxResolution(*vipsMaxResolution),
vips.WithMozJPEG(*vipsMozJPEG),
vips.WithAvifSpeed(*vipsAvifSpeed),
vips.WithStripMetadata(*vipsStripMetadata),
vips.WithLogger(logger),
vips.WithDebug(isDebug),
),
Expand Down
Binary file added testdata/golden/fit-in/67x67/dancing-banana.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/golden/fit-in/67x67/demo1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/golden/fit-in/67x67/demo3.webp
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file added testdata/golden/fit-in/67x67/gopher-front.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added testdata/golden/fit-in/67x67/gopher.tiff
Binary file not shown.
7 changes: 7 additions & 0 deletions vips/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ func WithMozJPEG(enabled bool) Option {
}
}

// WithStripMetadata with strip all metadata from image option
func WithStripMetadata(enabled bool) Option {
return func(v *Processor) {
v.StripMetadata = enabled
}
}

// WithAvifSpeed with avif speed option
func WithAvifSpeed(avifSpeed int) Option {
return func(v *Processor) {
Expand Down
2 changes: 2 additions & 0 deletions vips/option_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func TestWithOption(t *testing.T) {
WithMaxResolution(1666667),
WithMozJPEG(true),
WithAvifSpeed(9),
WithStripMetadata(true),
WithDebug(true),
WithMaxAnimationFrames(3),
WithDisableFilters("rgb", "fill, watermark"),
Expand All @@ -38,6 +39,7 @@ func TestWithOption(t *testing.T) {
assert.Equal(t, 1666667, v.MaxResolution)
assert.Equal(t, 3, v.MaxAnimationFrames)
assert.Equal(t, true, v.MozJPEG)
assert.Equal(t, true, v.StripMetadata)
assert.Equal(t, 9, v.AvifSpeed)
assert.Equal(t, []string{"rgb", "fill", "watermark"}, v.DisableFilters)

Expand Down
23 changes: 19 additions & 4 deletions vips/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (v *Processor) Process(
stretch = p.Stretch
thumbnail = false
stripExif bool
stripMetadata = v.StripMetadata
orient int
img *Image
format = ImageTypeUnknown
Expand Down Expand Up @@ -122,6 +123,8 @@ func (v *Processor) Process(
break
case "strip_exif":
stripExif = true
case "strip_metadata":
stripMetadata = true
break
}
}
Expand Down Expand Up @@ -313,7 +316,7 @@ func (v *Processor) Process(
}
format = supportedSaveFormat(format) // convert to supported export format
for {
buf, err := v.export(img, format, compression, quality, palette, bitdepth, stripExif)
buf, err := v.export(img, format, compression, quality, palette, bitdepth, stripMetadata)
if err != nil {
return nil, WrapErr(err)
}
Expand Down Expand Up @@ -575,7 +578,7 @@ func supportedSaveFormat(format ImageType) ImageType {
}

func (v *Processor) export(
image *Image, format ImageType, compression int, quality int, palette bool, bitdepth int, stripExif bool,
image *Image, format ImageType, compression int, quality int, palette bool, bitdepth int, stripMetadata bool,
) ([]byte, error) {
switch format {
case ImageTypePNG:
Expand All @@ -592,13 +595,16 @@ func (v *Processor) export(
if compression > 0 {
opts.Compression = compression
}
if stripMetadata {
opts.StripMetadata = true
}
return image.ExportPng(opts)
case ImageTypeWEBP:
opts := NewWebpExportParams()
if quality > 0 {
opts.Quality = quality
}
if stripExif {
if stripMetadata {
opts.StripMetadata = true
}
return image.ExportWebp(opts)
Expand All @@ -607,19 +613,25 @@ func (v *Processor) export(
if quality > 0 {
opts.Quality = quality
}
if stripMetadata {
opts.StripMetadata = true
}
return image.ExportTiff(opts)
case ImageTypeGIF:
opts := NewGifExportParams()
if quality > 0 {
opts.Quality = quality
}
if stripMetadata {
opts.StripMetadata = true
}
return image.ExportGIF(opts)
case ImageTypeAVIF:
opts := NewAvifExportParams()
if quality > 0 {
opts.Quality = quality
}
if stripExif {
if stripMetadata {
opts.StripMetadata = true
}
opts.Speed = v.AvifSpeed
Expand Down Expand Up @@ -650,6 +662,9 @@ func (v *Processor) export(
if quality > 0 {
opts.Quality = quality
}
if stripMetadata {
opts.StripMetadata = true
}
return image.ExportJpeg(opts)
}
}
Expand Down
3 changes: 2 additions & 1 deletion vips/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type Processor struct {
MaxResolution int
MaxAnimationFrames int
MozJPEG bool
StripMetadata bool
AvifSpeed int
Debug bool

Expand Down Expand Up @@ -305,7 +306,7 @@ func (v *Processor) FocalThumbnail(img *Image, w, h int, fx, fy float64) (err er
imageHeight = float64(img.PageHeight())
}

if float64(w)/float64(h) > float64(imageWidth)/float64(imageHeight) {
if float64(w)/float64(h) > float64(imageWidth)/float64(imageHeight) {
if err = img.Thumbnail(w, v.MaxHeight, InterestingNone); err != nil {
return
}
Expand Down
22 changes: 22 additions & 0 deletions vips/processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,28 @@ func TestProcessor(t *testing.T) {
{name: "meta strip exif", path: "meta/filters:strip_exif()/Canon_40D.jpg"},
}, WithDebug(true), WithLogger(zap.NewExample()))
})
t.Run("vips strip metadata config", func(t *testing.T) {
var resultDir = filepath.Join(testDataDir, "golden")
doGoldenTests(t, resultDir, []test{
{name: "png", path: "fit-in/67x67/gopher-front.png"},
{name: "jpeg", path: "fit-in/67x67/demo1.jpg"},
{name: "webp", path: "fit-in/67x67/demo3.webp", arm64Golden: true},
{name: "tiff", path: "fit-in/67x67/gopher.tiff"},
{name: "tiff", path: "fit-in/67x67/dancing-banana.gif"},
//{name: "avif", path: "fit-in/67x67/gopher-front.avif", checkTypeOnly: true},
}, WithDebug(true), WithStripMetadata(true), WithLogger(zap.NewExample()))
})
t.Run("vips strip_metadata filter", func(t *testing.T) {
var resultDir = filepath.Join(testDataDir, "golden")
doGoldenTests(t, resultDir, []test{
{name: "png", path: "gopher-front.png"},
{name: "jpeg", path: "fit-in/67x67/filters:strip_metadata()/demo1.jpg"},
{name: "webp", path: "fit-in/67x67/filters:strip_metadata()/demo3.webp", arm64Golden: true},
{name: "tiff", path: "fit-in/67x67/filters:strip_metadata()/gopher.tiff"},
{name: "gif", path: "fit-in/67x67/filters:strip_metadata()/dancing-banana.gif"},
//{name: "avif", path: "fit-in/67x67/filters:strip_metadata()/gopher-front.avif", checkTypeOnly: true},
}, WithDebug(true), WithLogger(zap.NewExample()))
})
t.Run("vips operations", func(t *testing.T) {
var resultDir = filepath.Join(testDataDir, "golden")
doGoldenTests(t, resultDir, []test{
Expand Down

0 comments on commit c64221a

Please sign in to comment.