diff --git a/changelog/unreleased/CVE-2023-36308.md b/changelog/unreleased/CVE-2023-36308.md new file mode 100644 index 0000000000..a8abb03212 --- /dev/null +++ b/changelog/unreleased/CVE-2023-36308.md @@ -0,0 +1,7 @@ +Bugfix: Crash when processing crafted TIFF files + +Fix for a vulnerability with low severity in disintegration/imaging. + +https://github.com/advisories/GHSA-q7pp-wcgr-pffx +https://github.com/owncloud/ocis/pull/8981 + diff --git a/go.mod b/go.mod index 0f041014db..adce9e3311 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 github.com/cs3org/reva/v2 v2.19.2-0.20240426071117-7ed0671f9e0b github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 - github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e github.com/egirna/icap-client v0.1.1 github.com/gabriel-vasile/mimetype v1.4.3 @@ -56,6 +55,7 @@ require ( github.com/jellydator/ttlcache/v3 v3.2.0 github.com/jinzhu/now v1.1.5 github.com/justinas/alice v1.2.0 + github.com/kovidgoyal/imaging v1.6.3 github.com/leonelquinteros/gotext v1.6.0 github.com/libregraph/idm v0.5.0 github.com/libregraph/lico v0.61.3-0.20240322112242-72cf9221d3a7 diff --git a/go.sum b/go.sum index a03b980a11..1916c2a993 100644 --- a/go.sum +++ b/go.sum @@ -1056,8 +1056,6 @@ github.com/dgryski/trifles v0.0.0-20200323201526-dd97f9abfb48/go.mod h1:if7Fbed8 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 h1:simG0vMYFvNriGhaaat7QVVkaVkXzvqcohaBoLZl9Hg= github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25/go.mod h1:Z3Lomva4pyMWYezjMAU5QWRh0p1VvO4199OHlFnyKkM= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= -github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= -github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= @@ -1613,6 +1611,8 @@ github.com/kolo/xmlrpc v0.0.0-20200310150728-e0350524596b/go.mod h1:o03bZfuBwAXH github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kovidgoyal/imaging v1.6.3 h1:iNPpv7ygiaB/NOztc6APMT7yr9UwBS+rOZwIbAdtyY8= +github.com/kovidgoyal/imaging v1.6.3/go.mod h1:sHvcLOOVhJuto2IoNdPLEqnAUoL5ZfHEF0PpNH+882g= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -2200,7 +2200,6 @@ golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86h golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20200618115811-c13761719519/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= diff --git a/services/thumbnails/pkg/preprocessor/preprocessor.go b/services/thumbnails/pkg/preprocessor/preprocessor.go index b8949dc953..d8addd3a70 100644 --- a/services/thumbnails/pkg/preprocessor/preprocessor.go +++ b/services/thumbnails/pkg/preprocessor/preprocessor.go @@ -12,7 +12,7 @@ import ( "mime" "strings" - "github.com/disintegration/imaging" + "github.com/kovidgoyal/imaging" "github.com/pkg/errors" "golang.org/x/image/font" "golang.org/x/image/font/opentype" diff --git a/services/thumbnails/pkg/thumbnail/generator.go b/services/thumbnails/pkg/thumbnail/generator.go index 64aa086dff..80796ad7ce 100644 --- a/services/thumbnails/pkg/thumbnail/generator.go +++ b/services/thumbnails/pkg/thumbnail/generator.go @@ -7,7 +7,7 @@ import ( "image/gif" "strings" - "github.com/disintegration/imaging" + "github.com/kovidgoyal/imaging" ) // Generator generates a web friendly file version. diff --git a/services/thumbnails/pkg/thumbnail/processor.go b/services/thumbnails/pkg/thumbnail/processor.go index 3782fac4fc..59bbe3a636 100644 --- a/services/thumbnails/pkg/thumbnail/processor.go +++ b/services/thumbnails/pkg/thumbnail/processor.go @@ -4,7 +4,7 @@ import ( "image" "strings" - "github.com/disintegration/imaging" + "github.com/kovidgoyal/imaging" ) // Processor processes the thumbnail by applying different transformations to it. @@ -13,7 +13,7 @@ type Processor interface { Process(img image.Image, width, height int, filter imaging.ResampleFilter) *image.NRGBA } -// DefinableProcessor is the most simple processor, it holds a replaceable image converter function. +// DefinableProcessor is the simplest processor, it holds a replaceable image converter function. type DefinableProcessor struct { Slug string Converter func(img image.Image, width, height int, filter imaging.ResampleFilter) *image.NRGBA diff --git a/services/thumbnails/pkg/thumbnail/processor_test.go b/services/thumbnails/pkg/thumbnail/processor_test.go index febda33b81..893931a879 100644 --- a/services/thumbnails/pkg/thumbnail/processor_test.go +++ b/services/thumbnails/pkg/thumbnail/processor_test.go @@ -3,7 +3,7 @@ package thumbnail_test import ( "testing" - "github.com/disintegration/imaging" + "github.com/kovidgoyal/imaging" tAssert "github.com/stretchr/testify/assert" "github.com/owncloud/ocis/v2/services/thumbnails/pkg/thumbnail" diff --git a/vendor/github.com/disintegration/imaging/.travis.yml b/vendor/github.com/disintegration/imaging/.travis.yml deleted file mode 100644 index 7ae5e4b25a..0000000000 --- a/vendor/github.com/disintegration/imaging/.travis.yml +++ /dev/null @@ -1,12 +0,0 @@ -language: go -go: - - "1.10.x" - - "1.11.x" - - "1.12.x" - -before_install: - - go get github.com/mattn/goveralls - -script: - - go test -v -race -cover - - $GOPATH/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/kovidgoyal/imaging/.gitignore b/vendor/github.com/kovidgoyal/imaging/.gitignore new file mode 100644 index 0000000000..cde012322c --- /dev/null +++ b/vendor/github.com/kovidgoyal/imaging/.gitignore @@ -0,0 +1,2 @@ + +dist/ diff --git a/vendor/github.com/kovidgoyal/imaging/.goreleaser.yaml b/vendor/github.com/kovidgoyal/imaging/.goreleaser.yaml new file mode 100644 index 0000000000..25c4966c46 --- /dev/null +++ b/vendor/github.com/kovidgoyal/imaging/.goreleaser.yaml @@ -0,0 +1,41 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com + +# The lines below are called `modelines`. See `:help modeline` +# Feel free to remove those if you don't want/need to use them. +# yaml-language-server: $schema=https://goreleaser.com/static/schema.json +# vim: set ts=2 sw=2 tw=0 fo=cnqoj + +version: 1 + +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy + # you may remove this if you don't need go generate + - go generate ./... + +builds: + - skip: true + +archives: + - format: tar.gz + # this name template makes the OS and Arch compatible with the results of `uname`. + name_template: >- + {{ .ProjectName }}_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} + {{- if .Arm }}v{{ .Arm }}{{ end }} + # use zip for windows archives + format_overrides: + - goos: windows + format: zip + +changelog: + sort: asc + filters: + exclude: + - "^docs:" + - "^test:" diff --git a/vendor/github.com/disintegration/imaging/LICENSE b/vendor/github.com/kovidgoyal/imaging/LICENSE similarity index 100% rename from vendor/github.com/disintegration/imaging/LICENSE rename to vendor/github.com/kovidgoyal/imaging/LICENSE diff --git a/vendor/github.com/disintegration/imaging/README.md b/vendor/github.com/kovidgoyal/imaging/README.md similarity index 88% rename from vendor/github.com/disintegration/imaging/README.md rename to vendor/github.com/kovidgoyal/imaging/README.md index a1fd764d2c..7ca37e4090 100644 --- a/vendor/github.com/disintegration/imaging/README.md +++ b/vendor/github.com/kovidgoyal/imaging/README.md @@ -1,226 +1,231 @@ -# Imaging - -[![GoDoc](https://godoc.org/github.com/disintegration/imaging?status.svg)](https://godoc.org/github.com/disintegration/imaging) -[![Build Status](https://travis-ci.org/disintegration/imaging.svg?branch=master)](https://travis-ci.org/disintegration/imaging) -[![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master&service=github)](https://coveralls.io/github/disintegration/imaging?branch=master) -[![Go Report Card](https://goreportcard.com/badge/github.com/disintegration/imaging)](https://goreportcard.com/report/github.com/disintegration/imaging) - -Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). - -All the image processing functions provided by the package accept any image type that implements `image.Image` interface -as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha). - -## Installation - - go get -u github.com/disintegration/imaging - -## Documentation - -http://godoc.org/github.com/disintegration/imaging - -## Usage examples - -A few usage examples can be found below. See the documentation for the full list of supported functions. - -### Image resizing - -```go -// Resize srcImage to size = 128x128px using the Lanczos filter. -dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos) - -// Resize srcImage to width = 800px preserving the aspect ratio. -dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos) - -// Scale down srcImage to fit the 800x600px bounding box. -dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos) - -// Resize and crop the srcImage to fill the 100x100px area. -dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos) -``` - -Imaging supports image resizing using various resampling filters. The most notable ones: -- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results. -- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results. -- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom. -- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters. -- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor. -- `NearestNeighbor` - Fastest resampling filter, no antialiasing. - -The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct. - -**Resampling filters comparison** - -Original image: - -![srcImage](testdata/branches.png) - -The same image resized from 600x400px to 150x100px using different resampling filters. -From faster (lower quality) to slower (higher quality): - -Filter | Resize result ---------------------------|--------------------------------------------- -`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png) -`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png) -`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png) -`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png) - - -### Gaussian Blur - -```go -dstImage := imaging.Blur(srcImage, 0.5) -``` - -Sigma parameter allows to control the strength of the blurring effect. - -Original image | Sigma = 0.5 | Sigma = 1.5 ------------------------------------|----------------------------------------|--------------------------------------- -![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png) - -### Sharpening - -```go -dstImage := imaging.Sharpen(srcImage, 0.5) -``` - -`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect. - -Original image | Sigma = 0.5 | Sigma = 1.5 ------------------------------------|-------------------------------------------|------------------------------------------ -![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png) - -### Gamma correction - -```go -dstImage := imaging.AdjustGamma(srcImage, 0.75) -``` - -Original image | Gamma = 0.75 | Gamma = 1.25 ------------------------------------|------------------------------------------|----------------------------------------- -![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png) - -### Contrast adjustment - -```go -dstImage := imaging.AdjustContrast(srcImage, 20) -``` - -Original image | Contrast = 15 | Contrast = -15 ------------------------------------|--------------------------------------------|------------------------------------------- -![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png) - -### Brightness adjustment - -```go -dstImage := imaging.AdjustBrightness(srcImage, 20) -``` - -Original image | Brightness = 10 | Brightness = -10 ------------------------------------|----------------------------------------------|--------------------------------------------- -![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png) - -### Saturation adjustment - -```go -dstImage := imaging.AdjustSaturation(srcImage, 20) -``` - -Original image | Saturation = 30 | Saturation = -30 ------------------------------------|----------------------------------------------|--------------------------------------------- -![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_saturation_p30.png) | ![dstImage](testdata/out_saturation_m30.png) - -## FAQ - -### Incorrect image orientation after processing (e.g. an image appears rotated after resizing) - -Most probably, the given image contains the EXIF orientation tag. -The stadard `image/*` packages do not support loading and saving -this kind of information. To fix the issue, try opening images with -the `AutoOrientation` decode option. If this option is set to `true`, -the image orientation is changed after decoding, according to the -orientation tag (if present). Here's the example: - -```go -img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true)) -``` - -### What's the difference between `imaging` and `gift` packages? - -[imaging](https://github.com/disintegration/imaging) -is designed to be a lightweight and simple image manipulation package. -It provides basic image processing functions and a few helper functions -such as `Open` and `Save`. It consistently returns *image.NRGBA image -type (8 bits per channel, RGBA). - -[gift](https://github.com/disintegration/gift) -supports more advanced image processing, for example, sRGB/Linear color -space conversions. It also supports different output image types -(e.g. 16 bits per channel) and provides easy-to-use API for chaining -multiple processing steps together. - -## Example code - -```go -package main - -import ( - "image" - "image/color" - "log" - - "github.com/disintegration/imaging" -) - -func main() { - // Open a test image. - src, err := imaging.Open("testdata/flowers.png") - if err != nil { - log.Fatalf("failed to open image: %v", err) - } - - // Crop the original image to 300x300px size using the center anchor. - src = imaging.CropAnchor(src, 300, 300, imaging.Center) - - // Resize the cropped image to width = 200px preserving the aspect ratio. - src = imaging.Resize(src, 200, 0, imaging.Lanczos) - - // Create a blurred version of the image. - img1 := imaging.Blur(src, 5) - - // Create a grayscale version of the image with higher contrast and sharpness. - img2 := imaging.Grayscale(src) - img2 = imaging.AdjustContrast(img2, 20) - img2 = imaging.Sharpen(img2, 2) - - // Create an inverted version of the image. - img3 := imaging.Invert(src) - - // Create an embossed version of the image using a convolution filter. - img4 := imaging.Convolve3x3( - src, - [9]float64{ - -1, -1, 0, - -1, 1, 1, - 0, 1, 1, - }, - nil, - ) - - // Create a new image and paste the four produced images into it. - dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0}) - dst = imaging.Paste(dst, img1, image.Pt(0, 0)) - dst = imaging.Paste(dst, img2, image.Pt(0, 200)) - dst = imaging.Paste(dst, img3, image.Pt(200, 0)) - dst = imaging.Paste(dst, img4, image.Pt(200, 200)) - - // Save the resulting image as JPEG. - err = imaging.Save(dst, "testdata/out_example.jpg") - if err != nil { - log.Fatalf("failed to save image: %v", err) - } -} -``` - -Output: - -![dstImage](testdata/out_example.jpg) +# Imaging + +Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). + +All the image processing functions provided by the package accept any image type that implements `image.Image` interface +as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha). + +## Installation + + go get -u github.com/kovidgoyal/imaging + +## Documentation + +https://pkg.go.dev/github.com/kovidgoyal/imaging + +## Usage examples + +A few usage examples can be found below. See the documentation for the full list of supported functions. + +### Image resizing + +```go +// Resize srcImage to size = 128x128px using the Lanczos filter. +dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos) + +// Resize srcImage to width = 800px preserving the aspect ratio. +dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos) + +// Scale down srcImage to fit the 800x600px bounding box. +dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos) + +// Resize and crop the srcImage to fill the 100x100px area. +dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos) +``` + +Imaging supports image resizing using various resampling filters. The most notable ones: +- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results. +- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results. +- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom. +- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters. +- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor. +- `NearestNeighbor` - Fastest resampling filter, no antialiasing. + +The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct. + +**Resampling filters comparison** + +Original image: + +![srcImage](testdata/branches.png) + +The same image resized from 600x400px to 150x100px using different resampling filters. +From faster (lower quality) to slower (higher quality): + +Filter | Resize result +--------------------------|--------------------------------------------- +`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png) +`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png) +`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png) +`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png) + + +### Gaussian Blur + +```go +dstImage := imaging.Blur(srcImage, 0.5) +``` + +Sigma parameter allows to control the strength of the blurring effect. + +Original image | Sigma = 0.5 | Sigma = 1.5 +-----------------------------------|----------------------------------------|--------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png) + +### Sharpening + +```go +dstImage := imaging.Sharpen(srcImage, 0.5) +``` + +`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect. + +Original image | Sigma = 0.5 | Sigma = 1.5 +-----------------------------------|-------------------------------------------|------------------------------------------ +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png) + +### Gamma correction + +```go +dstImage := imaging.AdjustGamma(srcImage, 0.75) +``` + +Original image | Gamma = 0.75 | Gamma = 1.25 +-----------------------------------|------------------------------------------|----------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png) + +### Contrast adjustment + +```go +dstImage := imaging.AdjustContrast(srcImage, 20) +``` + +Original image | Contrast = 15 | Contrast = -15 +-----------------------------------|--------------------------------------------|------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png) + +### Brightness adjustment + +```go +dstImage := imaging.AdjustBrightness(srcImage, 20) +``` + +Original image | Brightness = 10 | Brightness = -10 +-----------------------------------|----------------------------------------------|--------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png) + +### Saturation adjustment + +```go +dstImage := imaging.AdjustSaturation(srcImage, 20) +``` + +Original image | Saturation = 30 | Saturation = -30 +-----------------------------------|----------------------------------------------|--------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_saturation_p30.png) | ![dstImage](testdata/out_saturation_m30.png) + +### Hue adjustment + +```go +dstImage := imaging.AdjustHue(srcImage, 20) +``` + +Original image | Hue = 60 | Hue = -60 +-----------------------------------|----------------------------------------------|--------------------------------------------- +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_hue_p60.png) | ![dstImage](testdata/out_hue_m60.png) + +## FAQ + +### Incorrect image orientation after processing (e.g. an image appears rotated after resizing) + +Most probably, the given image contains the EXIF orientation tag. +The standard `image/*` packages do not support loading and saving +this kind of information. To fix the issue, try opening images with +the `AutoOrientation` decode option. If this option is set to `true`, +the image orientation is changed after decoding, according to the +orientation tag (if present). Here's the example: + +```go +img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true)) +``` + +### What's the difference between `imaging` and `gift` packages? + +[imaging](https://github.com/kovidgoyal/imaging) +is designed to be a lightweight and simple image manipulation package. +It provides basic image processing functions and a few helper functions +such as `Open` and `Save`. It consistently returns *image.NRGBA image +type (8 bits per channel, RGBA). + +[gift](https://github.com/disintegration/gift) +supports more advanced image processing, for example, sRGB/Linear color +space conversions. It also supports different output image types +(e.g. 16 bits per channel) and provides easy-to-use API for chaining +multiple processing steps together. + +## Example code + +```go +package main + +import ( + "image" + "image/color" + "log" + + "github.com/kovidgoyal/imaging" +) + +func main() { + // Open a test image. + src, err := imaging.Open("testdata/flowers.png") + if err != nil { + log.Fatalf("failed to open image: %v", err) + } + + // Crop the original image to 300x300px size using the center anchor. + src = imaging.CropAnchor(src, 300, 300, imaging.Center) + + // Resize the cropped image to width = 200px preserving the aspect ratio. + src = imaging.Resize(src, 200, 0, imaging.Lanczos) + + // Create a blurred version of the image. + img1 := imaging.Blur(src, 5) + + // Create a grayscale version of the image with higher contrast and sharpness. + img2 := imaging.Grayscale(src) + img2 = imaging.AdjustContrast(img2, 20) + img2 = imaging.Sharpen(img2, 2) + + // Create an inverted version of the image. + img3 := imaging.Invert(src) + + // Create an embossed version of the image using a convolution filter. + img4 := imaging.Convolve3x3( + src, + [9]float64{ + -1, -1, 0, + -1, 1, 1, + 0, 1, 1, + }, + nil, + ) + + // Create a new image and paste the four produced images into it. + dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0}) + dst = imaging.Paste(dst, img1, image.Pt(0, 0)) + dst = imaging.Paste(dst, img2, image.Pt(0, 200)) + dst = imaging.Paste(dst, img3, image.Pt(200, 0)) + dst = imaging.Paste(dst, img4, image.Pt(200, 200)) + + // Save the resulting image as JPEG. + err = imaging.Save(dst, "testdata/out_example.jpg") + if err != nil { + log.Fatalf("failed to save image: %v", err) + } +} +``` + +Output: + +![dstImage](testdata/out_example.jpg) diff --git a/vendor/github.com/disintegration/imaging/adjust.go b/vendor/github.com/kovidgoyal/imaging/adjust.go similarity index 86% rename from vendor/github.com/disintegration/imaging/adjust.go rename to vendor/github.com/kovidgoyal/imaging/adjust.go index daaf1de860..971aebc6fe 100644 --- a/vendor/github.com/disintegration/imaging/adjust.go +++ b/vendor/github.com/kovidgoyal/imaging/adjust.go @@ -62,6 +62,10 @@ func Invert(img image.Image) *image.NRGBA { // dstImage = imaging.AdjustSaturation(srcImage, -10) // Decrease image saturation by 10%. // func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA { + if percentage == 0 { + return Clone(img) + } + percentage = math.Min(math.Max(percentage, -100), 100) multiplier := 1 + percentage/100 @@ -76,6 +80,34 @@ func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA { }) } +// AdjustHue changes the hue of the image using the shift parameter (measured in degrees) and returns the adjusted image. +// The shift = 0 (or 360 / -360 / etc.) gives the original image. +// The shift = 180 (or -180) corresponds to a 180° degree rotation of the color wheel and thus gives the image with its hue inverted for each pixel. +// +// Examples: +// dstImage = imaging.AdjustHue(srcImage, 90) // Shift Hue by 90°. +// dstImage = imaging.AdjustHue(srcImage, -30) // Shift Hue by -30°. +// +func AdjustHue(img image.Image, shift float64) *image.NRGBA { + if math.Mod(shift, 360) == 0 { + return Clone(img) + } + + summand := shift / 360 + + return AdjustFunc(img, func(c color.NRGBA) color.NRGBA { + h, s, l := rgbToHSL(c.R, c.G, c.B) + h += summand + h = math.Mod(h, 1) + //Adding 1 because Golang's Modulo function behaves differently to similar operators in most other languages. + if h < 0 { + h++ + } + r, g, b := hslToRGB(h, s, l) + return color.NRGBA{r, g, b, c.A} + }) +} + // AdjustContrast changes the contrast of the image using the percentage parameter and returns the adjusted image. // The percentage must be in range (-100, 100). The percentage = 0 gives the original image. // The percentage = -100 gives solid gray image. @@ -86,6 +118,10 @@ func AdjustSaturation(img image.Image, percentage float64) *image.NRGBA { // dstImage = imaging.AdjustContrast(srcImage, 20) // Increase image contrast by 20%. // func AdjustContrast(img image.Image, percentage float64) *image.NRGBA { + if percentage == 0 { + return Clone(img) + } + percentage = math.Min(math.Max(percentage, -100.0), 100.0) lut := make([]uint8, 256) @@ -114,6 +150,10 @@ func AdjustContrast(img image.Image, percentage float64) *image.NRGBA { // dstImage = imaging.AdjustBrightness(srcImage, 10) // Increase image brightness by 10%. // func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA { + if percentage == 0 { + return Clone(img) + } + percentage = math.Min(math.Max(percentage, -100.0), 100.0) lut := make([]uint8, 256) @@ -134,6 +174,10 @@ func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA { // dstImage = imaging.AdjustGamma(srcImage, 0.7) // func AdjustGamma(img image.Image, gamma float64) *image.NRGBA { + if gamma == 1 { + return Clone(img) + } + e := 1.0 / math.Max(gamma, 0.0001) lut := make([]uint8, 256) diff --git a/vendor/github.com/disintegration/imaging/convolution.go b/vendor/github.com/kovidgoyal/imaging/convolution.go similarity index 100% rename from vendor/github.com/disintegration/imaging/convolution.go rename to vendor/github.com/kovidgoyal/imaging/convolution.go diff --git a/vendor/github.com/disintegration/imaging/doc.go b/vendor/github.com/kovidgoyal/imaging/doc.go similarity index 100% rename from vendor/github.com/disintegration/imaging/doc.go rename to vendor/github.com/kovidgoyal/imaging/doc.go diff --git a/vendor/github.com/disintegration/imaging/effects.go b/vendor/github.com/kovidgoyal/imaging/effects.go similarity index 100% rename from vendor/github.com/disintegration/imaging/effects.go rename to vendor/github.com/kovidgoyal/imaging/effects.go diff --git a/vendor/github.com/disintegration/imaging/histogram.go b/vendor/github.com/kovidgoyal/imaging/histogram.go similarity index 100% rename from vendor/github.com/disintegration/imaging/histogram.go rename to vendor/github.com/kovidgoyal/imaging/histogram.go diff --git a/vendor/github.com/disintegration/imaging/io.go b/vendor/github.com/kovidgoyal/imaging/io.go similarity index 100% rename from vendor/github.com/disintegration/imaging/io.go rename to vendor/github.com/kovidgoyal/imaging/io.go diff --git a/vendor/github.com/kovidgoyal/imaging/publish.py b/vendor/github.com/kovidgoyal/imaging/publish.py new file mode 100644 index 0000000000..3b0317bf4f --- /dev/null +++ b/vendor/github.com/kovidgoyal/imaging/publish.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python +# License: GPLv3 Copyright: 2024, Kovid Goyal + +import os +import subprocess + + +def run(*args: str): + cp = subprocess.run(args) + if cp.returncode != 0: + raise SystemExit(cp.returncode) + + +def main(): + version = input('Enter the version to publish: ') + try: + ans = input(f'Publish version \033[91m{version}\033[m (y/n): ') + except KeyboardInterrupt: + ans = 'n' + if ans.lower() != 'y': + return + os.environ['GITHUB_TOKEN'] = open(os.path.join(os.environ['PENV'], 'github-token')).read().strip() + run('git', 'tag', '-a', 'v' + version, '-m', f'version {version}') + run('git', 'push') + run('goreleaser', 'release') + + +if __name__ == '__main__': + main() diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/kovidgoyal/imaging/resize.go similarity index 99% rename from vendor/github.com/disintegration/imaging/resize.go rename to vendor/github.com/kovidgoyal/imaging/resize.go index 706435e3dc..963f40c482 100644 --- a/vendor/github.com/disintegration/imaging/resize.go +++ b/vendor/github.com/kovidgoyal/imaging/resize.go @@ -87,6 +87,10 @@ func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NR dstH = int(math.Max(1.0, math.Floor(tmpH+0.5))) } + if srcW == dstW && srcH == dstH { + return Clone(img) + } + if filter.Support <= 0 { // Nearest-neighbor special case. return resizeNearest(img, dstW, dstH) @@ -98,10 +102,8 @@ func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NR if srcW != dstW { return resizeHorizontal(img, dstW, filter) } - if srcH != dstH { - return resizeVertical(img, dstH, filter) - } - return Clone(img) + return resizeVertical(img, dstH, filter) + } func resizeHorizontal(img image.Image, width int, filter ResampleFilter) *image.NRGBA { diff --git a/vendor/github.com/disintegration/imaging/scanner.go b/vendor/github.com/kovidgoyal/imaging/scanner.go similarity index 98% rename from vendor/github.com/disintegration/imaging/scanner.go rename to vendor/github.com/kovidgoyal/imaging/scanner.go index 37d92cef88..84de2fc90f 100644 --- a/vendor/github.com/disintegration/imaging/scanner.go +++ b/vendor/github.com/kovidgoyal/imaging/scanner.go @@ -18,7 +18,7 @@ func newScanner(img image.Image) *scanner { h: img.Bounds().Dy(), } if img, ok := img.(*image.Paletted); ok { - s.palette = make([]color.NRGBA, len(img.Palette)) + s.palette = make([]color.NRGBA, max(256, len(img.Palette))) for i := 0; i < len(img.Palette); i++ { s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA) } diff --git a/vendor/github.com/kovidgoyal/imaging/session.vim b/vendor/github.com/kovidgoyal/imaging/session.vim new file mode 100644 index 0000000000..76924354f1 --- /dev/null +++ b/vendor/github.com/kovidgoyal/imaging/session.vim @@ -0,0 +1,2 @@ +" Empty for the moment + diff --git a/vendor/github.com/disintegration/imaging/tools.go b/vendor/github.com/kovidgoyal/imaging/tools.go similarity index 98% rename from vendor/github.com/disintegration/imaging/tools.go rename to vendor/github.com/kovidgoyal/imaging/tools.go index 0ec19a039c..9591ebc5ae 100644 --- a/vendor/github.com/disintegration/imaging/tools.go +++ b/vendor/github.com/kovidgoyal/imaging/tools.go @@ -96,6 +96,10 @@ func Crop(img image.Image, rect image.Rectangle) *image.NRGBA { if r.Empty() { return &image.NRGBA{} } + if r.Eq(img.Bounds().Sub(img.Bounds().Min)) { + return Clone(img) + } + src := newScanner(img) dst := image.NewNRGBA(image.Rect(0, 0, r.Dx(), r.Dy())) rowSize := r.Dx() * 4 @@ -133,6 +137,10 @@ func Paste(background, img image.Image, pos image.Point) *image.NRGBA { if interRect.Empty() { return dst } + if interRect.Eq(dst.Bounds()) { + return Clone(img) + } + src := newScanner(img) parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) { for y := range ys { diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/kovidgoyal/imaging/transform.go similarity index 100% rename from vendor/github.com/disintegration/imaging/transform.go rename to vendor/github.com/kovidgoyal/imaging/transform.go diff --git a/vendor/github.com/disintegration/imaging/utils.go b/vendor/github.com/kovidgoyal/imaging/utils.go similarity index 88% rename from vendor/github.com/disintegration/imaging/utils.go rename to vendor/github.com/kovidgoyal/imaging/utils.go index 6c7af1a518..f650c05bce 100644 --- a/vendor/github.com/disintegration/imaging/utils.go +++ b/vendor/github.com/kovidgoyal/imaging/utils.go @@ -5,8 +5,17 @@ import ( "math" "runtime" "sync" + "sync/atomic" ) +var maxProcs int64 + +// SetMaxProcs limits the number of concurrent processing goroutines to the given value. +// A value <= 0 clears the limit. +func SetMaxProcs(value int) { + atomic.StoreInt64(&maxProcs, int64(value)) +} + // parallel processes the data in separate goroutines. func parallel(start, stop int, fn func(<-chan int)) { count := stop - start @@ -15,6 +24,10 @@ func parallel(start, stop int, fn func(<-chan int)) { } procs := runtime.GOMAXPROCS(0) + limit := int(atomic.LoadInt64(&maxProcs)) + if procs > limit && limit > 0 { + procs = limit + } if procs > count { procs = count } diff --git a/vendor/modules.txt b/vendor/modules.txt index 1f98cc72ee..ef35213dfa 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -758,9 +758,6 @@ github.com/dgryski/go-rendezvous # github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 ## explicit; go 1.18 github.com/dhowden/tag -# github.com/disintegration/imaging v1.6.2 -## explicit -github.com/disintegration/imaging # github.com/dlclark/regexp2 v1.4.0 ## explicit github.com/dlclark/regexp2 @@ -1256,6 +1253,9 @@ github.com/klauspost/compress/s2 # github.com/klauspost/cpuid/v2 v2.2.6 ## explicit; go 1.15 github.com/klauspost/cpuid/v2 +# github.com/kovidgoyal/imaging v1.6.3 +## explicit; go 1.21 +github.com/kovidgoyal/imaging # github.com/leodido/go-urn v1.4.0 ## explicit; go 1.18 github.com/leodido/go-urn