From 6e2cb00008cbf09e556b00f87603797fcaa47e09 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 16 Apr 2018 05:37:14 -0700 Subject: Depenancy upgrades and movign to dep. (#8630) --- .../github.com/disintegration/imaging/.travis.yml | 16 +- vendor/github.com/disintegration/imaging/LICENSE | 2 +- vendor/github.com/disintegration/imaging/README.md | 63 +- vendor/github.com/disintegration/imaging/adjust.go | 256 ++++---- .../disintegration/imaging/adjust_test.go | 564 ------------------ vendor/github.com/disintegration/imaging/clone.go | 312 ---------- .../disintegration/imaging/clone_test.go | 247 -------- .../disintegration/imaging/convolution.go | 6 +- .../disintegration/imaging/convolution_test.go | 275 --------- vendor/github.com/disintegration/imaging/doc.go | 7 + .../github.com/disintegration/imaging/effects.go | 174 +++--- .../disintegration/imaging/effects_test.go | 254 -------- .../disintegration/imaging/example_test.go | 58 -- .../github.com/disintegration/imaging/helpers.go | 134 ++++- .../disintegration/imaging/helpers_test.go | 159 ----- .../github.com/disintegration/imaging/histogram.go | 46 +- .../disintegration/imaging/histogram_test.go | 42 -- vendor/github.com/disintegration/imaging/resize.go | 221 ++++--- .../disintegration/imaging/resize_test.go | 628 -------------------- .../github.com/disintegration/imaging/scanner.go | 250 ++++++++ .../disintegration/imaging/testdata/lena_128.png | Bin 50383 -> 0 bytes .../disintegration/imaging/testdata/lena_512.png | Bin 476195 -> 0 bytes .../imaging/testdata/out_blur_0.5.png | Bin 29110 -> 0 bytes .../imaging/testdata/out_blur_1.5.png | Bin 21067 -> 0 bytes .../imaging/testdata/out_brightness_m10.png | Bin 31562 -> 0 bytes .../imaging/testdata/out_brightness_p10.png | Bin 31532 -> 0 bytes .../imaging/testdata/out_contrast_m10.png | Bin 30812 -> 0 bytes .../imaging/testdata/out_contrast_p10.png | Bin 32615 -> 0 bytes .../imaging/testdata/out_example.jpg | Bin 137574 -> 0 bytes .../imaging/testdata/out_gamma_0.75.png | Bin 31901 -> 0 bytes .../imaging/testdata/out_gamma_1.25.png | Bin 31295 -> 0 bytes .../imaging/testdata/out_resize_catrom.png | Bin 31179 -> 0 bytes .../imaging/testdata/out_resize_lanczos.png | Bin 32070 -> 0 bytes .../imaging/testdata/out_resize_linear.png | Bin 29475 -> 0 bytes .../imaging/testdata/out_resize_nearest.png | Bin 35790 -> 0 bytes .../imaging/testdata/out_sharpen_0.5.png | Bin 33936 -> 0 bytes .../imaging/testdata/out_sharpen_1.5.png | Bin 36632 -> 0 bytes vendor/github.com/disintegration/imaging/tools.go | 133 +++-- .../disintegration/imaging/tools_test.go | 652 --------------------- .../github.com/disintegration/imaging/transform.go | 217 +++---- .../disintegration/imaging/transform_test.go | 581 ------------------ vendor/github.com/disintegration/imaging/utils.go | 88 +-- .../disintegration/imaging/utils_test.go | 61 -- 43 files changed, 944 insertions(+), 4502 deletions(-) delete mode 100644 vendor/github.com/disintegration/imaging/adjust_test.go delete mode 100644 vendor/github.com/disintegration/imaging/clone.go delete mode 100644 vendor/github.com/disintegration/imaging/clone_test.go delete mode 100644 vendor/github.com/disintegration/imaging/convolution_test.go create mode 100644 vendor/github.com/disintegration/imaging/doc.go delete mode 100644 vendor/github.com/disintegration/imaging/effects_test.go delete mode 100644 vendor/github.com/disintegration/imaging/example_test.go delete mode 100644 vendor/github.com/disintegration/imaging/helpers_test.go delete mode 100644 vendor/github.com/disintegration/imaging/histogram_test.go delete mode 100644 vendor/github.com/disintegration/imaging/resize_test.go create mode 100644 vendor/github.com/disintegration/imaging/scanner.go delete mode 100644 vendor/github.com/disintegration/imaging/testdata/lena_128.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/lena_512.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_blur_0.5.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_blur_1.5.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_brightness_m10.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_brightness_p10.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_contrast_m10.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_contrast_p10.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_example.jpg delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_gamma_0.75.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_gamma_1.25.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_resize_catrom.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_resize_lanczos.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_resize_linear.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_resize_nearest.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_sharpen_0.5.png delete mode 100644 vendor/github.com/disintegration/imaging/testdata/out_sharpen_1.5.png delete mode 100644 vendor/github.com/disintegration/imaging/tools_test.go delete mode 100644 vendor/github.com/disintegration/imaging/transform_test.go delete mode 100644 vendor/github.com/disintegration/imaging/utils_test.go (limited to 'vendor/github.com/disintegration') diff --git a/vendor/github.com/disintegration/imaging/.travis.yml b/vendor/github.com/disintegration/imaging/.travis.yml index 4886abd74..89370edcb 100644 --- a/vendor/github.com/disintegration/imaging/.travis.yml +++ b/vendor/github.com/disintegration/imaging/.travis.yml @@ -1,17 +1,13 @@ language: go - -sudo: false - go: - - 1.2 - - 1.7 - - 1.8 - - 1.9 + - "1.7.x" + - "1.8.x" + - "1.9.x" + - "1.10.x" before_install: - - go get golang.org/x/tools/cmd/cover - go get github.com/mattn/goveralls script: - - go test -v -covermode=count -coverprofile=coverage.out - - $HOME/gopath/bin/goveralls -service=travis-ci -coverprofile=coverage.out + - go test -v -race -cover + - $GOPATH/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/disintegration/imaging/LICENSE b/vendor/github.com/disintegration/imaging/LICENSE index 72a26f0e8..c68f7ab7c 100644 --- a/vendor/github.com/disintegration/imaging/LICENSE +++ b/vendor/github.com/disintegration/imaging/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2012-2017 Grigory Dryapak +Copyright (c) 2012-2018 Grigory Dryapak Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/disintegration/imaging/README.md b/vendor/github.com/disintegration/imaging/README.md index f957c3e79..c7ee30fc8 100644 --- a/vendor/github.com/disintegration/imaging/README.md +++ b/vendor/github.com/disintegration/imaging/README.md @@ -2,19 +2,16 @@ [![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)](https://coveralls.io/github/disintegration/imaging?branch=master) +[![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 manipulation functions (resize, rotate, flip, crop, etc.). -This package is based on the standard Go image package and works best along with it. +Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.). -Image manipulation functions provided by the package take any image type -that implements `image.Image` interface as an input, and return a new image of -`*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha). +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, not premultiplied by alpha). ## Installation -Imaging requires Go version 1.2 or greater. - go get -u github.com/disintegration/imaging ## Documentation @@ -46,19 +43,19 @@ Imaging supports image resizing using various resampling filters. The most notab - `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor. - `Linear` - Bilinear filter, smooth and reasonably fast. - `MitchellNetravali` - А smooth bicubic filter. -- `CatmullRom` - A sharp bicubic filter. +- `CatmullRom` - A sharp bicubic filter. - `Gaussian` - Blurring filter that uses gaussian function, useful for noise removal. -- `Lanczos` - High-quality resampling filter for photographic images yielding sharp results, but it's slower than cubic filters. +- `Lanczos` - High-quality resampling filter for photographic images yielding sharp results, slower than cubic filters. 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** -The original image. +Original image: -![srcImage](testdata/lena_512.png) +![srcImage](testdata/branches.png) -The same image resized from 512x512px to 128x128px using different resampling filters. +The same image resized from 600x400px to 150x100px using different resampling filters. From faster (lower quality) to slower (higher quality): Filter | Resize result @@ -79,7 +76,7 @@ Sigma parameter allows to control the strength of the blurring effect. Original image | Sigma = 0.5 | Sigma = 1.5 -----------------------------------|----------------------------------------|--------------------------------------- -![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png) +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png) ### Sharpening @@ -91,7 +88,7 @@ dstImage := imaging.Sharpen(srcImage, 0.5) Original image | Sigma = 0.5 | Sigma = 1.5 -----------------------------------|-------------------------------------------|------------------------------------------ -![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png) +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png) ### Gamma correction @@ -101,7 +98,7 @@ dstImage := imaging.AdjustGamma(srcImage, 0.75) Original image | Gamma = 0.75 | Gamma = 1.25 -----------------------------------|------------------------------------------|----------------------------------------- -![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png) +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png) ### Contrast adjustment @@ -109,9 +106,9 @@ Original image | Gamma = 0.75 | dstImage := imaging.AdjustContrast(srcImage, 20) ``` -Original image | Contrast = 10 | Contrast = -10 +Original image | Contrast = 15 | Contrast = -15 -----------------------------------|--------------------------------------------|------------------------------------------- -![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_contrast_p10.png) | ![dstImage](testdata/out_contrast_m10.png) +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png) ### Brightness adjustment @@ -121,7 +118,7 @@ dstImage := imaging.AdjustBrightness(srcImage, 20) Original image | Brightness = 10 | Brightness = -10 -----------------------------------|----------------------------------------------|--------------------------------------------- -![srcImage](testdata/lena_128.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png) +![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png) ## Example code @@ -137,20 +134,20 @@ import ( ) func main() { - // Open the test image. - src, err := imaging.Open("testdata/lena_512.png") + // Open a test image. + src, err := imaging.Open("testdata/flowers.png") if err != nil { - log.Fatalf("Open failed: %v", err) + log.Fatalf("failed to open image: %v", err) } - // Crop the original image to 350x350px size using the center anchor. - src = imaging.CropAnchor(src, 350, 350, imaging.Center) + // 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 = 256px preserving the aspect ratio. - src = imaging.Resize(src, 256, 0, imaging.Lanczos) + // 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, 2) + img1 := imaging.Blur(src, 5) // Create a grayscale version of the image with higher contrast and sharpness. img2 := imaging.Grayscale(src) @@ -172,16 +169,16 @@ func main() { ) // Create a new image and paste the four produced images into it. - dst := imaging.New(512, 512, color.NRGBA{0, 0, 0, 0}) + 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, 256)) - dst = imaging.Paste(dst, img3, image.Pt(256, 0)) - dst = imaging.Paste(dst, img4, image.Pt(256, 256)) + 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 using JPEG format. + // Save the resulting image as JPEG. err = imaging.Save(dst, "testdata/out_example.jpg") if err != nil { - log.Fatalf("Save failed: %v", err) + log.Fatalf("failed to save image: %v", err) } } ``` diff --git a/vendor/github.com/disintegration/imaging/adjust.go b/vendor/github.com/disintegration/imaging/adjust.go index daee893cc..fb3a9ce3c 100644 --- a/vendor/github.com/disintegration/imaging/adjust.go +++ b/vendor/github.com/disintegration/imaging/adjust.go @@ -6,50 +6,95 @@ import ( "math" ) -// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image. +// Grayscale produces a grayscale version of the image. +func Grayscale(img image.Image) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + r := dst.Pix[i+0] + g := dst.Pix[i+1] + b := dst.Pix[i+2] + f := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b) + y := uint8(f + 0.5) + dst.Pix[i+0] = y + dst.Pix[i+1] = y + dst.Pix[i+2] = y + i += 4 + } + } + }) + return dst +} + +// Invert produces an inverted (negated) version of the image. +func Invert(img image.Image) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + dst.Pix[i+0] = 255 - dst.Pix[i+0] + dst.Pix[i+1] = 255 - dst.Pix[i+1] + dst.Pix[i+2] = 255 - dst.Pix[i+2] + i += 4 + } + } + }) + return dst +} + +// 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. // -// Example: +// Examples: // -// dstImage = imaging.AdjustFunc( -// srcImage, -// func(c color.NRGBA) color.NRGBA { -// // shift the red channel by 16 -// r := int(c.R) + 16 -// if r > 255 { -// r = 255 -// } -// return color.NRGBA{uint8(r), c.G, c.B, c.A} -// } -// ) +// dstImage = imaging.AdjustContrast(srcImage, -10) // decrease image contrast by 10% +// dstImage = imaging.AdjustContrast(srcImage, 20) // increase image contrast by 20% // -func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA { - src := toNRGBA(img) - width := src.Bounds().Max.X - height := src.Bounds().Max.Y - dst := image.NewNRGBA(image.Rect(0, 0, width, height)) - - parallel(height, func(partStart, partEnd int) { - for y := partStart; y < partEnd; y++ { - for x := 0; x < width; x++ { - i := y*src.Stride + x*4 - j := y*dst.Stride + x*4 - - r := src.Pix[i+0] - g := src.Pix[i+1] - b := src.Pix[i+2] - a := src.Pix[i+3] - - c := fn(color.NRGBA{r, g, b, a}) +func AdjustContrast(img image.Image, percentage float64) *image.NRGBA { + percentage = math.Min(math.Max(percentage, -100.0), 100.0) + lut := make([]uint8, 256) - dst.Pix[j+0] = c.R - dst.Pix[j+1] = c.G - dst.Pix[j+2] = c.B - dst.Pix[j+3] = c.A - } + v := (100.0 + percentage) / 100.0 + for i := 0; i < 256; i++ { + if 0 <= v && v <= 1 { + lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*v) * 255.0) + } else if 1 < v && v < 2 { + lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*(1/(2.0-v))) * 255.0) + } else { + lut[i] = uint8(float64(i)/255.0+0.5) * 255 } - }) + } - return dst + return adjustLUT(img, lut) +} + +// AdjustBrightness changes the brightness 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 black image. The percentage = 100 gives solid white image. +// +// Examples: +// +// dstImage = imaging.AdjustBrightness(srcImage, -15) // decrease image brightness by 15% +// dstImage = imaging.AdjustBrightness(srcImage, 10) // increase image brightness by 10% +// +func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA { + percentage = math.Min(math.Max(percentage, -100.0), 100.0) + lut := make([]uint8, 256) + + shift := 255.0 * percentage / 100.0 + for i := 0; i < 256; i++ { + lut[i] = clamp(float64(i) + shift) + } + + return adjustLUT(img, lut) } // AdjustGamma performs a gamma correction on the image and returns the adjusted image. @@ -68,15 +113,7 @@ func AdjustGamma(img image.Image, gamma float64) *image.NRGBA { lut[i] = clamp(math.Pow(float64(i)/255.0, e) * 255.0) } - fn := func(c color.NRGBA) color.NRGBA { - return color.NRGBA{lut[c.R], lut[c.G], lut[c.B], c.A} - } - - return AdjustFunc(img, fn) -} - -func sigmoid(a, b, x float64) float64 { - return 1 / (1 + math.Exp(b*(a-x))) + return adjustLUT(img, lut) } // AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image. @@ -118,83 +155,68 @@ func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA { } } - fn := func(c color.NRGBA) color.NRGBA { - return color.NRGBA{lut[c.R], lut[c.G], lut[c.B], c.A} - } - - return AdjustFunc(img, fn) + return adjustLUT(img, lut) } -// 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 grey image. -// -// Examples: -// -// dstImage = imaging.AdjustContrast(srcImage, -10) // decrease image contrast by 10% -// dstImage = imaging.AdjustContrast(srcImage, 20) // increase image contrast by 20% -// -func AdjustContrast(img image.Image, percentage float64) *image.NRGBA { - percentage = math.Min(math.Max(percentage, -100.0), 100.0) - lut := make([]uint8, 256) +func sigmoid(a, b, x float64) float64 { + return 1 / (1 + math.Exp(b*(a-x))) +} - v := (100.0 + percentage) / 100.0 - for i := 0; i < 256; i++ { - if 0 <= v && v <= 1 { - lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*v) * 255.0) - } else if 1 < v && v < 2 { - lut[i] = clamp((0.5 + (float64(i)/255.0-0.5)*(1/(2.0-v))) * 255.0) - } else { - lut[i] = uint8(float64(i)/255.0+0.5) * 255 +// adjustLUT applies the given lookup table to the colors of the image. +func adjustLUT(img image.Image, lut []uint8) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + dst.Pix[i+0] = lut[dst.Pix[i+0]] + dst.Pix[i+1] = lut[dst.Pix[i+1]] + dst.Pix[i+2] = lut[dst.Pix[i+2]] + i += 4 + } } - } - - fn := func(c color.NRGBA) color.NRGBA { - return color.NRGBA{lut[c.R], lut[c.G], lut[c.B], c.A} - } - - return AdjustFunc(img, fn) + }) + return dst } -// AdjustBrightness changes the brightness 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 black image. The percentage = 100 gives solid white image. +// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image. // -// Examples: +// Example: // -// dstImage = imaging.AdjustBrightness(srcImage, -15) // decrease image brightness by 15% -// dstImage = imaging.AdjustBrightness(srcImage, 10) // increase image brightness by 10% +// dstImage = imaging.AdjustFunc( +// srcImage, +// func(c color.NRGBA) color.NRGBA { +// // shift the red channel by 16 +// r := int(c.R) + 16 +// if r > 255 { +// r = 255 +// } +// return color.NRGBA{uint8(r), c.G, c.B, c.A} +// } +// ) // -func AdjustBrightness(img image.Image, percentage float64) *image.NRGBA { - percentage = math.Min(math.Max(percentage, -100.0), 100.0) - lut := make([]uint8, 256) - - shift := 255.0 * percentage / 100.0 - for i := 0; i < 256; i++ { - lut[i] = clamp(float64(i) + shift) - } - - fn := func(c color.NRGBA) color.NRGBA { - return color.NRGBA{lut[c.R], lut[c.G], lut[c.B], c.A} - } - - return AdjustFunc(img, fn) -} - -// Grayscale produces grayscale version of the image. -func Grayscale(img image.Image) *image.NRGBA { - fn := func(c color.NRGBA) color.NRGBA { - f := 0.299*float64(c.R) + 0.587*float64(c.G) + 0.114*float64(c.B) - y := uint8(f + 0.5) - return color.NRGBA{y, y, y, c.A} - } - return AdjustFunc(img, fn) -} - -// Invert produces inverted (negated) version of the image. -func Invert(img image.Image) *image.NRGBA { - fn := func(c color.NRGBA) color.NRGBA { - return color.NRGBA{255 - c.R, 255 - c.G, 255 - c.B, c.A} - } - return AdjustFunc(img, fn) +func AdjustFunc(img image.Image, fn func(c color.NRGBA) color.NRGBA) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+src.w*4]) + for x := 0; x < src.w; x++ { + r := dst.Pix[i+0] + g := dst.Pix[i+1] + b := dst.Pix[i+2] + a := dst.Pix[i+3] + c := fn(color.NRGBA{r, g, b, a}) + dst.Pix[i+0] = c.R + dst.Pix[i+1] = c.G + dst.Pix[i+2] = c.B + dst.Pix[i+3] = c.A + i += 4 + } + } + }) + return dst } diff --git a/vendor/github.com/disintegration/imaging/adjust_test.go b/vendor/github.com/disintegration/imaging/adjust_test.go deleted file mode 100644 index 60183d6ea..000000000 --- a/vendor/github.com/disintegration/imaging/adjust_test.go +++ /dev/null @@ -1,564 +0,0 @@ -package imaging - -import ( - "image" - "testing" -) - -func TestGrayscale(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Grayscale 3x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x3d, 0x3d, 0x3d, 0x01, 0x78, 0x78, 0x78, 0x02, 0x17, 0x17, 0x17, 0x03, - 0x1f, 0x1f, 0x1f, 0xff, 0x25, 0x25, 0x25, 0xff, 0x66, 0x66, 0x66, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Grayscale(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestInvert(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Invert 3x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x33, 0xff, 0xff, 0x01, 0xff, 0x33, 0xff, 0x02, 0xff, 0xff, 0x33, 0x03, - 0xee, 0xdd, 0xcc, 0xff, 0xcc, 0xdd, 0xee, 0xff, 0x55, 0xcc, 0x44, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xcc, 0xcc, 0xcc, 0xff, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Invert(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestAdjustContrast(t *testing.T) { - td := []struct { - desc string - src image.Image - p float64 - want *image.NRGBA - }{ - { - "AdjustContrast 3x3 10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 10, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xd5, 0x00, 0x00, 0x01, 0x00, 0xd5, 0x00, 0x02, 0x00, 0x00, 0xd5, 0x03, - 0x05, 0x18, 0x2b, 0xff, 0x2b, 0x18, 0x05, 0xff, 0xaf, 0x2b, 0xc2, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustContrast 3x3 100", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 100, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0x00, 0x02, 0x00, 0x00, 0xff, 0x03, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustContrast 3x3 -10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - -10, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xc4, 0x0d, 0x0d, 0x01, 0x0d, 0xc4, 0x0d, 0x02, 0x0d, 0x0d, 0xc4, 0x03, - 0x1c, 0x2b, 0x3b, 0xff, 0x3b, 0x2b, 0x1c, 0xff, 0xa6, 0x3b, 0xb5, 0xff, - 0x0d, 0x0d, 0x0d, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xf2, 0xf2, 0xf2, 0xff, - }, - }, - }, - { - "AdjustContrast 3x3 -100", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - -100, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x80, 0x80, 0x80, 0x01, 0x80, 0x80, 0x80, 0x02, 0x80, 0x80, 0x80, 0x03, - 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, - 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, 0x80, 0x80, 0x80, 0xff, - }, - }, - }, - { - "AdjustContrast 3x3 0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - for _, d := range td { - got := AdjustContrast(d.src, d.p) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestAdjustContrastGolden(t *testing.T) { - src, err := Open("testdata/lena_128.png") - if err != nil { - t.Errorf("Open: %v", err) - } - for name, p := range map[string]float64{ - "out_contrast_m10.png": -10, - "out_contrast_p10.png": 10, - } { - got := AdjustContrast(src, p) - want, err := Open("testdata/" + name) - if err != nil { - t.Errorf("Open: %v", err) - } - if !compareNRGBA(got, toNRGBA(want), 0) { - t.Errorf("resulting image differs from golden: %s", name) - } - } -} - -func TestAdjustBrightness(t *testing.T) { - td := []struct { - desc string - src image.Image - p float64 - want *image.NRGBA - }{ - { - "AdjustBrightness 3x3 10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 10, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xe6, 0x1a, 0x1a, 0x01, 0x1a, 0xe6, 0x1a, 0x02, 0x1a, 0x1a, 0xe6, 0x03, - 0x2b, 0x3c, 0x4d, 0xff, 0x4d, 0x3c, 0x2b, 0xff, 0xc4, 0x4d, 0xd5, 0xff, - 0x1a, 0x1a, 0x1a, 0xff, 0x4d, 0x4d, 0x4d, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustBrightness 3x3 100", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 100, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x02, 0xff, 0xff, 0xff, 0x03, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustBrightness 3x3 -10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - -10, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xb3, 0x00, 0x00, 0x01, 0x00, 0xb3, 0x00, 0x02, 0x00, 0x00, 0xb3, 0x03, - 0x00, 0x09, 0x1a, 0xff, 0x1a, 0x09, 0x00, 0xff, 0x91, 0x1a, 0xa2, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x1a, 0x1a, 0x1a, 0xff, 0xe6, 0xe6, 0xe6, 0xff, - }, - }, - }, - { - "AdjustBrightness 3x3 -100", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - -100, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - { - "AdjustBrightness 3x3 0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - for _, d := range td { - got := AdjustBrightness(d.src, d.p) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestAdjustBrightnessGolden(t *testing.T) { - src, err := Open("testdata/lena_128.png") - if err != nil { - t.Errorf("Open: %v", err) - } - for name, p := range map[string]float64{ - "out_brightness_m10.png": -10, - "out_brightness_p10.png": 10, - } { - got := AdjustBrightness(src, p) - want, err := Open("testdata/" + name) - if err != nil { - t.Errorf("Open: %v", err) - } - if !compareNRGBA(got, toNRGBA(want), 0) { - t.Errorf("resulting image differs from golden: %s", name) - } - } -} - -func TestAdjustGamma(t *testing.T) { - td := []struct { - desc string - src image.Image - p float64 - want *image.NRGBA - }{ - { - "AdjustGamma 3x3 0.75", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0.75, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xbd, 0x00, 0x00, 0x01, 0x00, 0xbd, 0x00, 0x02, 0x00, 0x00, 0xbd, 0x03, - 0x07, 0x11, 0x1e, 0xff, 0x1e, 0x11, 0x07, 0xff, 0x95, 0x1e, 0xa9, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x1e, 0x1e, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustGamma 3x3 1.5", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 1.5, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xdc, 0x00, 0x00, 0x01, 0x00, 0xdc, 0x00, 0x02, 0x00, 0x00, 0xdc, 0x03, - 0x2a, 0x43, 0x57, 0xff, 0x57, 0x43, 0x2a, 0xff, 0xc3, 0x57, 0xcf, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x57, 0x57, 0x57, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustGamma 3x3 1.0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 1.0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - for _, d := range td { - got := AdjustGamma(d.src, d.p) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestAdjustGammaGolden(t *testing.T) { - src, err := Open("testdata/lena_128.png") - if err != nil { - t.Errorf("Open: %v", err) - } - for name, g := range map[string]float64{ - "out_gamma_0.75.png": 0.75, - "out_gamma_1.25.png": 1.25, - } { - got := AdjustGamma(src, g) - want, err := Open("testdata/" + name) - if err != nil { - t.Errorf("Open: %v", err) - } - if !compareNRGBA(got, toNRGBA(want), 0) { - t.Errorf("resulting image differs from golden: %s", name) - } - } -} - -func TestAdjustSigmoid(t *testing.T) { - td := []struct { - desc string - src image.Image - m float64 - p float64 - want *image.NRGBA - }{ - { - "AdjustSigmoid 3x3 0.5 3.0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0.5, - 3.0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xd4, 0x00, 0x00, 0x01, 0x00, 0xd4, 0x00, 0x02, 0x00, 0x00, 0xd4, 0x03, - 0x0d, 0x1b, 0x2b, 0xff, 0x2b, 0x1b, 0x0d, 0xff, 0xb1, 0x2b, 0xc3, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x2b, 0x2b, 0x2b, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustSigmoid 3x3 0.5 -3.0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0.5, - -3.0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xc4, 0x00, 0x00, 0x01, 0x00, 0xc4, 0x00, 0x02, 0x00, 0x00, 0xc4, 0x03, - 0x16, 0x2a, 0x3b, 0xff, 0x3b, 0x2a, 0x16, 0xff, 0xa4, 0x3b, 0xb3, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x3b, 0x3b, 0x3b, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "AdjustSigmoid 3x3 0.5 0.0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0.5, - 0.0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0x00, 0x00, 0x01, 0x00, 0xcc, 0x00, 0x02, 0x00, 0x00, 0xcc, 0x03, - 0x11, 0x22, 0x33, 0xff, 0x33, 0x22, 0x11, 0xff, 0xaa, 0x33, 0xbb, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x33, 0x33, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - for _, d := range td { - got := AdjustSigmoid(d.src, d.m, d.p) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} diff --git a/vendor/github.com/disintegration/imaging/clone.go b/vendor/github.com/disintegration/imaging/clone.go deleted file mode 100644 index a22e01913..000000000 --- a/vendor/github.com/disintegration/imaging/clone.go +++ /dev/null @@ -1,312 +0,0 @@ -package imaging - -import ( - "image" - "image/color" -) - -// Clone returns a copy of the given image. -func Clone(img image.Image) *image.NRGBA { - dstBounds := img.Bounds().Sub(img.Bounds().Min) - dst := image.NewNRGBA(dstBounds) - - switch src := img.(type) { - case *image.NRGBA: - copyNRGBA(dst, src) - case *image.NRGBA64: - copyNRGBA64(dst, src) - case *image.RGBA: - copyRGBA(dst, src) - case *image.RGBA64: - copyRGBA64(dst, src) - case *image.Gray: - copyGray(dst, src) - case *image.Gray16: - copyGray16(dst, src) - case *image.YCbCr: - copyYCbCr(dst, src) - case *image.Paletted: - copyPaletted(dst, src) - default: - copyImage(dst, src) - } - - return dst -} - -func copyNRGBA(dst *image.NRGBA, src *image.NRGBA) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - rowSize := dstW * 4 - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - copy(dst.Pix[di:di+rowSize], src.Pix[si:si+rowSize]) - } - }) -} - -func copyNRGBA64(dst *image.NRGBA, src *image.NRGBA64) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - for dstX := 0; dstX < dstW; dstX++ { - dst.Pix[di+0] = src.Pix[si+0] - dst.Pix[di+1] = src.Pix[si+2] - dst.Pix[di+2] = src.Pix[si+4] - dst.Pix[di+3] = src.Pix[si+6] - di += 4 - si += 8 - } - } - }) -} - -func copyRGBA(dst *image.NRGBA, src *image.RGBA) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - for dstX := 0; dstX < dstW; dstX++ { - a := src.Pix[si+3] - dst.Pix[di+3] = a - - switch a { - case 0: - dst.Pix[di+0] = 0 - dst.Pix[di+1] = 0 - dst.Pix[di+2] = 0 - case 0xff: - dst.Pix[di+0] = src.Pix[si+0] - dst.Pix[di+1] = src.Pix[si+1] - dst.Pix[di+2] = src.Pix[si+2] - default: - var tmp uint16 - tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a) - dst.Pix[di+0] = uint8(tmp) - tmp = uint16(src.Pix[si+1]) * 0xff / uint16(a) - dst.Pix[di+1] = uint8(tmp) - tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a) - dst.Pix[di+2] = uint8(tmp) - } - - di += 4 - si += 4 - } - } - }) -} - -func copyRGBA64(dst *image.NRGBA, src *image.RGBA64) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - for dstX := 0; dstX < dstW; dstX++ { - a := src.Pix[si+6] - dst.Pix[di+3] = a - - switch a { - case 0: - dst.Pix[di+0] = 0 - dst.Pix[di+1] = 0 - dst.Pix[di+2] = 0 - case 0xff: - dst.Pix[di+0] = src.Pix[si+0] - dst.Pix[di+1] = src.Pix[si+2] - dst.Pix[di+2] = src.Pix[si+4] - default: - var tmp uint16 - tmp = uint16(src.Pix[si+0]) * 0xff / uint16(a) - dst.Pix[di+0] = uint8(tmp) - tmp = uint16(src.Pix[si+2]) * 0xff / uint16(a) - dst.Pix[di+1] = uint8(tmp) - tmp = uint16(src.Pix[si+4]) * 0xff / uint16(a) - dst.Pix[di+2] = uint8(tmp) - } - - di += 4 - si += 8 - } - } - }) -} - -func copyGray(dst *image.NRGBA, src *image.Gray) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - for dstX := 0; dstX < dstW; dstX++ { - c := src.Pix[si] - dst.Pix[di+0] = c - dst.Pix[di+1] = c - dst.Pix[di+2] = c - dst.Pix[di+3] = 0xff - di += 4 - si++ - } - } - }) -} - -func copyGray16(dst *image.NRGBA, src *image.Gray16) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - for dstX := 0; dstX < dstW; dstX++ { - c := src.Pix[si] - dst.Pix[di+0] = c - dst.Pix[di+1] = c - dst.Pix[di+2] = c - dst.Pix[di+3] = 0xff - di += 4 - si += 2 - } - } - }) -} - -func copyYCbCr(dst *image.NRGBA, src *image.YCbCr) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - srcY := srcMinY + dstY - di := dst.PixOffset(0, dstY) - for dstX := 0; dstX < dstW; dstX++ { - srcX := srcMinX + dstX - - siy := (srcY-srcMinY)*src.YStride + (srcX - srcMinX) - - var sic int - switch src.SubsampleRatio { - case image.YCbCrSubsampleRatio444: - sic = (srcY-srcMinY)*src.CStride + (srcX - srcMinX) - case image.YCbCrSubsampleRatio422: - sic = (srcY-srcMinY)*src.CStride + (srcX/2 - srcMinX/2) - case image.YCbCrSubsampleRatio420: - sic = (srcY/2-srcMinY/2)*src.CStride + (srcX/2 - srcMinX/2) - case image.YCbCrSubsampleRatio440: - sic = (srcY/2-srcMinY/2)*src.CStride + (srcX - srcMinX) - default: - sic = src.COffset(srcX, srcY) - } - - y := int32(src.Y[siy]) - cb := int32(src.Cb[sic]) - 128 - cr := int32(src.Cr[sic]) - 128 - - r := (y<<16 + 91881*cr + 1<<15) >> 16 - if r > 255 { - r = 255 - } else if r < 0 { - r = 0 - } - - g := (y<<16 - 22554*cb - 46802*cr + 1<<15) >> 16 - if g > 255 { - g = 255 - } else if g < 0 { - g = 0 - } - - b := (y<<16 + 116130*cb + 1<<15) >> 16 - if b > 255 { - b = 255 - } else if b < 0 { - b = 0 - } - - dst.Pix[di+0] = uint8(r) - dst.Pix[di+1] = uint8(g) - dst.Pix[di+2] = uint8(b) - dst.Pix[di+3] = 255 - - di += 4 - } - } - }) -} - -func copyPaletted(dst *image.NRGBA, src *image.Paletted) { - srcMinX := src.Rect.Min.X - srcMinY := src.Rect.Min.Y - dstW := dst.Rect.Dx() - dstH := dst.Rect.Dy() - plen := len(src.Palette) - pnew := make([]color.NRGBA, plen) - for i := 0; i < plen; i++ { - pnew[i] = color.NRGBAModel.Convert(src.Palette[i]).(color.NRGBA) - } - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - si := src.PixOffset(srcMinX, srcMinY+dstY) - for dstX := 0; dstX < dstW; dstX++ { - c := pnew[src.Pix[si]] - dst.Pix[di+0] = c.R - dst.Pix[di+1] = c.G - dst.Pix[di+2] = c.B - dst.Pix[di+3] = c.A - di += 4 - si++ - } - } - }) -} - -func copyImage(dst *image.NRGBA, src image.Image) { - srcMinX := src.Bounds().Min.X - srcMinY := src.Bounds().Min.Y - dstW := dst.Bounds().Dx() - dstH := dst.Bounds().Dy() - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - di := dst.PixOffset(0, dstY) - for dstX := 0; dstX < dstW; dstX++ { - c := color.NRGBAModel.Convert(src.At(srcMinX+dstX, srcMinY+dstY)).(color.NRGBA) - dst.Pix[di+0] = c.R - dst.Pix[di+1] = c.G - dst.Pix[di+2] = c.B - dst.Pix[di+3] = c.A - di += 4 - } - } - }) -} - -// toNRGBA converts any image type to *image.NRGBA with min-point at (0, 0). -func toNRGBA(img image.Image) *image.NRGBA { - if img, ok := img.(*image.NRGBA); ok && img.Bounds().Min.Eq(image.ZP) { - return img - } - return Clone(img) -} diff --git a/vendor/github.com/disintegration/imaging/clone_test.go b/vendor/github.com/disintegration/imaging/clone_test.go deleted file mode 100644 index 36e309f0a..000000000 --- a/vendor/github.com/disintegration/imaging/clone_test.go +++ /dev/null @@ -1,247 +0,0 @@ -package imaging - -import ( - "image" - "image/color" - "testing" -) - -func TestClone(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Clone NRGBA", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, - }, - }, - { - "Clone NRGBA64", - &image.NRGBA64{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 8, - Pix: []uint8{ - 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, - 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, - }, - }, - { - "Clone RGBA", - &image.RGBA{ - Rect: image.Rect(-1, -1, 0, 2), - Stride: 1 * 4, - Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 3), - Stride: 1 * 4, - Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff}, - }, - }, - { - "Clone RGBA64", - &image.RGBA64{ - Rect: image.Rect(-1, -1, 0, 2), - Stride: 1 * 8, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, - 0xcc, 0xcc, 0xdd, 0xdd, 0xee, 0xee, 0xff, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 3), - Stride: 1 * 4, - Pix: []uint8{0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xaa, 0x33, 0xcc, 0xdd, 0xee, 0xff}, - }, - }, - { - "Clone Gray", - &image.Gray{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 1, - Pix: []uint8{0x11, 0xee}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff}, - }, - }, - { - "Clone Gray16", - &image.Gray16{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 2, - Pix: []uint8{0x11, 0x11, 0xee, 0xee}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{0x11, 0x11, 0x11, 0xff, 0xee, 0xee, 0xee, 0xff}, - }, - }, - { - "Clone Alpha", - &image.Alpha{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 1, - Pix: []uint8{0x11, 0xee}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{0xff, 0xff, 0xff, 0x11, 0xff, 0xff, 0xff, 0xee}, - }, - }, - { - "Clone YCbCr", - &image.YCbCr{ - Rect: image.Rect(-1, -1, 5, 0), - SubsampleRatio: image.YCbCrSubsampleRatio444, - YStride: 6, - CStride: 6, - Y: []uint8{0x00, 0xff, 0x7f, 0x26, 0x4b, 0x0e}, - Cb: []uint8{0x80, 0x80, 0x80, 0x6b, 0x56, 0xc0}, - Cr: []uint8{0x80, 0x80, 0x80, 0xc0, 0x4b, 0x76}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 6, 1), - Stride: 6 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x7f, 0x7f, 0xff, - 0x7f, 0x00, 0x00, 0xff, - 0x00, 0x7f, 0x00, 0xff, - 0x00, 0x00, 0x7f, 0xff, - }, - }, - }, - { - "Clone YCbCr 444", - &image.YCbCr{ - Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, - Cb: []uint8{0x55, 0xd4, 0xff, 0x8e, 0x2c, 0x01, 0x6b, 0xaa, 0xc0, 0x95, 0x56, 0x40, 0x80, 0x80, 0x80, 0x80}, - Cr: []uint8{0xff, 0xeb, 0x6b, 0x36, 0x15, 0x95, 0xc0, 0xb5, 0x76, 0x41, 0x4b, 0x8c, 0x80, 0x80, 0x80, 0x80}, - YStride: 4, - CStride: 4, - SubsampleRatio: image.YCbCrSubsampleRatio444, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - &image.NRGBA{ - Pix: []uint8{0xff, 0x0, 0x0, 0xff, 0xff, 0x0, 0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x49, 0xe1, 0xca, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0x0, 0xff, 0x7f, 0x0, 0x0, 0xff, 0x7f, 0x0, 0x7f, 0xff, 0x0, 0x0, 0x7f, 0xff, 0x0, 0x7f, 0x7f, 0xff, 0x0, 0x7f, 0x0, 0xff, 0x82, 0x7f, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, - Stride: 16, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - }, - { - "Clone YCbCr 440", - &image.YCbCr{ - Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, - Cb: []uint8{0x2c, 0x01, 0x6b, 0xaa, 0x80, 0x80, 0x80, 0x80}, - Cr: []uint8{0x15, 0x95, 0xc0, 0xb5, 0x80, 0x80, 0x80, 0x80}, - YStride: 4, - CStride: 4, - SubsampleRatio: image.YCbCrSubsampleRatio440, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - &image.NRGBA{ - Pix: []uint8{0x0, 0xb5, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x77, 0x0, 0x0, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0x0, 0xff, 0x1, 0xff, 0xff, 0xff, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, - Stride: 16, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - }, - { - "Clone YCbCr 422", - &image.YCbCr{ - Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, - Cb: []uint8{0xd4, 0x8e, 0x01, 0xaa, 0x95, 0x40, 0x80, 0x80}, - Cr: []uint8{0xeb, 0x36, 0x95, 0xb5, 0x41, 0x8c, 0x80, 0x80}, - YStride: 4, - CStride: 2, - SubsampleRatio: image.YCbCrSubsampleRatio422, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - &image.NRGBA{ - Pix: []uint8{0xe2, 0x0, 0xe1, 0xff, 0xff, 0x0, 0xfe, 0xff, 0x0, 0x4d, 0x36, 0xff, 0x49, 0xe1, 0xca, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0x0, 0x34, 0x33, 0xff, 0x1, 0x7f, 0x7e, 0xff, 0x5c, 0x58, 0x0, 0xff, 0x82, 0x7e, 0x0, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, - Stride: 16, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - }, - { - "Clone YCbCr 420", - &image.YCbCr{ - Y: []uint8{0x4c, 0x69, 0x1d, 0xb1, 0x96, 0xe2, 0x26, 0x34, 0xe, 0x59, 0x4b, 0x71, 0x0, 0x4c, 0x99, 0xff}, - Cb: []uint8{0x01, 0xaa, 0x80, 0x80}, - Cr: []uint8{0x95, 0xb5, 0x80, 0x80}, - YStride: 4, CStride: 2, - SubsampleRatio: image.YCbCrSubsampleRatio420, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - &image.NRGBA{ - Pix: []uint8{0x69, 0x69, 0x0, 0xff, 0x86, 0x86, 0x0, 0xff, 0x67, 0x0, 0x67, 0xff, 0xfb, 0x7d, 0xfb, 0xff, 0xb3, 0xb3, 0x0, 0xff, 0xff, 0xff, 0x1, 0xff, 0x70, 0x0, 0x70, 0xff, 0x7e, 0x0, 0x7e, 0xff, 0xe, 0xe, 0xe, 0xff, 0x59, 0x59, 0x59, 0xff, 0x4b, 0x4b, 0x4b, 0xff, 0x71, 0x71, 0x71, 0xff, 0x0, 0x0, 0x0, 0xff, 0x4c, 0x4c, 0x4c, 0xff, 0x99, 0x99, 0x99, 0xff, 0xff, 0xff, 0xff, 0xff}, - Stride: 16, - Rect: image.Rectangle{Min: image.Point{X: 0, Y: 0}, Max: image.Point{X: 4, Y: 4}}, - }, - }, - { - "Clone Paletted", - &image.Paletted{ - Rect: image.Rect(-1, -1, 5, 0), - Stride: 6 * 1, - Palette: color.Palette{ - color.NRGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xff}, - color.NRGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff}, - color.NRGBA{R: 0x7f, G: 0x7f, B: 0x7f, A: 0xff}, - color.NRGBA{R: 0x7f, G: 0x00, B: 0x00, A: 0xff}, - color.NRGBA{R: 0x00, G: 0x7f, B: 0x00, A: 0xff}, - color.NRGBA{R: 0x00, G: 0x00, B: 0x7f, A: 0xff}, - }, - Pix: []uint8{0x0, 0x1, 0x2, 0x3, 0x4, 0x5}, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 6, 1), - Stride: 6 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x7f, 0x7f, 0x7f, 0xff, - 0x7f, 0x00, 0x00, 0xff, - 0x00, 0x7f, 0x00, 0xff, - 0x00, 0x00, 0x7f, 0xff, - }, - }, - }, - } - - for _, d := range td { - got := Clone(d.src) - want := d.want - - delta := 0 - if _, ok := d.src.(*image.YCbCr); ok { - delta = 1 - } - - if !compareNRGBA(got, want, delta) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} diff --git a/vendor/github.com/disintegration/imaging/convolution.go b/vendor/github.com/disintegration/imaging/convolution.go index ed7540f05..9e6404dee 100644 --- a/vendor/github.com/disintegration/imaging/convolution.go +++ b/vendor/github.com/disintegration/imaging/convolution.go @@ -58,8 +58,6 @@ func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *imag m = 1 case 25: m = 2 - default: - return dst } i := 0 @@ -72,8 +70,8 @@ func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *imag } } - parallel(h, func(partStart, partEnd int) { - for y := partStart; y < partEnd; y++ { + parallel(0, h, func(ys <-chan int) { + for y := range ys { for x := 0; x < w; x++ { var r, g, b float64 for _, c := range coefs { diff --git a/vendor/github.com/disintegration/imaging/convolution_test.go b/vendor/github.com/disintegration/imaging/convolution_test.go deleted file mode 100644 index 5a824ead9..000000000 --- a/vendor/github.com/disintegration/imaging/convolution_test.go +++ /dev/null @@ -1,275 +0,0 @@ -package imaging - -import ( - "image" - "testing" -) - -func TestConvolve3x3(t *testing.T) { - testCases := []struct { - desc string - src image.Image - kernel [9]float64 - options *ConvolveOptions - want *image.NRGBA - }{ - { - "Convolve3x3 0x0", - &image.NRGBA{ - Rect: image.Rect(0, 0, 0, 0), - Stride: 0, - Pix: []uint8{}, - }, - [9]float64{ - 0, 0, 0, - 0, 1, 0, - 0, 0, 0, - }, - nil, - &image.NRGBA{Rect: image.Rect(0, 0, 0, 0)}, - }, - { - "Convolve3x3 4x4 identity", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - [9]float64{ - 0, 0, 0, - 0, 1, 0, - 0, 0, 0, - }, - nil, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "Convolve3x3 4x4 abs", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - [9]float64{ - 0, 0, 0, - 0, -1, 0, - 0, 0, 0, - }, - &ConvolveOptions{Abs: true}, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "Convolve3x3 4x4 bias", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - [9]float64{ - 0, 0, 0, - 0, 1, 0, - 0, 0, 0, - }, - &ConvolveOptions{Bias: 0x10}, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x10, 0x11, 0x12, 0x03, 0x14, 0x15, 0x16, 0x07, 0x18, 0x19, 0x1a, 0x0b, 0x1c, 0x1d, 0x1e, 0x0f, - 0x20, 0x21, 0x22, 0x13, 0x24, 0x25, 0x26, 0x17, 0x28, 0x29, 0x2a, 0x1b, 0x2c, 0x2d, 0x2e, 0x1f, - 0x30, 0x31, 0x32, 0x23, 0x34, 0x35, 0x36, 0x27, 0x38, 0x39, 0x3a, 0x2b, 0x3c, 0x3d, 0x3e, 0x2f, - 0x40, 0x41, 0x42, 0x33, 0x44, 0x45, 0x46, 0x37, 0x48, 0x49, 0x4a, 0x3b, 0x4c, 0x4d, 0x4e, 0x3f, - }, - }, - }, - { - "Convolve3x3 4x4 norm", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - [9]float64{ - 1, 1, 1, - 1, 1, 1, - 1, 1, 1, - }, - &ConvolveOptions{Normalize: true}, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x07, 0x08, 0x09, 0x03, 0x09, 0x0a, 0x0b, 0x07, 0x0d, 0x0e, 0x0f, 0x0b, 0x10, 0x11, 0x12, 0x0f, - 0x11, 0x12, 0x13, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1d, 0x1f, - 0x21, 0x22, 0x23, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2b, 0x2c, 0x2d, 0x2f, - 0x2c, 0x2d, 0x2e, 0x33, 0x2f, 0x30, 0x31, 0x37, 0x33, 0x34, 0x35, 0x3b, 0x35, 0x36, 0x37, 0x3f, - }, - }, - }, - { - "Convolve3x3 3x3 laplacian", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x01, 0xff, 0x00, 0x01, 0x02, 0xff, 0x00, 0x01, 0x03, 0xff, - 0x00, 0x01, 0x04, 0xff, 0x10, 0x10, 0x10, 0xff, 0x00, 0x01, 0x05, 0xff, - 0x00, 0x01, 0x06, 0xff, 0x00, 0x01, 0x07, 0xff, 0x00, 0x01, 0x08, 0xff, - }, - }, - [9]float64{ - -1, -1, -1, - -1, 8, -1, - -1, -1, -1, - }, - nil, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x80, 0x78, 0x5c, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - } - - for _, tc := range testCases { - got := Convolve3x3(tc.src, tc.kernel, tc.options) - want := tc.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: want %#v got %#v", tc.desc, want, got) - } - } -} - -func TestConvolve5x5(t *testing.T) { - testCases := []struct { - desc string - src image.Image - kernel [25]float64 - options *ConvolveOptions - want *image.NRGBA - }{ - { - "Convolve5x5 4x4 translate", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - [25]float64{ - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, - }, - nil, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x28, 0x29, 0x2a, 0x03, 0x2c, 0x2d, 0x2e, 0x07, 0x2c, 0x2d, 0x2e, 0x0b, 0x2c, 0x2d, 0x2e, 0x0f, - 0x38, 0x39, 0x3a, 0x13, 0x3c, 0x3d, 0x3e, 0x17, 0x3c, 0x3d, 0x3e, 0x1b, 0x3c, 0x3d, 0x3e, 0x1f, - 0x38, 0x39, 0x3a, 0x23, 0x3c, 0x3d, 0x3e, 0x27, 0x3c, 0x3d, 0x3e, 0x2b, 0x3c, 0x3d, 0x3e, 0x2f, - 0x38, 0x39, 0x3a, 0x33, 0x3c, 0x3d, 0x3e, 0x37, 0x3c, 0x3d, 0x3e, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - } - - for _, tc := range testCases { - got := Convolve5x5(tc.src, tc.kernel, tc.options) - want := tc.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: want %#v got %#v", tc.desc, want, got) - } - } -} - -func BenchmarkConvolve3x3(b *testing.B) { - b.StopTimer() - img, err := Open("testdata/lena_512.png") - if err != nil { - b.Fatalf("Open: %v", err) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - Convolve3x3( - img, - [9]float64{ - -1, -1, 0, - -1, 0, 1, - 0, 1, 1, - }, - nil, - ) - } -} - -func BenchmarkConvolve5x5(b *testing.B) { - b.StopTimer() - img, err := Open("testdata/lena_512.png") - if err != nil { - b.Fatalf("Open: %v", err) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - Convolve5x5( - img, - [25]float64{ - -1, -1, -1, -1, 0, - -1, -1, -1, 0, 1, - -1, -1, 0, 1, 1, - -1, 0, 1, 1, 1, - 0, 1, 1, 1, 1, - }, - nil, - ) - } -} diff --git a/vendor/github.com/disintegration/imaging/doc.go b/vendor/github.com/disintegration/imaging/doc.go new file mode 100644 index 000000000..5d59b46e2 --- /dev/null +++ b/vendor/github.com/disintegration/imaging/doc.go @@ -0,0 +1,7 @@ +/* +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, not premultiplied by alpha). +*/ +package imaging diff --git a/vendor/github.com/disintegration/imaging/effects.go b/vendor/github.com/disintegration/imaging/effects.go index f358a48ea..b16781f12 100644 --- a/vendor/github.com/disintegration/imaging/effects.go +++ b/vendor/github.com/disintegration/imaging/effects.go @@ -18,11 +18,9 @@ func gaussianBlurKernel(x, sigma float64) float64 { // func Blur(img image.Image, sigma float64) *image.NRGBA { if sigma <= 0 { - // sigma parameter must be positive! return Clone(img) } - src := toNRGBA(img) radius := int(math.Ceil(sigma * 3.0)) kernel := make([]float64, radius+1) @@ -30,54 +28,50 @@ func Blur(img image.Image, sigma float64) *image.NRGBA { kernel[i] = gaussianBlurKernel(float64(i), sigma) } - var dst *image.NRGBA - dst = blurHorizontal(src, kernel) - dst = blurVertical(dst, kernel) - - return dst + return blurVertical(blurHorizontal(img, kernel), kernel) } -func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA { +func blurHorizontal(img image.Image, kernel []float64) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) radius := len(kernel) - 1 - width := src.Bounds().Max.X - height := src.Bounds().Max.Y - - dst := image.NewNRGBA(image.Rect(0, 0, width, height)) - - parallel(width, func(partStart, partEnd int) { - for x := partStart; x < partEnd; x++ { - start := x - radius - if start < 0 { - start = 0 - } - end := x + radius - if end > width-1 { - end = width - 1 - } - - weightSum := 0.0 - for ix := start; ix <= end; ix++ { - weightSum += kernel[absint(x-ix)] - } + parallel(0, src.h, func(ys <-chan int) { + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + for x := 0; x < src.w; x++ { + min := x - radius + if min < 0 { + min = 0 + } + max := x + radius + if max > src.w-1 { + max = src.w - 1 + } - for y := 0; y < height; y++ { - var r, g, b, a float64 - for ix := start; ix <= end; ix++ { + var r, g, b, a, wsum float64 + for ix := min; ix <= max; ix++ { + i := ix * 4 weight := kernel[absint(x-ix)] - i := y*src.Stride + ix*4 - wa := float64(src.Pix[i+3]) * weight - r += float64(src.Pix[i+0]) * wa - g += float64(src.Pix[i+1]) * wa - b += float64(src.Pix[i+2]) * wa + wsum += weight + wa := float64(scanLine[i+3]) * weight + r += float64(scanLine[i+0]) * wa + g += float64(scanLine[i+1]) * wa + b += float64(scanLine[i+2]) * wa a += wa } + if a != 0 { + r /= a + g /= a + b /= a + } j := y*dst.Stride + x*4 - dst.Pix[j+0] = clamp(r / a) - dst.Pix[j+1] = clamp(g / a) - dst.Pix[j+2] = clamp(b / a) - dst.Pix[j+3] = clamp(a / weightSum) + dst.Pix[j+0] = clamp(r) + dst.Pix[j+1] = clamp(g) + dst.Pix[j+2] = clamp(b) + dst.Pix[j+3] = clamp(a / wsum) } } }) @@ -85,47 +79,47 @@ func blurHorizontal(src *image.NRGBA, kernel []float64) *image.NRGBA { return dst } -func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA { +func blurVertical(img image.Image, kernel []float64) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) radius := len(kernel) - 1 - width := src.Bounds().Max.X - height := src.Bounds().Max.Y - - dst := image.NewNRGBA(image.Rect(0, 0, width, height)) - - parallel(height, func(partStart, partEnd int) { - for y := partStart; y < partEnd; y++ { - start := y - radius - if start < 0 { - start = 0 - } - - end := y + radius - if end > height-1 { - end = height - 1 - } - weightSum := 0.0 - for iy := start; iy <= end; iy++ { - weightSum += kernel[absint(y-iy)] - } + parallel(0, src.w, func(xs <-chan int) { + scanLine := make([]uint8, src.h*4) + for x := range xs { + src.scan(x, 0, x+1, src.h, scanLine) + for y := 0; y < src.h; y++ { + min := y - radius + if min < 0 { + min = 0 + } + max := y + radius + if max > src.h-1 { + max = src.h - 1 + } - for x := 0; x < width; x++ { - var r, g, b, a float64 - for iy := start; iy <= end; iy++ { + var r, g, b, a, wsum float64 + for iy := min; iy <= max; iy++ { + i := iy * 4 weight := kernel[absint(y-iy)] - i := iy*src.Stride + x*4 - wa := float64(src.Pix[i+3]) * weight - r += float64(src.Pix[i+0]) * wa - g += float64(src.Pix[i+1]) * wa - b += float64(src.Pix[i+2]) * wa + wsum += weight + wa := float64(scanLine[i+3]) * weight + r += float64(scanLine[i+0]) * wa + g += float64(scanLine[i+1]) * wa + b += float64(scanLine[i+2]) * wa a += wa } + if a != 0 { + r /= a + g /= a + b /= a + } j := y*dst.Stride + x*4 - dst.Pix[j+0] = clamp(r / a) - dst.Pix[j+1] = clamp(g / a) - dst.Pix[j+2] = clamp(b / a) - dst.Pix[j+3] = clamp(a / weightSum) + dst.Pix[j+0] = clamp(r) + dst.Pix[j+1] = clamp(g) + dst.Pix[j+2] = clamp(b) + dst.Pix[j+3] = clamp(a / wsum) } } }) @@ -142,31 +136,27 @@ func blurVertical(src *image.NRGBA, kernel []float64) *image.NRGBA { // func Sharpen(img image.Image, sigma float64) *image.NRGBA { if sigma <= 0 { - // sigma parameter must be positive! return Clone(img) } - src := toNRGBA(img) + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) blurred := Blur(img, sigma) - width := src.Bounds().Max.X - height := src.Bounds().Max.Y - dst := image.NewNRGBA(image.Rect(0, 0, width, height)) - - parallel(height, func(partStart, partEnd int) { - for y := partStart; y < partEnd; y++ { - for x := 0; x < width; x++ { - i := y*src.Stride + x*4 - for j := 0; j < 4; j++ { - k := i + j - val := int(src.Pix[k])<<1 - int(blurred.Pix[k]) - if val < 0 { - val = 0 - } else if val > 255 { - val = 255 - } - dst.Pix[k] = uint8(val) + parallel(0, src.h, func(ys <-chan int) { + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + j := y * dst.Stride + for i := 0; i < src.w*4; i++ { + val := int(scanLine[i])<<1 - int(blurred.Pix[j]) + if val < 0 { + val = 0 + } else if val > 0xff { + val = 0xff } + dst.Pix[j] = uint8(val) + j++ } } }) diff --git a/vendor/github.com/disintegration/imaging/effects_test.go b/vendor/github.com/disintegration/imaging/effects_test.go deleted file mode 100644 index 9c787cb49..000000000 --- a/vendor/github.com/disintegration/imaging/effects_test.go +++ /dev/null @@ -1,254 +0,0 @@ -package imaging - -import ( - "image" - "testing" -) - -func TestBlur(t *testing.T) { - td := []struct { - desc string - src image.Image - sigma float64 - want *image.NRGBA - }{ - { - "Blur 3x3 0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - 0.0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - }, - { - "Blur 3x3 0.5", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - 0.5, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0xaa, 0xff, 0x04, 0x66, 0xaa, 0xff, 0x18, 0x66, 0xaa, 0xff, 0x04, - 0x66, 0xaa, 0xff, 0x18, 0x66, 0xaa, 0xff, 0x9e, 0x66, 0xaa, 0xff, 0x18, - 0x66, 0xaa, 0xff, 0x04, 0x66, 0xaa, 0xff, 0x18, 0x66, 0xaa, 0xff, 0x04, - }, - }, - }, - { - "Blur 3x3 10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x66, 0xaa, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - 10, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0xaa, 0xff, 0x1c, 0x66, 0xaa, 0xff, 0x1c, 0x66, 0xaa, 0xff, 0x1c, - 0x66, 0xaa, 0xff, 0x1c, 0x66, 0xaa, 0xff, 0x1c, 0x66, 0xaa, 0xff, 0x1c, - 0x66, 0xaa, 0xff, 0x1c, 0x66, 0xaa, 0xff, 0x1c, 0x66, 0xaa, 0xff, 0x1c, - }, - }, - }, - } - for _, d := range td { - got := Blur(d.src, d.sigma) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestBlurGolden(t *testing.T) { - src, err := Open("testdata/lena_128.png") - if err != nil { - t.Errorf("Open: %v", err) - } - for name, sigma := range map[string]float64{ - "out_blur_0.5.png": 0.5, - "out_blur_1.5.png": 1.5, - } { - got := Blur(src, sigma) - want, err := Open("testdata/" + name) - if err != nil { - t.Errorf("Open: %v", err) - } - if !compareNRGBA(got, toNRGBA(want), 0) { - t.Errorf("resulting image differs from golden: %s", name) - } - } -} - -func BenchmarkBlur(b *testing.B) { - b.StopTimer() - img, err := Open("testdata/lena_512.png") - if err != nil { - b.Fatalf("Open: %v", err) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - Blur(img, 3) - } -} - -func TestSharpen(t *testing.T) { - td := []struct { - desc string - src image.Image - sigma float64 - want *image.NRGBA - }{ - { - "Sharpen 3x3 0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, 0x77, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - }, - }, - 0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, 0x77, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - }, - }, - }, - { - "Sharpen 3x3 0.5", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, 0x77, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - }, - }, - 0.5, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0x66, 0x66, 0x66, 0x64, 0x64, 0x64, 0x64, 0x66, 0x66, 0x66, 0x66, - 0x64, 0x64, 0x64, 0x64, 0x7d, 0x7d, 0x7d, 0x7e, 0x64, 0x64, 0x64, 0x64, - 0x66, 0x66, 0x66, 0x66, 0x64, 0x64, 0x64, 0x64, 0x66, 0x66, 0x66, 0x66, - }, - }, - }, - { - "Sharpen 3x3 100", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x77, 0x77, 0x77, 0x77, 0x66, 0x66, 0x66, 0x66, - 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, - }, - }, - 100, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 3), - Stride: 3 * 4, - Pix: []uint8{ - 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x64, 0x64, 0x64, 0x86, 0x86, 0x86, 0x86, 0x64, 0x64, 0x64, 0x64, - 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, - }, - }, - }, - { - "Sharpen 3x1 10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 0), - Stride: 3 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - }, - }, - 10, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 1), - Stride: 3 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Sharpen(d.src, d.sigma) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestSharpenGolden(t *testing.T) { - src, err := Open("testdata/lena_128.png") - if err != nil { - t.Errorf("Open: %v", err) - } - for name, sigma := range map[string]float64{ - "out_sharpen_0.5.png": 0.5, - "out_sharpen_1.5.png": 1.5, - } { - got := Sharpen(src, sigma) - want, err := Open("testdata/" + name) - if err != nil { - t.Errorf("Open: %v", err) - } - if !compareNRGBA(got, toNRGBA(want), 0) { - t.Errorf("resulting image differs from golden: %s", name) - } - } -} - -func BenchmarkSharpen(b *testing.B) { - b.StopTimer() - img, err := Open("testdata/lena_512.png") - if err != nil { - b.Fatalf("Open: %v", err) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - Sharpen(img, 3) - } -} diff --git a/vendor/github.com/disintegration/imaging/example_test.go b/vendor/github.com/disintegration/imaging/example_test.go deleted file mode 100644 index d79451f03..000000000 --- a/vendor/github.com/disintegration/imaging/example_test.go +++ /dev/null @@ -1,58 +0,0 @@ -package imaging_test - -import ( - "image" - "image/color" - "log" - - "github.com/disintegration/imaging" -) - -func Example() { - // Open the test image. - src, err := imaging.Open("testdata/lena_512.png") - if err != nil { - log.Fatalf("Open failed: %v", err) - } - - // Crop the original image to 350x350px size using the center anchor. - src = imaging.CropAnchor(src, 350, 350, imaging.Center) - - // Resize the cropped image to width = 256px preserving the aspect ratio. - src = imaging.Resize(src, 256, 0, imaging.Lanczos) - - // Create a blurred version of the image. - img1 := imaging.Blur(src, 2) - - // 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(512, 512, color.NRGBA{0, 0, 0, 0}) - dst = imaging.Paste(dst, img1, image.Pt(0, 0)) - dst = imaging.Paste(dst, img2, image.Pt(0, 256)) - dst = imaging.Paste(dst, img3, image.Pt(256, 0)) - dst = imaging.Paste(dst, img4, image.Pt(256, 256)) - - // Save the resulting image using JPEG format. - err = imaging.Save(dst, "testdata/out_example.jpg") - if err != nil { - log.Fatalf("Save failed: %v", err) - } -} diff --git a/vendor/github.com/disintegration/imaging/helpers.go b/vendor/github.com/disintegration/imaging/helpers.go index d4e73f120..7193e473c 100644 --- a/vendor/github.com/disintegration/imaging/helpers.go +++ b/vendor/github.com/disintegration/imaging/helpers.go @@ -1,15 +1,10 @@ -// Package imaging provides basic image manipulation functions (resize, rotate, flip, crop, etc.). -// This package is based on the standard Go image package and works best along with it. -// -// Image manipulation functions provided by the package take any image type -// that implements `image.Image` interface as an input, and return a new image of -// `*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha). package imaging import ( "errors" "image" "image/color" + "image/draw" "image/gif" "image/jpeg" "image/png" @@ -56,32 +51,48 @@ var ( ErrUnsupportedFormat = errors.New("imaging: unsupported image format") ) +type fileSystem interface { + Create(string) (io.WriteCloser, error) + Open(string) (io.ReadCloser, error) +} + +type localFS struct{} + +func (localFS) Create(name string) (io.WriteCloser, error) { return os.Create(name) } +func (localFS) Open(name string) (io.ReadCloser, error) { return os.Open(name) } + +var fs fileSystem = localFS{} + // Decode reads an image from r. func Decode(r io.Reader) (image.Image, error) { img, _, err := image.Decode(r) - if err != nil { - return nil, err - } - return toNRGBA(img), nil + return img, err } // Open loads an image from file func Open(filename string) (image.Image, error) { - file, err := os.Open(filename) + file, err := fs.Open(filename) if err != nil { return nil, err } defer file.Close() - img, err := Decode(file) - return img, err + return Decode(file) } type encodeConfig struct { - jpegQuality int + jpegQuality int + gifNumColors int + gifQuantizer draw.Quantizer + gifDrawer draw.Drawer + pngCompressionLevel png.CompressionLevel } var defaultEncodeConfig = encodeConfig{ - jpegQuality: 95, + jpegQuality: 95, + gifNumColors: 256, + gifQuantizer: nil, + gifDrawer: nil, + pngCompressionLevel: png.DefaultCompression, } // EncodeOption sets an optional parameter for the Encode and Save functions. @@ -95,6 +106,38 @@ func JPEGQuality(quality int) EncodeOption { } } +// GIFNumColors returns an EncodeOption that sets the maximum number of colors +// used in the GIF-encoded image. It ranges from 1 to 256. Default is 256. +func GIFNumColors(numColors int) EncodeOption { + return func(c *encodeConfig) { + c.gifNumColors = numColors + } +} + +// GIFQuantizer returns an EncodeOption that sets the quantizer that is used to produce +// a palette of the GIF-encoded image. +func GIFQuantizer(quantizer draw.Quantizer) EncodeOption { + return func(c *encodeConfig) { + c.gifQuantizer = quantizer + } +} + +// GIFDrawer returns an EncodeOption that sets the drawer that is used to convert +// the source image to the desired palette of the GIF-encoded image. +func GIFDrawer(drawer draw.Drawer) EncodeOption { + return func(c *encodeConfig) { + c.gifDrawer = drawer + } +} + +// PNGCompressionLevel returns an EncodeOption that sets the compression level +// of the PNG-encoded image. Default is png.DefaultCompression. +func PNGCompressionLevel(level png.CompressionLevel) EncodeOption { + return func(c *encodeConfig) { + c.pngCompressionLevel = level + } +} + // Encode writes the image img to w in the specified format (JPEG, PNG, GIF, TIFF or BMP). func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) error { cfg := defaultEncodeConfig @@ -122,13 +165,22 @@ func Encode(w io.Writer, img image.Image, format Format, opts ...EncodeOption) e } case PNG: - err = png.Encode(w, img) + enc := png.Encoder{CompressionLevel: cfg.pngCompressionLevel} + err = enc.Encode(w, img) + case GIF: - err = gif.Encode(w, img, &gif.Options{NumColors: 256}) + err = gif.Encode(w, img, &gif.Options{ + NumColors: cfg.gifNumColors, + Quantizer: cfg.gifQuantizer, + Drawer: cfg.gifDrawer, + }) + case TIFF: err = tiff.Encode(w, img, &tiff.Options{Compression: tiff.Deflate, Predictor: true}) + case BMP: err = bmp.Encode(w, img) + default: err = ErrUnsupportedFormat } @@ -163,11 +215,17 @@ func Save(img image.Image, filename string, opts ...EncodeOption) (err error) { return ErrUnsupportedFormat } - file, err := os.Create(filename) + file, err := fs.Create(filename) if err != nil { return err } - defer file.Close() + + defer func() { + cerr := file.Close() + if err == nil { + err = cerr + } + }() return Encode(file, img, f, opts...) } @@ -185,16 +243,38 @@ func New(width, height int, fillColor color.Color) *image.NRGBA { return dst } - cs := []uint8{c.R, c.G, c.B, c.A} - - // fill the first row + // Fill the first row. + i := 0 for x := 0; x < width; x++ { - copy(dst.Pix[x*4:(x+1)*4], cs) - } - // copy the first row to other rows - for y := 1; y < height; y++ { - copy(dst.Pix[y*dst.Stride:y*dst.Stride+width*4], dst.Pix[0:width*4]) + dst.Pix[i+0] = c.R + dst.Pix[i+1] = c.G + dst.Pix[i+2] = c.B + dst.Pix[i+3] = c.A + i += 4 } + // Copy the first row to other rows. + size := width * 4 + parallel(1, height, func(ys <-chan int) { + for y := range ys { + i = y * dst.Stride + copy(dst.Pix[i:i+size], dst.Pix[0:size]) + } + }) + + return dst +} + +// Clone returns a copy of the given image. +func Clone(img image.Image) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) + size := src.w * 4 + parallel(0, src.h, func(ys <-chan int) { + for y := range ys { + i := y * dst.Stride + src.scan(0, y, src.w, y+1, dst.Pix[i:i+size]) + } + }) return dst } diff --git a/vendor/github.com/disintegration/imaging/helpers_test.go b/vendor/github.com/disintegration/imaging/helpers_test.go deleted file mode 100644 index c3b87f23c..000000000 --- a/vendor/github.com/disintegration/imaging/helpers_test.go +++ /dev/null @@ -1,159 +0,0 @@ -package imaging - -import ( - "bytes" - "image" - "image/color" - "testing" -) - -func compareNRGBA(img1, img2 *image.NRGBA, delta int) bool { - if !img1.Rect.Eq(img2.Rect) { - return false - } - - if len(img1.Pix) != len(img2.Pix) { - return false - } - - for i := 0; i < len(img1.Pix); i++ { - if absint(int(img1.Pix[i])-int(img2.Pix[i])) > delta { - return false - } - } - - return true -} - -func TestEncodeDecode(t *testing.T) { - imgWithAlpha := image.NewNRGBA(image.Rect(0, 0, 3, 3)) - imgWithAlpha.Pix = []uint8{ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, - 244, 245, 246, 247, 248, 249, 250, 252, 252, 253, 254, 255, - } - - imgWithoutAlpha := image.NewNRGBA(image.Rect(0, 0, 3, 3)) - imgWithoutAlpha.Pix = []uint8{ - 0, 1, 2, 255, 4, 5, 6, 255, 8, 9, 10, 255, - 127, 128, 129, 255, 131, 132, 133, 255, 135, 136, 137, 255, - 244, 245, 246, 255, 248, 249, 250, 255, 252, 253, 254, 255, - } - - for _, format := range []Format{JPEG, PNG, GIF, BMP, TIFF} { - img := imgWithoutAlpha - if format == PNG { - img = imgWithAlpha - } - - buf := &bytes.Buffer{} - err := Encode(buf, img, format) - if err != nil { - t.Errorf("fail encoding format %s", format) - continue - } - - img2, err := Decode(buf) - if err != nil { - t.Errorf("fail decoding format %s", format) - continue - } - img2cloned := Clone(img2) - - delta := 0 - if format == JPEG { - delta = 3 - } else if format == GIF { - delta = 16 - } - - if !compareNRGBA(img, img2cloned, delta) { - t.Errorf("test [DecodeEncode %s] failed: %#v %#v", format, img, img2cloned) - continue - } - } - - buf := &bytes.Buffer{} - err := Encode(buf, imgWithAlpha, JPEG) - if err != nil { - t.Errorf("failed encoding alpha to JPEG format %s", err) - } - - buf = &bytes.Buffer{} - err = Encode(buf, imgWithAlpha, Format(100)) - if err != ErrUnsupportedFormat { - t.Errorf("expected ErrUnsupportedFormat") - } - - buf = bytes.NewBuffer([]byte("bad data")) - _, err = Decode(buf) - if err == nil { - t.Errorf("decoding bad data, expected error") - } -} - -func TestNew(t *testing.T) { - td := []struct { - desc string - w, h int - c color.Color - dstBounds image.Rectangle - dstPix []uint8 - }{ - { - "New 1x1 black", - 1, 1, - color.NRGBA{0, 0, 0, 0}, - image.Rect(0, 0, 1, 1), - []uint8{0x00, 0x00, 0x00, 0x00}, - }, - { - "New 1x2 red", - 1, 2, - color.NRGBA{255, 0, 0, 255}, - image.Rect(0, 0, 1, 2), - []uint8{0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff}, - }, - { - "New 2x1 white", - 2, 1, - color.NRGBA{255, 255, 255, 255}, - image.Rect(0, 0, 2, 1), - []uint8{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, - }, - { - "New 0x0 white", - 0, 0, - color.NRGBA{255, 255, 255, 255}, - image.Rect(0, 0, 0, 0), - nil, - }, - } - - for _, d := range td { - got := New(d.w, d.h, d.c) - want := image.NewNRGBA(d.dstBounds) - want.Pix = d.dstPix - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestFormats(t *testing.T) { - formatNames := map[Format]string{ - JPEG: "JPEG", - PNG: "PNG", - GIF: "GIF", - BMP: "BMP", - TIFF: "TIFF", - Format(-1): "Unsupported", - } - for format, name := range formatNames { - got := format.String() - if got != name { - t.Errorf("test [Format names] failed: got %#v want %#v", got, name) - continue - } - } -} diff --git a/vendor/github.com/disintegration/imaging/histogram.go b/vendor/github.com/disintegration/imaging/histogram.go index 967ee6a25..5bcb001ca 100644 --- a/vendor/github.com/disintegration/imaging/histogram.go +++ b/vendor/github.com/disintegration/imaging/histogram.go @@ -2,6 +2,7 @@ package imaging import ( "image" + "sync" ) // Histogram returns a normalized histogram of an image. @@ -9,35 +10,42 @@ import ( // Resulting histogram is represented as an array of 256 floats, where // histogram[i] is a probability of a pixel being of a particular luminance i. func Histogram(img image.Image) [256]float64 { - src := toNRGBA(img) - width := src.Bounds().Max.X - height := src.Bounds().Max.Y - + var mu sync.Mutex var histogram [256]float64 var total float64 - if width == 0 || height == 0 { + src := newScanner(img) + if src.w == 0 || src.h == 0 { return histogram } - for y := 0; y < height; y++ { - for x := 0; x < width; x++ { - i := y*src.Stride + x*4 - - r := src.Pix[i+0] - g := src.Pix[i+1] - b := src.Pix[i+2] - - y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b) - - histogram[int(y+0.5)]++ - total++ + parallel(0, src.h, func(ys <-chan int) { + var tmpHistogram [256]float64 + var tmpTotal float64 + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + i := 0 + for x := 0; x < src.w; x++ { + r := scanLine[i+0] + g := scanLine[i+1] + b := scanLine[i+2] + y := 0.299*float32(r) + 0.587*float32(g) + 0.114*float32(b) + tmpHistogram[int(y+0.5)]++ + tmpTotal++ + i += 4 + } } - } + mu.Lock() + for i := 0; i < 256; i++ { + histogram[i] += tmpHistogram[i] + } + total += tmpTotal + mu.Unlock() + }) for i := 0; i < 256; i++ { histogram[i] = histogram[i] / total } - return histogram } diff --git a/vendor/github.com/disintegration/imaging/histogram_test.go b/vendor/github.com/disintegration/imaging/histogram_test.go deleted file mode 100644 index 10f4c3fef..000000000 --- a/vendor/github.com/disintegration/imaging/histogram_test.go +++ /dev/null @@ -1,42 +0,0 @@ -package imaging - -import ( - "image" - "image/color" - "testing" -) - -func TestHistogram(t *testing.T) { - b := image.Rectangle{image.Point{0, 0}, image.Point{2, 2}} - - i1 := image.NewRGBA(b) - i1.Set(0, 0, image.Black) - i1.Set(1, 0, image.White) - i1.Set(1, 1, image.White) - i1.Set(0, 1, color.Gray{123}) - - h := Histogram(i1) - if h[0] != 0.25 || h[123] != 0.25 || h[255] != 0.5 { - t.Errorf("Incorrect histogram for image i1") - } - - i2 := image.NewRGBA(b) - i2.Set(0, 0, color.Gray{51}) - i2.Set(0, 1, color.Gray{14}) - i2.Set(1, 0, color.Gray{14}) - - h = Histogram(i2) - if h[14] != 0.5 || h[51] != 0.25 || h[0] != 0.25 { - t.Errorf("Incorrect histogram for image i2") - } - - b = image.Rectangle{image.Point{0, 0}, image.Point{0, 0}} - i3 := image.NewRGBA(b) - h = Histogram(i3) - for _, val := range h { - if val != 0 { - t.Errorf("Histogram for an empty image should be a zero histogram.") - return - } - } -} diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/disintegration/imaging/resize.go index cd5bfb5d8..97f498a0a 100644 --- a/vendor/github.com/disintegration/imaging/resize.go +++ b/vendor/github.com/disintegration/imaging/resize.go @@ -24,17 +24,17 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWei for v := 0; v < dstSize; v++ { fu := (float64(v)+0.5)*du - 0.5 - startu := int(math.Ceil(fu - ru)) - if startu < 0 { - startu = 0 + begin := int(math.Ceil(fu - ru)) + if begin < 0 { + begin = 0 } - endu := int(math.Floor(fu + ru)) - if endu > srcSize-1 { - endu = srcSize - 1 + end := int(math.Floor(fu + ru)) + if end > srcSize-1 { + end = srcSize - 1 } var sum float64 - for u := startu; u <= endu; u++ { + for u := begin; u <= end; u++ { w := filter.Kernel((float64(u) - fu) / scale) if w != 0 { sum += w @@ -67,7 +67,6 @@ func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWei // func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { dstW, dstH := width, height - if dstW < 0 || dstH < 0 { return &image.NRGBA{} } @@ -75,16 +74,13 @@ func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NR return &image.NRGBA{} } - src := toNRGBA(img) - - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - + srcW := img.Bounds().Dx() + srcH := img.Bounds().Dy() if srcW <= 0 || srcH <= 0 { return &image.NRGBA{} } - // if new width or height is 0 then preserve aspect ratio, minimum 1px + // If new width or height is 0 then preserve aspect ratio, minimum 1px. if dstW == 0 { tmpW := float64(dstH) * float64(srcW) / float64(srcH) dstW = int(math.Max(1.0, math.Floor(tmpW+0.5))) @@ -94,57 +90,45 @@ func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NR dstH = int(math.Max(1.0, math.Floor(tmpH+0.5))) } - var dst *image.NRGBA - - if filter.Support <= 0.0 { - // nearest-neighbor special case - dst = resizeNearest(src, dstW, dstH) - - } else { - // two-pass resize - if srcW != dstW { - dst = resizeHorizontal(src, dstW, filter) - } else { - dst = src - } - - if srcH != dstH { - dst = resizeVertical(dst, dstH, filter) - } + if filter.Support <= 0 { + // Nearest-neighbor special case. + return resizeNearest(img, dstW, dstH) } - return dst + if srcW != dstW && srcH != dstH { + return resizeVertical(resizeHorizontal(img, dstW, filter), dstH, filter) + } + if srcW != dstW { + return resizeHorizontal(img, dstW, filter) + } + if srcH != dstH { + return resizeVertical(img, dstH, filter) + } + return Clone(img) } -func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image.NRGBA { - srcBounds := src.Bounds() - srcW := srcBounds.Max.X - srcH := srcBounds.Max.Y - - dstW := width - dstH := srcH - - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - weights := precomputeWeights(dstW, srcW, filter) - - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { - i0 := dstY * src.Stride - j0 := dstY * dst.Stride - for dstX := 0; dstX < dstW; dstX++ { +func resizeHorizontal(img image.Image, width int, filter ResampleFilter) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, width, src.h)) + weights := precomputeWeights(width, src.w, filter) + parallel(0, src.h, func(ys <-chan int) { + scanLine := make([]uint8, src.w*4) + for y := range ys { + src.scan(0, y, src.w, y+1, scanLine) + j0 := y * dst.Stride + for x := 0; x < width; x++ { var r, g, b, a float64 - for _, w := range weights[dstX] { - i := i0 + w.index*4 - aw := float64(src.Pix[i+3]) * w.weight - r += float64(src.Pix[i+0]) * aw - g += float64(src.Pix[i+1]) * aw - b += float64(src.Pix[i+2]) * aw + for _, w := range weights[x] { + i := w.index * 4 + aw := float64(scanLine[i+3]) * w.weight + r += float64(scanLine[i+0]) * aw + g += float64(scanLine[i+1]) * aw + b += float64(scanLine[i+2]) * aw a += aw } if a != 0 { aInv := 1 / a - j := j0 + dstX*4 + j := j0 + x*4 dst.Pix[j+0] = clamp(r * aInv) dst.Pix[j+1] = clamp(g * aInv) dst.Pix[j+2] = clamp(b * aInv) @@ -153,37 +137,30 @@ func resizeHorizontal(src *image.NRGBA, width int, filter ResampleFilter) *image } } }) - return dst } -func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image.NRGBA { - srcBounds := src.Bounds() - srcW := srcBounds.Max.X - srcH := srcBounds.Max.Y - - dstW := srcW - dstH := height - - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - weights := precomputeWeights(dstH, srcH, filter) - - parallel(dstW, func(partStart, partEnd int) { - for dstX := partStart; dstX < partEnd; dstX++ { - for dstY := 0; dstY < dstH; dstY++ { +func resizeVertical(img image.Image, height int, filter ResampleFilter) *image.NRGBA { + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, src.w, height)) + weights := precomputeWeights(height, src.h, filter) + parallel(0, src.w, func(xs <-chan int) { + scanLine := make([]uint8, src.h*4) + for x := range xs { + src.scan(x, 0, x+1, src.h, scanLine) + for y := 0; y < height; y++ { var r, g, b, a float64 - for _, w := range weights[dstY] { - i := w.index*src.Stride + dstX*4 - aw := float64(src.Pix[i+3]) * w.weight - r += float64(src.Pix[i+0]) * aw - g += float64(src.Pix[i+1]) * aw - b += float64(src.Pix[i+2]) * aw + for _, w := range weights[y] { + i := w.index * 4 + aw := float64(scanLine[i+3]) * w.weight + r += float64(scanLine[i+0]) * aw + g += float64(scanLine[i+1]) * aw + b += float64(scanLine[i+2]) * aw a += aw } if a != 0 { aInv := 1 / a - j := dstY*dst.Stride + dstX*4 + j := y*dst.Stride + x*4 dst.Pix[j+0] = clamp(r * aInv) dst.Pix[j+1] = clamp(g * aInv) dst.Pix[j+2] = clamp(b * aInv) @@ -192,45 +169,44 @@ func resizeVertical(src *image.NRGBA, height int, filter ResampleFilter) *image. } } }) - return dst } // resizeNearest is a fast nearest-neighbor resize, no filtering. -func resizeNearest(src *image.NRGBA, width, height int) *image.NRGBA { - dstW, dstH := width, height - - srcBounds := src.Bounds() - srcW := srcBounds.Max.X - srcH := srcBounds.Max.Y - - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - dx := float64(srcW) / float64(dstW) - dy := float64(srcH) / float64(dstH) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - srcY := int((float64(dstY) + 0.5) * dy) - if srcY > srcH-1 { - srcY = srcH - 1 +func resizeNearest(img image.Image, width, height int) *image.NRGBA { + dst := image.NewNRGBA(image.Rect(0, 0, width, height)) + dx := float64(img.Bounds().Dx()) / float64(width) + dy := float64(img.Bounds().Dy()) / float64(height) + + if dx > 1 && dy > 1 { + src := newScanner(img) + parallel(0, height, func(ys <-chan int) { + for y := range ys { + srcY := int((float64(y) + 0.5) * dy) + dstOff := y * dst.Stride + for x := 0; x < width; x++ { + srcX := int((float64(x) + 0.5) * dx) + src.scan(srcX, srcY, srcX+1, srcY+1, dst.Pix[dstOff:dstOff+4]) + dstOff += 4 + } } - - for dstX := 0; dstX < dstW; dstX++ { - srcX := int((float64(dstX) + 0.5) * dx) - if srcX > srcW-1 { - srcX = srcW - 1 + }) + } else { + src := toNRGBA(img) + parallel(0, height, func(ys <-chan int) { + for y := range ys { + srcY := int((float64(y) + 0.5) * dy) + srcOff0 := srcY * src.Stride + dstOff := y * dst.Stride + for x := 0; x < width; x++ { + srcX := int((float64(x) + 0.5) * dx) + srcOff := srcOff0 + srcX*4 + copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) + dstOff += 4 } - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) } - } - - }) + }) + } return dst } @@ -344,27 +320,28 @@ func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image // General filter recommendations: // // - Lanczos -// Probably the best resampling filter for photographic images yielding sharp results, -// but it's slower than cubic filters (see below). +// High-quality resampling filter for photographic images yielding sharp results. +// It's slower than cubic filters (see below). // // - CatmullRom // A sharp cubic filter. It's a good filter for both upscaling and downscaling if sharp results are needed. // // - MitchellNetravali -// A high quality cubic filter that produces smoother results with less ringing than CatmullRom. +// A high quality cubic filter that produces smoother results with less ringing artifacts than CatmullRom. // // - BSpline // A good filter if a very smooth output is needed. // // - Linear -// Bilinear interpolation filter, produces reasonably good, smooth output. It's faster than cubic filters. +// Bilinear interpolation filter, produces reasonably good, smooth output. +// It's faster than cubic filters. // // - Box -// Simple and fast resampling filter appropriate for downscaling. +// Simple and fast averaging filter appropriate for downscaling. // When upscaling it's similar to NearestNeighbor. // // - NearestNeighbor -// Fastest resample filter, no antialiasing at all. Rarely used. +// Fastest resampling filter, no antialiasing. // type ResampleFilter struct { Support float64 @@ -417,14 +394,14 @@ var Welch ResampleFilter var Cosine ResampleFilter func bcspline(x, b, c float64) float64 { + var y float64 x = math.Abs(x) if x < 1.0 { - return ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6 - } - if x < 2.0 { - return ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6 + y = ((12-9*b-6*c)*x*x*x + (-18+12*b+6*c)*x*x + (6 - 2*b)) / 6 + } else if x < 2.0 { + y = ((-b-6*c)*x*x*x + (6*b+30*c)*x*x + (-12*b-48*c)*x + (8*b + 24*c)) / 6 } - return 0 + return y } func sinc(x float64) float64 { diff --git a/vendor/github.com/disintegration/imaging/resize_test.go b/vendor/github.com/disintegration/imaging/resize_test.go deleted file mode 100644 index 72701e093..000000000 --- a/vendor/github.com/disintegration/imaging/resize_test.go +++ /dev/null @@ -1,628 +0,0 @@ -package imaging - -import ( - "image" - "testing" -) - -func TestResize(t *testing.T) { - td := []struct { - desc string - src image.Image - w, h int - f ResampleFilter - want *image.NRGBA - }{ - { - "Resize 2x2 1x1 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 1, 1, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 1), - Stride: 1 * 4, - Pix: []uint8{0x55, 0x55, 0x55, 0xc0}, - }, - }, - { - "Resize 2x2 2x2 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 2, 2, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - }, - { - "Resize 3x1 1x1 nearest", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 2, 0), - Stride: 3 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 1, 1, - NearestNeighbor, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 1), - Stride: 1 * 4, - Pix: []uint8{0x00, 0xff, 0x00, 0xff}, - }, - }, - { - "Resize 2x2 0x4 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 0, 4, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - }, - { - "Resize 2x2 4x0 linear", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 4, 0, - Linear, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x40, 0xff, 0x00, 0x00, 0xbf, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0x40, 0x6e, 0x6d, 0x25, 0x70, 0xb0, 0x14, 0x3b, 0xcf, 0xbf, 0x00, 0x40, 0xff, - 0x00, 0xff, 0x00, 0xbf, 0x14, 0xb0, 0x3b, 0xcf, 0x33, 0x33, 0x99, 0xef, 0x40, 0x00, 0xbf, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xbf, 0x40, 0xff, 0x00, 0x40, 0xbf, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - }, - { - "Resize 0x0 1x1 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, -1, -1), - Stride: 0, - Pix: []uint8{}, - }, - 1, 1, - Box, - &image.NRGBA{}, - }, - { - "Resize 2x2 0x0 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 0, 0, - Box, - &image.NRGBA{}, - }, - { - "Resize 2x2 -1x0 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - -1, 0, - Box, - &image.NRGBA{}, - }, - } - for _, d := range td { - got := Resize(d.src, d.w, d.h, d.f) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } - - for i, filter := range []ResampleFilter{ - NearestNeighbor, - Box, - Linear, - Hermite, - MitchellNetravali, - CatmullRom, - BSpline, - Gaussian, - Lanczos, - Hann, - Hamming, - Blackman, - Bartlett, - Welch, - Cosine, - } { - src := image.NewNRGBA(image.Rect(-1, -1, 2, 3)) - got := Resize(src, 5, 6, filter) - want := image.NewNRGBA(image.Rect(0, 0, 5, 6)) - if !compareNRGBA(got, want, 0) { - t.Errorf("test [Resize all filters #%d] failed: %#v", i, got) - } - - if filter.Kernel != nil { - x := filter.Kernel(filter.Support + 0.0001) - if x != 0 { - t.Errorf("test [ResampleFilter edge cases #%d] failed: %f", i, x) - } - } - } - - bcs2 := bcspline(2, 1, 0) - if bcs2 != 0 { - t.Errorf("test [bcspline 2] failed: %f", bcs2) - } -} - -func TestResizeGolden(t *testing.T) { - src, err := Open("testdata/lena_512.png") - if err != nil { - t.Errorf("Open: %v", err) - } - for name, filter := range map[string]ResampleFilter{ - "out_resize_nearest.png": NearestNeighbor, - "out_resize_linear.png": Linear, - "out_resize_catrom.png": CatmullRom, - "out_resize_lanczos.png": Lanczos, - } { - got := Resize(src, 128, 0, filter) - want, err := Open("testdata/" + name) - if err != nil { - t.Errorf("Open: %v", err) - } - if !compareNRGBA(got, toNRGBA(want), 0) { - t.Errorf("resulting image differs from golden: %s", name) - } - } -} - -func TestFit(t *testing.T) { - td := []struct { - desc string - src image.Image - w, h int - f ResampleFilter - want *image.NRGBA - }{ - { - "Fit 2x2 1x10 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 1, 10, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 1), - Stride: 1 * 4, - Pix: []uint8{0x55, 0x55, 0x55, 0xc0}, - }, - }, - { - "Fit 2x2 10x1 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 10, 1, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 1), - Stride: 1 * 4, - Pix: []uint8{0x55, 0x55, 0x55, 0xc0}, - }, - }, - { - "Fit 2x2 10x10 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 10, 10, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - }, - { - "Fit 0x0 1x1 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, -1, -1), - Stride: 0, - Pix: []uint8{}, - }, - 1, 1, - Box, - &image.NRGBA{}, - }, - { - "Fit 2x2 0x0 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - 0, 0, - Box, - &image.NRGBA{}, - }, - { - "Fit 2x2 -1x0 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - }, - }, - -1, 0, - Box, - &image.NRGBA{}, - }, - } - for _, d := range td { - got := Fit(d.src, d.w, d.h, d.f) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestFill(t *testing.T) { - td := []struct { - desc string - src image.Image - w, h int - a Anchor - f ResampleFilter - want *image.NRGBA - }{ - { - "Fill 4x4 2x2 Center Nearest", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - Center, - NearestNeighbor, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x14, 0x15, 0x16, 0x17, 0x1c, 0x1d, 0x1e, 0x1f, - 0x34, 0x35, 0x36, 0x37, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "Fill 4x4 1x4 TopLeft Nearest", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 1, 4, - TopLeft, - NearestNeighbor, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 4), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, - 0x10, 0x11, 0x12, 0x13, - 0x20, 0x21, 0x22, 0x23, - 0x30, 0x31, 0x32, 0x33, - }, - }, - }, - { - "Fill 4x4 8x2 Bottom Nearest", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 8, 2, - Bottom, - NearestNeighbor, - &image.NRGBA{ - Rect: image.Rect(0, 0, 8, 2), - Stride: 8 * 4, - Pix: []uint8{ - 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f, - 0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "Fill 4x4 2x8 Top Nearest", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 8, - Top, - NearestNeighbor, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 8), - Stride: 2 * 4, - Pix: []uint8{ - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - }, - }, - }, - { - "Fill 4x4 4x4 TopRight Box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 4, 4, - TopRight, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "Fill 4x4 0x4 Left Box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 0, 4, - Left, - Box, - &image.NRGBA{}, - }, - { - "Fill 0x0 4x4 Right Box", - &image.NRGBA{}, - 4, 4, - Right, - Box, - &image.NRGBA{}, - }, - } - for _, d := range td { - got := Fill(d.src, d.w, d.h, d.a, d.f) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestThumbnail(t *testing.T) { - td := []struct { - desc string - src image.Image - w, h int - f ResampleFilter - want *image.NRGBA - }{ - { - "Thumbnail 6x2 1x1 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 5, 1), - Stride: 6 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 1, 1, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 1), - Stride: 1 * 4, - Pix: []uint8{0x55, 0x55, 0x55, 0xc0}, - }, - }, - { - "Thumbnail 2x6 1x1 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 5), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 1, 1, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 1), - Stride: 1 * 4, - Pix: []uint8{0x55, 0x55, 0x55, 0xc0}, - }, - }, - { - "Thumbnail 1x3 2x2 box", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 2), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0x00, - 0xff, 0x00, 0x00, 0xff, - 0xff, 0xff, 0xff, 0xff, - }, - }, - 2, 2, - Box, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Thumbnail(d.src, d.w, d.h, d.f) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func BenchmarkResizeLanczosUp(b *testing.B) { - benchmarkResize(b, "testdata/lena_128.png", 512, Lanczos) -} - -func BenchmarkResizeLinearUp(b *testing.B) { - benchmarkResize(b, "testdata/lena_128.png", 512, Linear) -} - -func BenchmarkResizeNearestNeighborUp(b *testing.B) { - benchmarkResize(b, "testdata/lena_128.png", 512, NearestNeighbor) -} - -func BenchmarkResizeLanczosDown(b *testing.B) { - benchmarkResize(b, "testdata/lena_512.png", 128, Lanczos) -} - -func BenchmarkResizeLinearDown(b *testing.B) { - benchmarkResize(b, "testdata/lena_512.png", 128, Linear) -} - -func BenchmarkResizeNearestNeighborDown(b *testing.B) { - benchmarkResize(b, "testdata/lena_512.png", 128, NearestNeighbor) -} - -func benchmarkResize(b *testing.B, filename string, size int, f ResampleFilter) { - b.StopTimer() - img, err := Open(filename) - if err != nil { - b.Fatalf("Open: %v", err) - } - b.StartTimer() - for i := 0; i < b.N; i++ { - Resize(img, size, size, f) - } -} diff --git a/vendor/github.com/disintegration/imaging/scanner.go b/vendor/github.com/disintegration/imaging/scanner.go new file mode 100644 index 000000000..c4dbfe1ec --- /dev/null +++ b/vendor/github.com/disintegration/imaging/scanner.go @@ -0,0 +1,250 @@ +package imaging + +import ( + "image" + "image/color" +) + +type scanner struct { + image image.Image + w, h int + palette []color.NRGBA +} + +func newScanner(img image.Image) *scanner { + s := &scanner{ + image: img, + w: img.Bounds().Dx(), + h: img.Bounds().Dy(), + } + if img, ok := img.(*image.Paletted); ok { + s.palette = make([]color.NRGBA, len(img.Palette)) + for i := 0; i < len(img.Palette); i++ { + s.palette[i] = color.NRGBAModel.Convert(img.Palette[i]).(color.NRGBA) + } + } + return s +} + +// scan scans the given rectangular region of the image into dst. +func (s *scanner) scan(x1, y1, x2, y2 int, dst []uint8) { + switch img := s.image.(type) { + case *image.NRGBA: + size := (x2 - x1) * 4 + j := 0 + i := y1*img.Stride + x1*4 + for y := y1; y < y2; y++ { + copy(dst[j:j+size], img.Pix[i:i+size]) + j += size + i += img.Stride + } + + case *image.NRGBA64: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*8 + for x := x1; x < x2; x++ { + dst[j+0] = img.Pix[i+0] + dst[j+1] = img.Pix[i+2] + dst[j+2] = img.Pix[i+4] + dst[j+3] = img.Pix[i+6] + j += 4 + i += 8 + } + } + + case *image.RGBA: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*4 + for x := x1; x < x2; x++ { + a := img.Pix[i+3] + switch a { + case 0: + dst[j+0] = 0 + dst[j+1] = 0 + dst[j+2] = 0 + case 0xff: + dst[j+0] = img.Pix[i+0] + dst[j+1] = img.Pix[i+1] + dst[j+2] = img.Pix[i+2] + default: + r16 := uint16(img.Pix[i+0]) + g16 := uint16(img.Pix[i+1]) + b16 := uint16(img.Pix[i+2]) + a16 := uint16(a) + dst[j+0] = uint8(r16 * 0xff / a16) + dst[j+1] = uint8(g16 * 0xff / a16) + dst[j+2] = uint8(b16 * 0xff / a16) + } + dst[j+3] = a + j += 4 + i += 4 + } + } + + case *image.RGBA64: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*8 + for x := x1; x < x2; x++ { + a := img.Pix[i+6] + switch a { + case 0: + dst[j+0] = 0 + dst[j+1] = 0 + dst[j+2] = 0 + case 0xff: + dst[j+0] = img.Pix[i+0] + dst[j+1] = img.Pix[i+2] + dst[j+2] = img.Pix[i+4] + default: + r32 := uint32(img.Pix[i+0])<<8 | uint32(img.Pix[i+1]) + g32 := uint32(img.Pix[i+2])<<8 | uint32(img.Pix[i+3]) + b32 := uint32(img.Pix[i+4])<<8 | uint32(img.Pix[i+5]) + a32 := uint32(img.Pix[i+6])<<8 | uint32(img.Pix[i+7]) + dst[j+0] = uint8((r32 * 0xffff / a32) >> 8) + dst[j+1] = uint8((g32 * 0xffff / a32) >> 8) + dst[j+2] = uint8((b32 * 0xffff / a32) >> 8) + } + dst[j+3] = a + j += 4 + i += 8 + } + } + + case *image.Gray: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1 + for x := x1; x < x2; x++ { + c := img.Pix[i] + dst[j+0] = c + dst[j+1] = c + dst[j+2] = c + dst[j+3] = 0xff + j += 4 + i++ + } + } + + case *image.Gray16: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1*2 + for x := x1; x < x2; x++ { + c := img.Pix[i] + dst[j+0] = c + dst[j+1] = c + dst[j+2] = c + dst[j+3] = 0xff + j += 4 + i += 2 + } + } + + case *image.YCbCr: + j := 0 + x1 += img.Rect.Min.X + x2 += img.Rect.Min.X + y1 += img.Rect.Min.Y + y2 += img.Rect.Min.Y + for y := y1; y < y2; y++ { + iy := (y-img.Rect.Min.Y)*img.YStride + (x1 - img.Rect.Min.X) + for x := x1; x < x2; x++ { + var ic int + switch img.SubsampleRatio { + case image.YCbCrSubsampleRatio444: + ic = (y-img.Rect.Min.Y)*img.CStride + (x - img.Rect.Min.X) + case image.YCbCrSubsampleRatio422: + ic = (y-img.Rect.Min.Y)*img.CStride + (x/2 - img.Rect.Min.X/2) + case image.YCbCrSubsampleRatio420: + ic = (y/2-img.Rect.Min.Y/2)*img.CStride + (x/2 - img.Rect.Min.X/2) + case image.YCbCrSubsampleRatio440: + ic = (y/2-img.Rect.Min.Y/2)*img.CStride + (x - img.Rect.Min.X) + default: + ic = img.COffset(x, y) + } + + yy := int(img.Y[iy]) + cb := int(img.Cb[ic]) - 128 + cr := int(img.Cr[ic]) - 128 + + r := (yy<<16 + 91881*cr + 1<<15) >> 16 + if r > 0xff { + r = 0xff + } else if r < 0 { + r = 0 + } + + g := (yy<<16 - 22554*cb - 46802*cr + 1<<15) >> 16 + if g > 0xff { + g = 0xff + } else if g < 0 { + g = 0 + } + + b := (yy<<16 + 116130*cb + 1<<15) >> 16 + if b > 0xff { + b = 0xff + } else if b < 0 { + b = 0 + } + + dst[j+0] = uint8(r) + dst[j+1] = uint8(g) + dst[j+2] = uint8(b) + dst[j+3] = 0xff + + iy++ + j += 4 + } + } + + case *image.Paletted: + j := 0 + for y := y1; y < y2; y++ { + i := y*img.Stride + x1 + for x := x1; x < x2; x++ { + c := s.palette[img.Pix[i]] + dst[j+0] = c.R + dst[j+1] = c.G + dst[j+2] = c.B + dst[j+3] = c.A + j += 4 + i++ + } + } + + default: + j := 0 + b := s.image.Bounds() + x1 += b.Min.X + x2 += b.Min.X + y1 += b.Min.Y + y2 += b.Min.Y + for y := y1; y < y2; y++ { + for x := x1; x < x2; x++ { + r16, g16, b16, a16 := s.image.At(x, y).RGBA() + switch a16 { + case 0xffff: + dst[j+0] = uint8(r16 >> 8) + dst[j+1] = uint8(g16 >> 8) + dst[j+2] = uint8(b16 >> 8) + dst[j+3] = 0xff + case 0: + dst[j+0] = 0 + dst[j+1] = 0 + dst[j+2] = 0 + dst[j+3] = 0 + default: + dst[j+0] = uint8(((r16 * 0xffff) / a16) >> 8) + dst[j+1] = uint8(((g16 * 0xffff) / a16) >> 8) + dst[j+2] = uint8(((b16 * 0xffff) / a16) >> 8) + dst[j+3] = uint8(a16 >> 8) + } + j += 4 + } + } + } +} diff --git a/vendor/github.com/disintegration/imaging/testdata/lena_128.png b/vendor/github.com/disintegration/imaging/testdata/lena_128.png deleted file mode 100644 index 43eb8e7c6..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/lena_128.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/lena_512.png b/vendor/github.com/disintegration/imaging/testdata/lena_512.png deleted file mode 100644 index 0e0f9e6bc..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/lena_512.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_blur_0.5.png b/vendor/github.com/disintegration/imaging/testdata/out_blur_0.5.png deleted file mode 100644 index 90d19347e..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_blur_0.5.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_blur_1.5.png b/vendor/github.com/disintegration/imaging/testdata/out_blur_1.5.png deleted file mode 100644 index 3df019c33..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_blur_1.5.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_brightness_m10.png b/vendor/github.com/disintegration/imaging/testdata/out_brightness_m10.png deleted file mode 100644 index a59191e9d..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_brightness_m10.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_brightness_p10.png b/vendor/github.com/disintegration/imaging/testdata/out_brightness_p10.png deleted file mode 100644 index 0b8bb3e10..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_brightness_p10.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_contrast_m10.png b/vendor/github.com/disintegration/imaging/testdata/out_contrast_m10.png deleted file mode 100644 index 8b8e0b8e0..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_contrast_m10.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_contrast_p10.png b/vendor/github.com/disintegration/imaging/testdata/out_contrast_p10.png deleted file mode 100644 index dbfd40eea..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_contrast_p10.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_example.jpg b/vendor/github.com/disintegration/imaging/testdata/out_example.jpg deleted file mode 100644 index 5f225b58f..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_example.jpg and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_gamma_0.75.png b/vendor/github.com/disintegration/imaging/testdata/out_gamma_0.75.png deleted file mode 100644 index 89d28735b..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_gamma_0.75.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_gamma_1.25.png b/vendor/github.com/disintegration/imaging/testdata/out_gamma_1.25.png deleted file mode 100644 index 915e6d53d..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_gamma_1.25.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_resize_catrom.png b/vendor/github.com/disintegration/imaging/testdata/out_resize_catrom.png deleted file mode 100644 index 628272f97..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_resize_catrom.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_resize_lanczos.png b/vendor/github.com/disintegration/imaging/testdata/out_resize_lanczos.png deleted file mode 100644 index 6d168f70e..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_resize_lanczos.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_resize_linear.png b/vendor/github.com/disintegration/imaging/testdata/out_resize_linear.png deleted file mode 100644 index 0a74e5e5f..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_resize_linear.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_resize_nearest.png b/vendor/github.com/disintegration/imaging/testdata/out_resize_nearest.png deleted file mode 100644 index 108cb6601..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_resize_nearest.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_sharpen_0.5.png b/vendor/github.com/disintegration/imaging/testdata/out_sharpen_0.5.png deleted file mode 100644 index 056ba59b2..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_sharpen_0.5.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/testdata/out_sharpen_1.5.png b/vendor/github.com/disintegration/imaging/testdata/out_sharpen_1.5.png deleted file mode 100644 index a47dc6040..000000000 Binary files a/vendor/github.com/disintegration/imaging/testdata/out_sharpen_1.5.png and /dev/null differ diff --git a/vendor/github.com/disintegration/imaging/tools.go b/vendor/github.com/disintegration/imaging/tools.go index e57225c58..fae1fa153 100644 --- a/vendor/github.com/disintegration/imaging/tools.go +++ b/vendor/github.com/disintegration/imaging/tools.go @@ -58,10 +58,20 @@ func anchorPt(b image.Rectangle, w, h int, anchor Anchor) image.Point { // Crop cuts out a rectangular region with the specified bounds // from the image and returns the cropped image. func Crop(img image.Image, rect image.Rectangle) *image.NRGBA { - src := toNRGBA(img) - srcRect := rect.Sub(img.Bounds().Min) - sub := src.SubImage(srcRect) - return Clone(sub) // New image Bounds().Min point will be (0, 0) + r := rect.Intersect(img.Bounds()).Sub(img.Bounds().Min) + if r.Empty() { + return &image.NRGBA{} + } + src := newScanner(img) + dst := image.NewNRGBA(image.Rect(0, 0, r.Dx(), r.Dy())) + rowSize := r.Dx() * 4 + parallel(r.Min.Y, r.Max.Y, func(ys <-chan int) { + for y := range ys { + i := (y - r.Min.Y) * dst.Stride + src.scan(r.Min.X, y, r.Max.X, y+1, dst.Pix[i:i+rowSize]) + } + }) + return dst } // CropAnchor cuts out a rectangular region with the specified size @@ -82,34 +92,25 @@ func CropCenter(img image.Image, width, height int) *image.NRGBA { // Paste pastes the img image to the background image at the specified position and returns the combined image. func Paste(background, img image.Image, pos image.Point) *image.NRGBA { - src := toNRGBA(img) - dst := Clone(background) // cloned image bounds start at (0, 0) - startPt := pos.Sub(background.Bounds().Min) // so we should translate start point - endPt := startPt.Add(src.Bounds().Size()) - pasteBounds := image.Rectangle{startPt, endPt} - - if dst.Bounds().Overlaps(pasteBounds) { - intersectBounds := dst.Bounds().Intersect(pasteBounds) - - rowSize := intersectBounds.Dx() * 4 - numRows := intersectBounds.Dy() - - srcStartX := intersectBounds.Min.X - pasteBounds.Min.X - srcStartY := intersectBounds.Min.Y - pasteBounds.Min.Y - - i0 := dst.PixOffset(intersectBounds.Min.X, intersectBounds.Min.Y) - j0 := src.PixOffset(srcStartX, srcStartY) - - di := dst.Stride - dj := src.Stride - - for row := 0; row < numRows; row++ { - copy(dst.Pix[i0:i0+rowSize], src.Pix[j0:j0+rowSize]) - i0 += di - j0 += dj - } + dst := Clone(background) + pos = pos.Sub(background.Bounds().Min) + pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())} + interRect := pasteRect.Intersect(dst.Bounds()) + if interRect.Empty() { + return dst } - + src := newScanner(img) + parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) { + for y := range ys { + x1 := interRect.Min.X - pasteRect.Min.X + x2 := interRect.Max.X - pasteRect.Min.X + y1 := y - pasteRect.Min.Y + y2 := y1 + 1 + i1 := y*dst.Stride + interRect.Min.X*4 + i2 := i1 + interRect.Dx()*4 + src.scan(x1, y1, x2, y2, dst.Pix[i1:i2]) + } + }) return dst } @@ -136,49 +137,59 @@ func PasteCenter(background, img image.Image) *image.NRGBA { // // Usage examples: // -// // draw the sprite over the background at position (50, 50) +// // Draw spriteImage over backgroundImage at the given position (x=50, y=50). // dstImage := imaging.Overlay(backgroundImage, spriteImage, image.Pt(50, 50), 1.0) // -// // blend two opaque images of the same size +// // Blend two opaque images of the same size. // dstImage := imaging.Overlay(imageOne, imageTwo, image.Pt(0, 0), 0.5) // func Overlay(background, img image.Image, pos image.Point, opacity float64) *image.NRGBA { - opacity = math.Min(math.Max(opacity, 0.0), 1.0) // check: 0.0 <= opacity <= 1.0 - - src := toNRGBA(img) - dst := Clone(background) // cloned image bounds start at (0, 0) - startPt := pos.Sub(background.Bounds().Min) // so we should translate start point - endPt := startPt.Add(src.Bounds().Size()) - pasteBounds := image.Rectangle{startPt, endPt} - - if dst.Bounds().Overlaps(pasteBounds) { - intersectBounds := dst.Bounds().Intersect(pasteBounds) - - for y := intersectBounds.Min.Y; y < intersectBounds.Max.Y; y++ { - for x := intersectBounds.Min.X; x < intersectBounds.Max.X; x++ { - i := y*dst.Stride + x*4 - - srcX := x - pasteBounds.Min.X - srcY := y - pasteBounds.Min.Y - j := srcY*src.Stride + srcX*4 - + opacity = math.Min(math.Max(opacity, 0.0), 1.0) // Ensure 0.0 <= opacity <= 1.0. + dst := Clone(background) + pos = pos.Sub(background.Bounds().Min) + pasteRect := image.Rectangle{Min: pos, Max: pos.Add(img.Bounds().Size())} + interRect := pasteRect.Intersect(dst.Bounds()) + if interRect.Empty() { + return dst + } + src := newScanner(img) + parallel(interRect.Min.Y, interRect.Max.Y, func(ys <-chan int) { + scanLine := make([]uint8, interRect.Dx()*4) + for y := range ys { + x1 := interRect.Min.X - pasteRect.Min.X + x2 := interRect.Max.X - pasteRect.Min.X + y1 := y - pasteRect.Min.Y + y2 := y1 + 1 + src.scan(x1, y1, x2, y2, scanLine) + i := y*dst.Stride + interRect.Min.X*4 + j := 0 + for x := interRect.Min.X; x < interRect.Max.X; x++ { + r1 := float64(dst.Pix[i+0]) + g1 := float64(dst.Pix[i+1]) + b1 := float64(dst.Pix[i+2]) a1 := float64(dst.Pix[i+3]) - a2 := float64(src.Pix[j+3]) - coef2 := opacity * a2 / 255.0 - coef1 := (1 - coef2) * a1 / 255.0 + r2 := float64(scanLine[j+0]) + g2 := float64(scanLine[j+1]) + b2 := float64(scanLine[j+2]) + a2 := float64(scanLine[j+3]) + + coef2 := opacity * a2 / 255 + coef1 := (1 - coef2) * a1 / 255 coefSum := coef1 + coef2 coef1 /= coefSum coef2 /= coefSum - dst.Pix[i+0] = uint8(float64(dst.Pix[i+0])*coef1 + float64(src.Pix[j+0])*coef2) - dst.Pix[i+1] = uint8(float64(dst.Pix[i+1])*coef1 + float64(src.Pix[j+1])*coef2) - dst.Pix[i+2] = uint8(float64(dst.Pix[i+2])*coef1 + float64(src.Pix[j+2])*coef2) - dst.Pix[i+3] = uint8(math.Min(a1+a2*opacity*(255.0-a1)/255.0, 255.0)) + dst.Pix[i+0] = uint8(r1*coef1 + r2*coef2) + dst.Pix[i+1] = uint8(g1*coef1 + g2*coef2) + dst.Pix[i+2] = uint8(b1*coef1 + b2*coef2) + dst.Pix[i+3] = uint8(math.Min(a1+a2*opacity*(255-a1)/255, 255)) + + i += 4 + j += 4 } } - } - + }) return dst } diff --git a/vendor/github.com/disintegration/imaging/tools_test.go b/vendor/github.com/disintegration/imaging/tools_test.go deleted file mode 100644 index 83a258c26..000000000 --- a/vendor/github.com/disintegration/imaging/tools_test.go +++ /dev/null @@ -1,652 +0,0 @@ -package imaging - -import ( - "image" - "testing" -) - -func TestCrop(t *testing.T) { - td := []struct { - desc string - src image.Image - r image.Rectangle - want *image.NRGBA - }{ - { - "Crop 2x3 2x1", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - image.Rect(-1, 0, 1, 1), - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - }, - }, - }, - } - for _, d := range td { - got := Crop(d.src, d.r) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestCropCenter(t *testing.T) { - td := []struct { - desc string - src image.Image - w, h int - want *image.NRGBA - }{ - { - "CropCenter 2x3 2x1", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - 2, 1, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - }, - }, - }, - { - "CropCenter 2x3 0x1", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - 0, 1, - &image.NRGBA{ - Rect: image.Rect(0, 0, 0, 0), - Stride: 0, - Pix: []uint8{}, - }, - }, - { - "CropCenter 2x3 5x5", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - 5, 5, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, d := range td { - got := CropCenter(d.src, d.w, d.h) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestCropAnchor(t *testing.T) { - td := []struct { - desc string - src image.Image - w, h int - anchor Anchor - want *image.NRGBA - }{ - { - "CropAnchor 4x4 2x2 TopLeft", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - TopLeft, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - }, - }, - }, - { - "CropAnchor 4x4 2x2 Top", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - Top, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - }, - }, - }, - { - "CropAnchor 4x4 2x2 TopRight", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - TopRight, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - }, - }, - }, - { - "CropAnchor 4x4 2x2 Left", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - Left, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - }, - }, - }, - { - "CropAnchor 4x4 2x2 Center", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - Center, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - }, - }, - }, - { - "CropAnchor 4x4 2x2 Right", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - Right, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - }, - }, - }, - { - "CropAnchor 4x4 2x2 BottomLeft", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - BottomLeft, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - }, - }, - }, - { - "CropAnchor 4x4 2x2 Bottom", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - Bottom, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, - 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, - }, - }, - }, - { - "CropAnchor 4x4 2x2 BottomRight", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 2, 2, - BottomRight, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "CropAnchor 4x4 0x0 BottomRight", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 0, 0, - BottomRight, - &image.NRGBA{ - Rect: image.Rect(0, 0, 0, 0), - Stride: 0, - Pix: []uint8{}, - }, - }, - { - "CropAnchor 4x4 100x100 BottomRight", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 100, 100, - BottomRight, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "CropAnchor 4x4 1x100 BottomRight", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 1, 100, - BottomRight, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 4), - Stride: 1 * 4, - Pix: []uint8{ - 0x0c, 0x0d, 0x0e, 0x0f, - 0x1c, 0x1d, 0x1e, 0x1f, - 0x2c, 0x2d, 0x2e, 0x2f, - 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - }, - { - "CropAnchor 4x4 0x100 BottomRight", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - }, - }, - 0, 100, - BottomRight, - &image.NRGBA{ - Rect: image.Rect(0, 0, 0, 0), - Stride: 0, - Pix: []uint8{}, - }, - }, - } - for _, d := range td { - got := CropAnchor(d.src, d.w, d.h, d.anchor) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestPaste(t *testing.T) { - td := []struct { - desc string - src1 image.Image - src2 image.Image - p image.Point - want *image.NRGBA - }{ - { - "Paste 2x3 2x1", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(1, 1, 3, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - }, - }, - image.Pt(-1, 0), - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Paste(d.src1, d.src2, d.p) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestPasteCenter(t *testing.T) { - td := []struct { - desc string - src1 image.Image - src2 image.Image - want *image.NRGBA - }{ - { - "PasteCenter 2x3 2x1", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(1, 1, 3, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, d := range td { - got := PasteCenter(d.src1, d.src2) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestOverlay(t *testing.T) { - td := []struct { - desc string - src1 image.Image - src2 image.Image - p image.Point - a float64 - want *image.NRGBA - }{ - { - "Overlay 2x3 2x1 1.0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0x60, 0x00, 0x90, 0xff, 0xff, 0x00, 0x99, 0x7f, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(1, 1, 3, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x20, 0x40, 0x80, 0x7f, 0xaa, 0xbb, 0xcc, 0xff, - }, - }, - image.Pt(-1, 0), - 1.0, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0x40, 0x1f, 0x88, 0xff, 0xaa, 0xbb, 0xcc, 0xff, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Overlay 2x2 2x2 0.5", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x20, 0x20, 0x20, 0x00, - }, - }, - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0x00, 0xff, 0x20, 0x20, 0x20, 0xff, - }, - }, - image.Pt(-1, -1), - 0.5, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x7f, 0x7f, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x7f, 0x7f, 0x7f, 0xff, 0x20, 0x20, 0x20, 0x7f, - }, - }, - }, - } - for _, d := range td { - got := Overlay(d.src1, d.src2, d.p, d.a) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestOverlayCenter(t *testing.T) { - td := []struct { - desc string - src1 image.Image - src2 image.Image - a float64 - want *image.NRGBA - }{ - { - "OverlayCenter 2x3 2x1", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, - 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, - 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(1, 1, 3, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, - }, - }, - 0.5, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, - 0x2c, 0x2c, 0x2c, 0xff, 0x2c, 0x2c, 0x2c, 0xff, - 0x10, 0x10, 0x10, 0xff, 0x10, 0x10, 0x10, 0xff, - }, - }, - }, - } - for _, d := range td { - got := OverlayCenter(d.src1, d.src2, 0.5) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/disintegration/imaging/transform.go index 94d72d556..d788d0d42 100644 --- a/vendor/github.com/disintegration/imaging/transform.go +++ b/vendor/github.com/disintegration/imaging/transform.go @@ -8,197 +8,124 @@ import ( // FlipH flips the image horizontally (from left to right) and returns the transformed image. func FlipH(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcW - dstH := srcH + src := newScanner(img) + dstW := src.w + dstH := src.h + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstW - dstX - 1 - srcY := dstY - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcY := dstY + src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) } - }) - return dst } // FlipV flips the image vertically (from top to bottom) and returns the transformed image. func FlipV(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcW - dstH := srcH + src := newScanner(img) + dstW := src.w + dstH := src.h + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstX - srcY := dstH - dstY - 1 - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcY := dstH - dstY - 1 + src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) } - }) - return dst } // Transpose flips the image horizontally and rotates 90 degrees counter-clockwise. func Transpose(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcH - dstH := srcW + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstY - srcY := dstX - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstY + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) } - }) - return dst } // Transverse flips the image vertically and rotates 90 degrees counter-clockwise. func Transverse(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcH - dstH := srcW + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstH - dstY - 1 - srcY := dstW - dstX - 1 - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstH - dstY - 1 + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) } - }) - return dst } -// Rotate90 rotates the image 90 degrees counterclockwise and returns the transformed image. +// Rotate90 rotates the image 90 degrees counter-clockwise and returns the transformed image. func Rotate90(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcH - dstH := srcW + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstH - dstY - 1 - srcY := dstX - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstH - dstY - 1 + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) } - }) - return dst } -// Rotate180 rotates the image 180 degrees counterclockwise and returns the transformed image. +// Rotate180 rotates the image 180 degrees counter-clockwise and returns the transformed image. func Rotate180(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcW - dstH := srcH + src := newScanner(img) + dstW := src.w + dstH := src.h + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstW - dstX - 1 - srcY := dstH - dstY - 1 - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcY := dstH - dstY - 1 + src.scan(0, srcY, src.w, srcY+1, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) } - }) - return dst } -// Rotate270 rotates the image 270 degrees counterclockwise and returns the transformed image. +// Rotate270 rotates the image 270 degrees counter-clockwise and returns the transformed image. func Rotate270(img image.Image) *image.NRGBA { - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW := srcH - dstH := srcW + src := newScanner(img) + dstW := src.h + dstH := src.w + rowSize := dstW * 4 dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - parallel(dstH, func(partStart, partEnd int) { - - for dstY := partStart; dstY < partEnd; dstY++ { - for dstX := 0; dstX < dstW; dstX++ { - srcX := dstY - srcY := dstW - dstX - 1 - - srcOff := srcY*src.Stride + srcX*4 - dstOff := dstY*dst.Stride + dstX*4 - - copy(dst.Pix[dstOff:dstOff+4], src.Pix[srcOff:srcOff+4]) - } + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { + i := dstY * dst.Stride + srcX := dstY + src.scan(srcX, 0, srcX+1, src.h, dst.Pix[i:i+rowSize]) + reverse(dst.Pix[i : i+rowSize]) } - }) - return dst } @@ -237,8 +164,8 @@ func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA { bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA) sin, cos := math.Sincos(math.Pi * angle / 180) - parallel(dstH, func(partStart, partEnd int) { - for dstY := partStart; dstY < partEnd; dstY++ { + parallel(0, dstH, func(ys <-chan int) { + for dstY := range ys { for dstX := 0; dstX < dstW; dstX++ { xf, yf := rotatePoint(float64(dstX)-dstXOff, float64(dstY)-dstYOff, sin, cos) xf, yf = xf+srcXOff, yf+srcYOff diff --git a/vendor/github.com/disintegration/imaging/transform_test.go b/vendor/github.com/disintegration/imaging/transform_test.go deleted file mode 100644 index 447dd1ea0..000000000 --- a/vendor/github.com/disintegration/imaging/transform_test.go +++ /dev/null @@ -1,581 +0,0 @@ -package imaging - -import ( - "image" - "image/color" - "testing" -) - -func TestFlipH(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "FlipH 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, - 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, - }, - }, - }, - } - for _, d := range td { - got := FlipH(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestFlipV(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "FlipV 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - }, - }, - }, - } - for _, d := range td { - got := FlipV(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestTranspose(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Transpose 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, - 0xcc, 0xdd, 0xee, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Transpose(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestTransverse(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Transverse 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xcc, 0xdd, 0xee, 0xff, - 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, - }, - }, - }, - } - for _, d := range td { - got := Transverse(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestRotate90(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Rotate90 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0xcc, 0xdd, 0xee, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x11, 0x22, 0x33, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, - }, - }, - }, - } - for _, d := range td { - got := Rotate90(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestRotate180(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Rotate180 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 3), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, - 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, - 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0x22, 0x33, - }, - }, - }, - } - for _, d := range td { - got := Rotate180(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestRotate270(t *testing.T) { - td := []struct { - desc string - src image.Image - want *image.NRGBA - }{ - { - "Rotate270 2x3", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 1, 2), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0x11, 0x22, 0x33, 0xcc, 0xdd, 0xee, 0xff, - 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, - }, - }, - &image.NRGBA{ - Rect: image.Rect(0, 0, 3, 2), - Stride: 3 * 4, - Pix: []uint8{ - 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33, - 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xcc, 0xdd, 0xee, 0xff, - }, - }, - }, - } - for _, d := range td { - got := Rotate270(d.src) - want := d.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", d.desc, got) - } - } -} - -func TestRotate(t *testing.T) { - testCases := []struct { - desc string - src image.Image - angle float64 - bg color.Color - want *image.NRGBA - }{ - { - "Rotate 0", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 0, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "Rotate 90", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 90, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - }, - { - "Rotate 180", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 180, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 4, 4), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate 45", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 3, 3), - Stride: 4 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - }, - }, - 45, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 6, 6), - Stride: 6 * 4, - Pix: []uint8{ - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0x58, 0x08, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x61, 0x00, 0x00, 0xff, 0xe9, 0x16, 0x00, 0xff, 0x35, 0xca, 0x00, 0xff, 0x00, 0x30, 0x30, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x61, 0x00, 0x00, 0xff, 0xe9, 0x16, 0x00, 0xff, 0x35, 0xca, 0x00, 0xff, 0x00, 0x80, 0x80, 0xff, 0x35, 0x35, 0xff, 0xff, 0x58, 0x58, 0x61, 0xff, - 0x58, 0x08, 0x00, 0xff, 0x35, 0xca, 0x00, 0xff, 0x00, 0x80, 0x80, 0xff, 0x35, 0x35, 0xff, 0xff, 0xe9, 0xe9, 0xff, 0xff, 0x61, 0x61, 0x61, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x30, 0x30, 0xff, 0x35, 0x35, 0xff, 0xff, 0xe9, 0xe9, 0xff, 0xff, 0x61, 0x61, 0x61, 0xff, 0x00, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x58, 0x58, 0x61, 0xff, 0x61, 0x61, 0x61, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate 0x0", - &image.NRGBA{ - Rect: image.Rect(0, 0, 0, 0), - Stride: 0, - Pix: []uint8{}, - }, - 123, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 0, 0), - Stride: 0, - Pix: []uint8{}, - }, - }, - { - "Rotate -90", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - -90, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate -360*10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - }, - }, - -360 * 10, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate -360*10 + 90", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - -360*10 + 90, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - }, - }, - }, - { - "Rotate -360*10 + 180", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - -360*10 + 180, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate -360*10 + 270", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - -360*10 + 270, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate 360*10", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - }, - }, - 360 * 10, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate 360*10 + 90", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - 360*10 + 90, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, - }, - }, - }, - { - "Rotate 360*10 + 180", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - 360*10 + 180, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 1, 2), - Stride: 1 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, - 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - { - "Rotate 360*10 + 270", - &image.NRGBA{ - Rect: image.Rect(-1, -1, 0, 1), - Stride: 1 * 4, - Pix: []uint8{ - 0xff, 0x00, 0x00, 0xff, - 0x00, 0xff, 0x00, 0xff, - }, - }, - 360*10 + 270, - color.Black, - &image.NRGBA{ - Rect: image.Rect(0, 0, 2, 1), - Stride: 2 * 4, - Pix: []uint8{ - 0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, - }, - }, - }, - } - for _, test := range testCases { - got := Rotate(test.src, test.angle, test.bg) - want := test.want - if !compareNRGBA(got, want, 0) { - t.Errorf("test [%s] failed: %#v", test.desc, got) - } - } -} diff --git a/vendor/github.com/disintegration/imaging/utils.go b/vendor/github.com/disintegration/imaging/utils.go index 9f5926aaa..3b6ad2e49 100644 --- a/vendor/github.com/disintegration/imaging/utils.go +++ b/vendor/github.com/disintegration/imaging/utils.go @@ -1,53 +1,38 @@ package imaging import ( + "image" "runtime" "sync" - "sync/atomic" ) -// parallel starts parallel image processing based on the current GOMAXPROCS value. -// If GOMAXPROCS = 1 it uses no parallelization. -// If GOMAXPROCS > 1 it spawns N=GOMAXPROCS workers in separate goroutines. -func parallel(dataSize int, fn func(partStart, partEnd int)) { - numGoroutines := 1 - partSize := dataSize - - numProcs := runtime.GOMAXPROCS(0) - if numProcs > 1 { - numGoroutines = numProcs - partSize = dataSize / (numGoroutines * 10) - if partSize < 1 { - partSize = 1 - } +// parallel processes the data in separate goroutines. +func parallel(start, stop int, fn func(<-chan int)) { + count := stop - start + if count < 1 { + return } - if numGoroutines == 1 { - fn(0, dataSize) - } else { - var wg sync.WaitGroup - wg.Add(numGoroutines) - idx := uint64(0) + procs := runtime.GOMAXPROCS(0) + if procs > count { + procs = count + } - for p := 0; p < numGoroutines; p++ { - go func() { - defer wg.Done() - for { - partStart := int(atomic.AddUint64(&idx, uint64(partSize))) - partSize - if partStart >= dataSize { - break - } - partEnd := partStart + partSize - if partEnd > dataSize { - partEnd = dataSize - } - fn(partStart, partEnd) - } - }() - } + c := make(chan int, count) + for i := start; i < stop; i++ { + c <- i + } + close(c) - wg.Wait() + var wg sync.WaitGroup + for i := 0; i < procs; i++ { + wg.Add(1) + go func() { + defer wg.Done() + fn(c) + }() } + wg.Wait() } // absint returns the absolute value of i. @@ -69,3 +54,30 @@ func clamp(x float64) uint8 { } return 0 } + +func reverse(pix []uint8) { + if len(pix) <= 4 { + return + } + i := 0 + j := len(pix) - 4 + for i < j { + pix[i+0], pix[j+0] = pix[j+0], pix[i+0] + pix[i+1], pix[j+1] = pix[j+1], pix[i+1] + pix[i+2], pix[j+2] = pix[j+2], pix[i+2] + pix[i+3], pix[j+3] = pix[j+3], pix[i+3] + i += 4 + j -= 4 + } +} + +func toNRGBA(img image.Image) *image.NRGBA { + if img, ok := img.(*image.NRGBA); ok { + return &image.NRGBA{ + Pix: img.Pix, + Stride: img.Stride, + Rect: img.Rect.Sub(img.Rect.Min), + } + } + return Clone(img) +} diff --git a/vendor/github.com/disintegration/imaging/utils_test.go b/vendor/github.com/disintegration/imaging/utils_test.go deleted file mode 100644 index 44cc75102..000000000 --- a/vendor/github.com/disintegration/imaging/utils_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package imaging - -import ( - "runtime" - "testing" -) - -func testParallelN(enabled bool, n, procs int) bool { - data := make([]bool, n) - before := runtime.GOMAXPROCS(0) - runtime.GOMAXPROCS(procs) - parallel(n, func(start, end int) { - for i := start; i < end; i++ { - data[i] = true - } - }) - for i := 0; i < n; i++ { - if !data[i] { - return false - } - } - runtime.GOMAXPROCS(before) - return true -} - -func TestParallel(t *testing.T) { - for _, e := range []bool{true, false} { - for _, n := range []int{1, 10, 100, 1000} { - for _, p := range []int{1, 2, 4, 8, 16, 100} { - if !testParallelN(e, n, p) { - t.Errorf("test [parallel %v %d %d] failed", e, n, p) - } - } - } - } -} - -func TestClamp(t *testing.T) { - td := []struct { - f float64 - u uint8 - }{ - {0, 0}, - {255, 255}, - {128, 128}, - {0.49, 0}, - {0.50, 1}, - {254.9, 255}, - {254.0, 254}, - {256, 255}, - {2500, 255}, - {-10, 0}, - {127.6, 128}, - } - - for _, d := range td { - if clamp(d.f) != d.u { - t.Errorf("test [clamp %v %v] failed: %v", d.f, d.u, clamp(d.f)) - } - } -} -- cgit v1.2.3-1-g7c22