diff options
author | Tulir Asokan <tulir@maunium.net> | 2019-01-11 23:28:47 +0200 |
---|---|---|
committer | Tulir Asokan <tulir@maunium.net> | 2019-01-11 23:28:47 +0200 |
commit | 331597b9f8a7942cbcb233a328301e4d5bf94fb0 (patch) | |
tree | 5ec624585ebf66c63549a098acb6f7421f1193a7 /vendor/github.com/disintegration/imaging | |
parent | 2fc3378b717f40f37f3a188b68407887242d9c06 (diff) |
Switch to Go modules and make other changes
Diffstat (limited to 'vendor/github.com/disintegration/imaging')
-rw-r--r-- | vendor/github.com/disintegration/imaging/.travis.yml | 13 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/LICENSE | 21 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/README.md | 188 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/adjust.go | 222 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/convolution.go | 146 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/doc.go | 7 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/effects.go | 173 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/histogram.go | 51 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/io.go | 463 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/resize.go | 572 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/scanner.go | 250 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/tools.go | 247 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/transform.go | 271 | ||||
-rw-r--r-- | vendor/github.com/disintegration/imaging/utils.go | 83 |
14 files changed, 0 insertions, 2707 deletions
diff --git a/vendor/github.com/disintegration/imaging/.travis.yml b/vendor/github.com/disintegration/imaging/.travis.yml deleted file mode 100644 index 89370ed..0000000 --- a/vendor/github.com/disintegration/imaging/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: go -go: - - "1.7.x" - - "1.8.x" - - "1.9.x" - - "1.10.x" - -before_install: - - go get github.com/mattn/goveralls - -script: - - go test -v -race -cover - - $GOPATH/bin/goveralls -service=travis-ci diff --git a/vendor/github.com/disintegration/imaging/LICENSE b/vendor/github.com/disintegration/imaging/LICENSE deleted file mode 100644 index c68f7ab..0000000 --- a/vendor/github.com/disintegration/imaging/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -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 -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE.
\ No newline at end of file diff --git a/vendor/github.com/disintegration/imaging/README.md b/vendor/github.com/disintegration/imaging/README.md deleted file mode 100644 index c7ee30f..0000000 --- a/vendor/github.com/disintegration/imaging/README.md +++ /dev/null @@ -1,188 +0,0 @@ -# Imaging
-
-[![GoDoc](https://godoc.org/github.com/disintegration/imaging?status.svg)](https://godoc.org/github.com/disintegration/imaging)
-[![Build Status](https://travis-ci.org/disintegration/imaging.svg?branch=master)](https://travis-ci.org/disintegration/imaging)
-[![Coverage Status](https://coveralls.io/repos/github/disintegration/imaging/badge.svg?branch=master&service=github)](https://coveralls.io/github/disintegration/imaging?branch=master)
-[![Go Report Card](https://goreportcard.com/badge/github.com/disintegration/imaging)](https://goreportcard.com/report/github.com/disintegration/imaging)
-
-Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
-
-All the image processing functions provided by the package accept any image type that implements `image.Image` interface
-as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, not premultiplied by alpha).
-
-## Installation
-
- go get -u github.com/disintegration/imaging
-
-## Documentation
-
-http://godoc.org/github.com/disintegration/imaging
-
-## Usage examples
-
-A few usage examples can be found below. See the documentation for the full list of supported functions.
-
-### Image resizing
-
-```go
-// Resize srcImage to size = 128x128px using the Lanczos filter.
-dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
-
-// Resize srcImage to width = 800px preserving the aspect ratio.
-dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
-
-// Scale down srcImage to fit the 800x600px bounding box.
-dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
-
-// Resize and crop the srcImage to fill the 100x100px area.
-dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
-```
-
-Imaging supports image resizing using various resampling filters. The most notable ones:
-- `NearestNeighbor` - Fastest resampling filter, no antialiasing.
-- `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.
-- `Gaussian` - Blurring filter that uses gaussian function, useful for noise removal.
-- `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**
-
-Original image:
-
-![srcImage](testdata/branches.png)
-
-The same image resized from 600x400px to 150x100px using different resampling filters.
-From faster (lower quality) to slower (higher quality):
-
-Filter | Resize result
---------------------------|---------------------------------------------
-`imaging.NearestNeighbor` | ![dstImage](testdata/out_resize_nearest.png)
-`imaging.Linear` | ![dstImage](testdata/out_resize_linear.png)
-`imaging.CatmullRom` | ![dstImage](testdata/out_resize_catrom.png)
-`imaging.Lanczos` | ![dstImage](testdata/out_resize_lanczos.png)
-
-
-### Gaussian Blur
-
-```go
-dstImage := imaging.Blur(srcImage, 0.5)
-```
-
-Sigma parameter allows to control the strength of the blurring effect.
-
-Original image | Sigma = 0.5 | Sigma = 1.5
------------------------------------|----------------------------------------|---------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_blur_0.5.png) | ![dstImage](testdata/out_blur_1.5.png)
-
-### Sharpening
-
-```go
-dstImage := imaging.Sharpen(srcImage, 0.5)
-```
-
-`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
-
-Original image | Sigma = 0.5 | Sigma = 1.5
------------------------------------|-------------------------------------------|------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_sharpen_0.5.png) | ![dstImage](testdata/out_sharpen_1.5.png)
-
-### Gamma correction
-
-```go
-dstImage := imaging.AdjustGamma(srcImage, 0.75)
-```
-
-Original image | Gamma = 0.75 | Gamma = 1.25
------------------------------------|------------------------------------------|-----------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_gamma_0.75.png) | ![dstImage](testdata/out_gamma_1.25.png)
-
-### Contrast adjustment
-
-```go
-dstImage := imaging.AdjustContrast(srcImage, 20)
-```
-
-Original image | Contrast = 15 | Contrast = -15
------------------------------------|--------------------------------------------|-------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_contrast_p15.png) | ![dstImage](testdata/out_contrast_m15.png)
-
-### Brightness adjustment
-
-```go
-dstImage := imaging.AdjustBrightness(srcImage, 20)
-```
-
-Original image | Brightness = 10 | Brightness = -10
------------------------------------|----------------------------------------------|---------------------------------------------
-![srcImage](testdata/flowers_small.png) | ![dstImage](testdata/out_brightness_p10.png) | ![dstImage](testdata/out_brightness_m10.png)
-
-## Example code
-
-```go
-package main
-
-import (
- "image"
- "image/color"
- "log"
-
- "github.com/disintegration/imaging"
-)
-
-func main() {
- // Open a test image.
- src, err := imaging.Open("testdata/flowers.png")
- if err != nil {
- log.Fatalf("failed to open image: %v", err)
- }
-
- // Crop the original image to 300x300px size using the center anchor.
- src = imaging.CropAnchor(src, 300, 300, imaging.Center)
-
- // Resize the cropped image to width = 200px preserving the aspect ratio.
- src = imaging.Resize(src, 200, 0, imaging.Lanczos)
-
- // Create a blurred version of the image.
- img1 := imaging.Blur(src, 5)
-
- // Create a grayscale version of the image with higher contrast and sharpness.
- img2 := imaging.Grayscale(src)
- img2 = imaging.AdjustContrast(img2, 20)
- img2 = imaging.Sharpen(img2, 2)
-
- // Create an inverted version of the image.
- img3 := imaging.Invert(src)
-
- // Create an embossed version of the image using a convolution filter.
- img4 := imaging.Convolve3x3(
- src,
- [9]float64{
- -1, -1, 0,
- -1, 1, 1,
- 0, 1, 1,
- },
- nil,
- )
-
- // Create a new image and paste the four produced images into it.
- dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
- dst = imaging.Paste(dst, img1, image.Pt(0, 0))
- dst = imaging.Paste(dst, img2, image.Pt(0, 200))
- dst = imaging.Paste(dst, img3, image.Pt(200, 0))
- dst = imaging.Paste(dst, img4, image.Pt(200, 200))
-
- // Save the resulting image as JPEG.
- err = imaging.Save(dst, "testdata/out_example.jpg")
- if err != nil {
- log.Fatalf("failed to save image: %v", err)
- }
-}
-```
-
-Output:
-
-![dstImage](testdata/out_example.jpg)
\ No newline at end of file diff --git a/vendor/github.com/disintegration/imaging/adjust.go b/vendor/github.com/disintegration/imaging/adjust.go deleted file mode 100644 index fb3a9ce..0000000 --- a/vendor/github.com/disintegration/imaging/adjust.go +++ /dev/null @@ -1,222 +0,0 @@ -package imaging - -import ( - "image" - "image/color" - "math" -) - -// 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. -// -// 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) - - 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 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. -// Gamma parameter must be positive. Gamma = 1.0 gives the original image. -// Gamma less than 1.0 darkens the image and gamma greater than 1.0 lightens it. -// -// Example: -// -// dstImage = imaging.AdjustGamma(srcImage, 0.7) -// -func AdjustGamma(img image.Image, gamma float64) *image.NRGBA { - e := 1.0 / math.Max(gamma, 0.0001) - lut := make([]uint8, 256) - - for i := 0; i < 256; i++ { - lut[i] = clamp(math.Pow(float64(i)/255.0, e) * 255.0) - } - - return adjustLUT(img, lut) -} - -// AdjustSigmoid changes the contrast of the image using a sigmoidal function and returns the adjusted image. -// It's a non-linear contrast change useful for photo adjustments as it preserves highlight and shadow detail. -// The midpoint parameter is the midpoint of contrast that must be between 0 and 1, typically 0.5. -// The factor parameter indicates how much to increase or decrease the contrast, typically in range (-10, 10). -// If the factor parameter is positive the image contrast is increased otherwise the contrast is decreased. -// -// Examples: -// -// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, 3.0) // increase the contrast -// dstImage = imaging.AdjustSigmoid(srcImage, 0.5, -3.0) // decrease the contrast -// -func AdjustSigmoid(img image.Image, midpoint, factor float64) *image.NRGBA { - if factor == 0 { - return Clone(img) - } - - lut := make([]uint8, 256) - a := math.Min(math.Max(midpoint, 0.0), 1.0) - b := math.Abs(factor) - sig0 := sigmoid(a, b, 0) - sig1 := sigmoid(a, b, 1) - e := 1.0e-6 - - if factor > 0 { - for i := 0; i < 256; i++ { - x := float64(i) / 255.0 - sigX := sigmoid(a, b, x) - f := (sigX - sig0) / (sig1 - sig0) - lut[i] = clamp(f * 255.0) - } - } else { - for i := 0; i < 256; i++ { - x := float64(i) / 255.0 - arg := math.Min(math.Max((sig1-sig0)*x+sig0, e), 1.0-e) - f := a - math.Log(1.0/arg-1.0)/b - lut[i] = clamp(f * 255.0) - } - } - - return adjustLUT(img, lut) -} - -func sigmoid(a, b, x float64) float64 { - return 1 / (1 + math.Exp(b*(a-x))) -} - -// 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 - } - } - }) - return dst -} - -// AdjustFunc applies the fn function to each pixel of the img image and returns the adjusted image. -// -// Example: -// -// 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 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/convolution.go b/vendor/github.com/disintegration/imaging/convolution.go deleted file mode 100644 index 9e6404d..0000000 --- a/vendor/github.com/disintegration/imaging/convolution.go +++ /dev/null @@ -1,146 +0,0 @@ -package imaging - -import ( - "image" -) - -// ConvolveOptions are convolution parameters. -type ConvolveOptions struct { - // If Normalize is true the kernel is normalized before convolution. - Normalize bool - - // If Abs is true the absolute value of each color channel is taken after convolution. - Abs bool - - // Bias is added to each color channel value after convolution. - Bias int -} - -// Convolve3x3 convolves the image with the specified 3x3 convolution kernel. -// Default parameters are used if a nil *ConvolveOptions is passed. -func Convolve3x3(img image.Image, kernel [9]float64, options *ConvolveOptions) *image.NRGBA { - return convolve(img, kernel[:], options) -} - -// Convolve5x5 convolves the image with the specified 5x5 convolution kernel. -// Default parameters are used if a nil *ConvolveOptions is passed. -func Convolve5x5(img image.Image, kernel [25]float64, options *ConvolveOptions) *image.NRGBA { - return convolve(img, kernel[:], options) -} - -func convolve(img image.Image, kernel []float64, options *ConvolveOptions) *image.NRGBA { - src := toNRGBA(img) - w := src.Bounds().Max.X - h := src.Bounds().Max.Y - dst := image.NewNRGBA(image.Rect(0, 0, w, h)) - - if w < 1 || h < 1 { - return dst - } - - if options == nil { - options = &ConvolveOptions{} - } - - if options.Normalize { - normalizeKernel(kernel) - } - - type coef struct { - x, y int - k float64 - } - var coefs []coef - var m int - - switch len(kernel) { - case 9: - m = 1 - case 25: - m = 2 - } - - i := 0 - for y := -m; y <= m; y++ { - for x := -m; x <= m; x++ { - if kernel[i] != 0 { - coefs = append(coefs, coef{x: x, y: y, k: kernel[i]}) - } - i++ - } - } - - 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 { - ix := x + c.x - if ix < 0 { - ix = 0 - } else if ix >= w { - ix = w - 1 - } - - iy := y + c.y - if iy < 0 { - iy = 0 - } else if iy >= h { - iy = h - 1 - } - - off := iy*src.Stride + ix*4 - r += float64(src.Pix[off+0]) * c.k - g += float64(src.Pix[off+1]) * c.k - b += float64(src.Pix[off+2]) * c.k - } - - if options.Abs { - if r < 0 { - r = -r - } - if g < 0 { - g = -g - } - if b < 0 { - b = -b - } - } - - if options.Bias != 0 { - r += float64(options.Bias) - g += float64(options.Bias) - b += float64(options.Bias) - } - - srcOff := y*src.Stride + x*4 - dstOff := y*dst.Stride + x*4 - dst.Pix[dstOff+0] = clamp(r) - dst.Pix[dstOff+1] = clamp(g) - dst.Pix[dstOff+2] = clamp(b) - dst.Pix[dstOff+3] = src.Pix[srcOff+3] - } - } - }) - - return dst -} - -func normalizeKernel(kernel []float64) { - var sum, sumpos float64 - for i := range kernel { - sum += kernel[i] - if kernel[i] > 0 { - sumpos += kernel[i] - } - } - if sum != 0 { - for i := range kernel { - kernel[i] /= sum - } - } else if sumpos != 0 { - for i := range kernel { - kernel[i] /= sumpos - } - } -} diff --git a/vendor/github.com/disintegration/imaging/doc.go b/vendor/github.com/disintegration/imaging/doc.go deleted file mode 100644 index 5d59b46..0000000 --- a/vendor/github.com/disintegration/imaging/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -/* -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 deleted file mode 100644 index 149cfeb..0000000 --- a/vendor/github.com/disintegration/imaging/effects.go +++ /dev/null @@ -1,173 +0,0 @@ -package imaging - -import ( - "image" - "math" -) - -func gaussianBlurKernel(x, sigma float64) float64 { - return math.Exp(-(x*x)/(2*sigma*sigma)) / (sigma * math.Sqrt(2*math.Pi)) -} - -// Blur produces a blurred version of the image using a Gaussian function. -// Sigma parameter must be positive and indicates how much the image will be blurred. -// -// Usage example: -// -// dstImage := imaging.Blur(srcImage, 3.5) -// -func Blur(img image.Image, sigma float64) *image.NRGBA { - if sigma <= 0 { - return Clone(img) - } - - radius := int(math.Ceil(sigma * 3.0)) - kernel := make([]float64, radius+1) - - for i := 0; i <= radius; i++ { - kernel[i] = gaussianBlurKernel(float64(i), sigma) - } - - return blurVertical(blurHorizontal(img, kernel), kernel) -} - -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 - - parallel(0, src.h, func(ys <-chan int) { - scanLine := make([]uint8, src.w*4) - scanLineF := make([]float64, len(scanLine)) - for y := range ys { - src.scan(0, y, src.w, y+1, scanLine) - for i, v := range scanLine { - scanLineF[i] = float64(v) - } - for x, idx := 0, 0; x < src.w; x, idx = x+1, idx+4 { - min := x - radius - if min < 0 { - min = 0 - } - max := x + radius - if max > src.w-1 { - max = src.w - 1 - } - - var r, g, b, a, wsum float64 - for ix := min; ix <= max; ix++ { - i := ix * 4 - weight := kernel[absint(x-ix)] - wsum += weight - wa := scanLineF[i+3] * weight - r += scanLineF[i+0] * wa - g += scanLineF[i+1] * wa - b += scanLineF[i+2] * wa - a += wa - } - if a != 0 { - r /= a - g /= a - b /= a - } - - scanLine[idx+0] = clamp(r) - scanLine[idx+1] = clamp(g) - scanLine[idx+2] = clamp(b) - scanLine[idx+3] = clamp(a / wsum) - } - copy(dst.Pix[y*dst.Stride:], scanLine) - } - }) - - return dst -} - -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 - - parallel(0, src.w, func(xs <-chan int) { - scanLine := make([]uint8, src.h*4) - scanLineF := make([]float64, len(scanLine)) - for x := range xs { - src.scan(x, 0, x+1, src.h, scanLine) - for i, v := range scanLine { - scanLineF[i] = float64(v) - } - 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 - } - - var r, g, b, a, wsum float64 - for iy := min; iy <= max; iy++ { - i := iy * 4 - weight := kernel[absint(y-iy)] - wsum += weight - wa := scanLineF[i+3] * weight - r += scanLineF[i+0] * wa - g += scanLineF[i+1] * wa - b += scanLineF[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) - dst.Pix[j+1] = clamp(g) - dst.Pix[j+2] = clamp(b) - dst.Pix[j+3] = clamp(a / wsum) - } - } - }) - - return dst -} - -// Sharpen produces a sharpened version of the image. -// Sigma parameter must be positive and indicates how much the image will be sharpened. -// -// Usage example: -// -// dstImage := imaging.Sharpen(srcImage, 3.5) -// -func Sharpen(img image.Image, sigma float64) *image.NRGBA { - if sigma <= 0 { - return Clone(img) - } - - src := newScanner(img) - dst := image.NewNRGBA(image.Rect(0, 0, src.w, src.h)) - blurred := Blur(img, sigma) - - 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++ - } - } - }) - - return dst -} diff --git a/vendor/github.com/disintegration/imaging/histogram.go b/vendor/github.com/disintegration/imaging/histogram.go deleted file mode 100644 index 5bcb001..0000000 --- a/vendor/github.com/disintegration/imaging/histogram.go +++ /dev/null @@ -1,51 +0,0 @@ -package imaging - -import ( - "image" - "sync" -) - -// Histogram returns a normalized histogram of an image. -// -// 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 { - var mu sync.Mutex - var histogram [256]float64 - var total float64 - - src := newScanner(img) - if src.w == 0 || src.h == 0 { - return histogram - } - - 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/io.go b/vendor/github.com/disintegration/imaging/io.go deleted file mode 100644 index 557bf2f..0000000 --- a/vendor/github.com/disintegration/imaging/io.go +++ /dev/null @@ -1,463 +0,0 @@ -package imaging - -import ( - "encoding/binary" - "errors" - "image" - "image/draw" - "image/gif" - "image/jpeg" - "image/png" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - - "golang.org/x/image/bmp" - "golang.org/x/image/tiff" -) - -// Format is an image file format. -type Format int - -// Image file formats. -const ( - JPEG Format = iota - PNG - GIF - TIFF - BMP -) - -func (f Format) String() string { - switch f { - case JPEG: - return "JPEG" - case PNG: - return "PNG" - case GIF: - return "GIF" - case TIFF: - return "TIFF" - case BMP: - return "BMP" - default: - return "Unsupported" - } -} - -var formatFromExt = map[string]Format{ - "jpg": JPEG, - "jpeg": JPEG, - "png": PNG, - "tif": TIFF, - "tiff": TIFF, - "bmp": BMP, - "gif": GIF, -} - -// FormatFromExtension parses image format from extension: -// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. -func FormatFromExtension(ext string) (Format, error) { - if f, ok := formatFromExt[strings.ToLower(strings.TrimPrefix(ext, "."))]; ok { - return f, nil - } - return -1, ErrUnsupportedFormat -} - -// FormatFromFilename parses image format from filename extension: -// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. -func FormatFromFilename(filename string) (Format, error) { - ext := filepath.Ext(filename) - return FormatFromExtension(ext) -} - -var ( - // ErrUnsupportedFormat means the given image format (or file extension) is unsupported. - 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{} - -type decodeConfig struct { - autoOrientation bool -} - -var defaultDecodeConfig = decodeConfig{ - autoOrientation: false, -} - -// DecodeOption sets an optional parameter for the Decode and Open functions. -type DecodeOption func(*decodeConfig) - -// AutoOrientation returns a DecodeOption that sets the auto-orientation mode. -// If auto-orientation is enabled, the image will be transformed after decoding -// according to the EXIF orientation tag (if present). By default it's disabled. -func AutoOrientation(enabled bool) DecodeOption { - return func(c *decodeConfig) { - c.autoOrientation = enabled - } -} - -// Decode reads an image from r. -func Decode(r io.Reader, opts ...DecodeOption) (image.Image, error) { - cfg := defaultDecodeConfig - for _, option := range opts { - option(&cfg) - } - - if !cfg.autoOrientation { - img, _, err := image.Decode(r) - return img, err - } - - var orient orientation - pr, pw := io.Pipe() - r = io.TeeReader(r, pw) - done := make(chan struct{}) - go func() { - defer close(done) - orient = readOrientation(pr) - io.Copy(ioutil.Discard, pr) - }() - - img, _, err := image.Decode(r) - pw.Close() - <-done - if err != nil { - return nil, err - } - - return fixOrientation(img, orient), nil -} - -// Open loads an image from file. -// -// Examples: -// -// // Load an image from file. -// img, err := imaging.Open("test.jpg") -// -// // Load an image and transform it depending on the EXIF orientation tag (if present). -// img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true)) -// -func Open(filename string, opts ...DecodeOption) (image.Image, error) { - file, err := fs.Open(filename) - if err != nil { - return nil, err - } - defer file.Close() - return Decode(file, opts...) -} - -type encodeConfig struct { - jpegQuality int - gifNumColors int - gifQuantizer draw.Quantizer - gifDrawer draw.Drawer - pngCompressionLevel png.CompressionLevel -} - -var defaultEncodeConfig = encodeConfig{ - jpegQuality: 95, - gifNumColors: 256, - gifQuantizer: nil, - gifDrawer: nil, - pngCompressionLevel: png.DefaultCompression, -} - -// EncodeOption sets an optional parameter for the Encode and Save functions. -type EncodeOption func(*encodeConfig) - -// JPEGQuality returns an EncodeOption that sets the output JPEG quality. -// Quality ranges from 1 to 100 inclusive, higher is better. Default is 95. -func JPEGQuality(quality int) EncodeOption { - return func(c *encodeConfig) { - c.jpegQuality = quality - } -} - -// 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 - for _, option := range opts { - option(&cfg) - } - - var err error - switch format { - case JPEG: - var rgba *image.RGBA - if nrgba, ok := img.(*image.NRGBA); ok { - if nrgba.Opaque() { - rgba = &image.RGBA{ - Pix: nrgba.Pix, - Stride: nrgba.Stride, - Rect: nrgba.Rect, - } - } - } - if rgba != nil { - err = jpeg.Encode(w, rgba, &jpeg.Options{Quality: cfg.jpegQuality}) - } else { - err = jpeg.Encode(w, img, &jpeg.Options{Quality: cfg.jpegQuality}) - } - - case PNG: - enc := png.Encoder{CompressionLevel: cfg.pngCompressionLevel} - err = enc.Encode(w, img) - - case GIF: - 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 - } - return err -} - -// Save saves the image to file with the specified filename. -// The format is determined from the filename extension: -// "jpg" (or "jpeg"), "png", "gif", "tif" (or "tiff") and "bmp" are supported. -// -// Examples: -// -// // Save the image as PNG. -// err := imaging.Save(img, "out.png") -// -// // Save the image as JPEG with optional quality parameter set to 80. -// err := imaging.Save(img, "out.jpg", imaging.JPEGQuality(80)) -// -func Save(img image.Image, filename string, opts ...EncodeOption) (err error) { - f, err := FormatFromFilename(filename) - if err != nil { - return err - } - file, err := fs.Create(filename) - if err != nil { - return err - } - - defer func() { - cerr := file.Close() - if err == nil { - err = cerr - } - }() - - return Encode(file, img, f, opts...) -} - -// orientation is an EXIF flag that specifies the transformation -// that should be applied to image to display it correctly. -type orientation int - -const ( - orientationUnspecified = 0 - orientationNormal = 1 - orientationFlipH = 2 - orientationRotate180 = 3 - orientationFlipV = 4 - orientationTranspose = 5 - orientationRotate270 = 6 - orientationTransverse = 7 - orientationRotate90 = 8 -) - -// readOrientation tries to read the orientation EXIF flag from image data in r. -// If the EXIF data block is not found or the orientation flag is not found -// or any other error occures while reading the data, it returns the -// orientationUnspecified (0) value. -func readOrientation(r io.Reader) orientation { - const ( - markerSOI = 0xffd8 - markerAPP1 = 0xffe1 - exifHeader = 0x45786966 - byteOrderBE = 0x4d4d - byteOrderLE = 0x4949 - orientationTag = 0x0112 - ) - - // Check if JPEG SOI marker is present. - var soi uint16 - if err := binary.Read(r, binary.BigEndian, &soi); err != nil { - return orientationUnspecified - } - if soi != markerSOI { - return orientationUnspecified // Missing JPEG SOI marker. - } - - // Find JPEG APP1 marker. - for { - var marker, size uint16 - if err := binary.Read(r, binary.BigEndian, &marker); err != nil { - return orientationUnspecified - } - if err := binary.Read(r, binary.BigEndian, &size); err != nil { - return orientationUnspecified - } - if marker>>8 != 0xff { - return orientationUnspecified // Invalid JPEG marker. - } - if marker == markerAPP1 { - break - } - if size < 2 { - return orientationUnspecified // Invalid block size. - } - if _, err := io.CopyN(ioutil.Discard, r, int64(size-2)); err != nil { - return orientationUnspecified - } - } - - // Check if EXIF header is present. - var header uint32 - if err := binary.Read(r, binary.BigEndian, &header); err != nil { - return orientationUnspecified - } - if header != exifHeader { - return orientationUnspecified - } - if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil { - return orientationUnspecified - } - - // Read byte order information. - var ( - byteOrderTag uint16 - byteOrder binary.ByteOrder - ) - if err := binary.Read(r, binary.BigEndian, &byteOrderTag); err != nil { - return orientationUnspecified - } - switch byteOrderTag { - case byteOrderBE: - byteOrder = binary.BigEndian - case byteOrderLE: - byteOrder = binary.LittleEndian - default: - return orientationUnspecified // Invalid byte order flag. - } - if _, err := io.CopyN(ioutil.Discard, r, 2); err != nil { - return orientationUnspecified - } - - // Skip the EXIF offset. - var offset uint32 - if err := binary.Read(r, byteOrder, &offset); err != nil { - return orientationUnspecified - } - if offset < 8 { - return orientationUnspecified // Invalid offset value. - } - if _, err := io.CopyN(ioutil.Discard, r, int64(offset-8)); err != nil { - return orientationUnspecified - } - - // Read the number of tags. - var numTags uint16 - if err := binary.Read(r, byteOrder, &numTags); err != nil { - return orientationUnspecified - } - - // Find the orientation tag. - for i := 0; i < int(numTags); i++ { - var tag uint16 - if err := binary.Read(r, byteOrder, &tag); err != nil { - return orientationUnspecified - } - if tag != orientationTag { - if _, err := io.CopyN(ioutil.Discard, r, 10); err != nil { - return orientationUnspecified - } - continue - } - if _, err := io.CopyN(ioutil.Discard, r, 6); err != nil { - return orientationUnspecified - } - var val uint16 - if err := binary.Read(r, byteOrder, &val); err != nil { - return orientationUnspecified - } - if val < 1 || val > 8 { - return orientationUnspecified // Invalid tag value. - } - return orientation(val) - } - return orientationUnspecified // Missing orientation tag. -} - -// fixOrientation applies a transform to img corresponding to the given orientation flag. -func fixOrientation(img image.Image, o orientation) image.Image { - switch o { - case orientationNormal: - case orientationFlipH: - img = FlipH(img) - case orientationFlipV: - img = FlipV(img) - case orientationRotate90: - img = Rotate90(img) - case orientationRotate180: - img = Rotate180(img) - case orientationRotate270: - img = Rotate270(img) - case orientationTranspose: - img = Transpose(img) - case orientationTransverse: - img = Transverse(img) - } - return img -} diff --git a/vendor/github.com/disintegration/imaging/resize.go b/vendor/github.com/disintegration/imaging/resize.go deleted file mode 100644 index 97f498a..0000000 --- a/vendor/github.com/disintegration/imaging/resize.go +++ /dev/null @@ -1,572 +0,0 @@ -package imaging - -import ( - "image" - "math" -) - -type indexWeight struct { - index int - weight float64 -} - -func precomputeWeights(dstSize, srcSize int, filter ResampleFilter) [][]indexWeight { - du := float64(srcSize) / float64(dstSize) - scale := du - if scale < 1.0 { - scale = 1.0 - } - ru := math.Ceil(scale * filter.Support) - - out := make([][]indexWeight, dstSize) - tmp := make([]indexWeight, 0, dstSize*int(ru+2)*2) - - for v := 0; v < dstSize; v++ { - fu := (float64(v)+0.5)*du - 0.5 - - begin := int(math.Ceil(fu - ru)) - if begin < 0 { - begin = 0 - } - end := int(math.Floor(fu + ru)) - if end > srcSize-1 { - end = srcSize - 1 - } - - var sum float64 - for u := begin; u <= end; u++ { - w := filter.Kernel((float64(u) - fu) / scale) - if w != 0 { - sum += w - tmp = append(tmp, indexWeight{index: u, weight: w}) - } - } - if sum != 0 { - for i := range tmp { - tmp[i].weight /= sum - } - } - - out[v] = tmp - tmp = tmp[len(tmp):] - } - - return out -} - -// Resize resizes the image to the specified width and height using the specified resampling -// filter and returns the transformed image. If one of width or height is 0, the image aspect -// ratio is preserved. -// -// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, -// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. -// -// Usage example: -// -// dstImage := imaging.Resize(srcImage, 800, 600, imaging.Lanczos) -// -func Resize(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { - dstW, dstH := width, height - if dstW < 0 || dstH < 0 { - return &image.NRGBA{} - } - if dstW == 0 && dstH == 0 { - return &image.NRGBA{} - } - - 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 dstW == 0 { - tmpW := float64(dstH) * float64(srcW) / float64(srcH) - dstW = int(math.Max(1.0, math.Floor(tmpW+0.5))) - } - if dstH == 0 { - tmpH := float64(dstW) * float64(srcH) / float64(srcW) - dstH = int(math.Max(1.0, math.Floor(tmpH+0.5))) - } - - if filter.Support <= 0 { - // Nearest-neighbor special case. - return resizeNearest(img, dstW, dstH) - } - - 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(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[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 + x*4 - dst.Pix[j+0] = clamp(r * aInv) - dst.Pix[j+1] = clamp(g * aInv) - dst.Pix[j+2] = clamp(b * aInv) - dst.Pix[j+3] = clamp(a) - } - } - } - }) - return dst -} - -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[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 := 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) - dst.Pix[j+3] = clamp(a) - } - } - } - }) - return dst -} - -// resizeNearest is a fast nearest-neighbor resize, no filtering. -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 - } - } - }) - } 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 - } - } - }) - } - - return dst -} - -// Fit scales down the image using the specified resample filter to fit the specified -// maximum width and height and returns the transformed image. -// -// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, -// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. -// -// Usage example: -// -// dstImage := imaging.Fit(srcImage, 800, 600, imaging.Lanczos) -// -func Fit(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { - maxW, maxH := width, height - - if maxW <= 0 || maxH <= 0 { - return &image.NRGBA{} - } - - srcBounds := img.Bounds() - srcW := srcBounds.Dx() - srcH := srcBounds.Dy() - - if srcW <= 0 || srcH <= 0 { - return &image.NRGBA{} - } - - if srcW <= maxW && srcH <= maxH { - return Clone(img) - } - - srcAspectRatio := float64(srcW) / float64(srcH) - maxAspectRatio := float64(maxW) / float64(maxH) - - var newW, newH int - if srcAspectRatio > maxAspectRatio { - newW = maxW - newH = int(float64(newW) / srcAspectRatio) - } else { - newH = maxH - newW = int(float64(newH) * srcAspectRatio) - } - - return Resize(img, newW, newH, filter) -} - -// Fill scales the image to the smallest possible size that will cover the specified dimensions, -// crops the resized image to the specified dimensions using the given anchor point and returns -// the transformed image. -// -// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, -// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. -// -// Usage example: -// -// dstImage := imaging.Fill(srcImage, 800, 600, imaging.Center, imaging.Lanczos) -// -func Fill(img image.Image, width, height int, anchor Anchor, filter ResampleFilter) *image.NRGBA { - minW, minH := width, height - - if minW <= 0 || minH <= 0 { - return &image.NRGBA{} - } - - srcBounds := img.Bounds() - srcW := srcBounds.Dx() - srcH := srcBounds.Dy() - - if srcW <= 0 || srcH <= 0 { - return &image.NRGBA{} - } - - if srcW == minW && srcH == minH { - return Clone(img) - } - - srcAspectRatio := float64(srcW) / float64(srcH) - minAspectRatio := float64(minW) / float64(minH) - - var tmp *image.NRGBA - if srcAspectRatio < minAspectRatio { - tmp = Resize(img, minW, 0, filter) - } else { - tmp = Resize(img, 0, minH, filter) - } - - return CropAnchor(tmp, minW, minH, anchor) -} - -// Thumbnail scales the image up or down using the specified resample filter, crops it -// to the specified width and hight and returns the transformed image. -// -// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, -// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. -// -// Usage example: -// -// dstImage := imaging.Thumbnail(srcImage, 100, 100, imaging.Lanczos) -// -func Thumbnail(img image.Image, width, height int, filter ResampleFilter) *image.NRGBA { - return Fill(img, width, height, Center, filter) -} - -// ResampleFilter is a resampling filter struct. It can be used to define custom filters. -// -// Supported resample filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, -// CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. -// -// General filter recommendations: -// -// - Lanczos -// 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 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. -// -// - Box -// Simple and fast averaging filter appropriate for downscaling. -// When upscaling it's similar to NearestNeighbor. -// -// - NearestNeighbor -// Fastest resampling filter, no antialiasing. -// -type ResampleFilter struct { - Support float64 - Kernel func(float64) float64 -} - -// NearestNeighbor is a nearest-neighbor filter (no anti-aliasing). -var NearestNeighbor ResampleFilter - -// Box filter (averaging pixels). -var Box ResampleFilter - -// Linear filter. -var Linear ResampleFilter - -// Hermite cubic spline filter (BC-spline; B=0; C=0). -var Hermite ResampleFilter - -// MitchellNetravali is Mitchell-Netravali cubic filter (BC-spline; B=1/3; C=1/3). -var MitchellNetravali ResampleFilter - -// CatmullRom is a Catmull-Rom - sharp cubic filter (BC-spline; B=0; C=0.5). -var CatmullRom ResampleFilter - -// BSpline is a smooth cubic filter (BC-spline; B=1; C=0). -var BSpline ResampleFilter - -// Gaussian is a Gaussian blurring Filter. -var Gaussian ResampleFilter - -// Bartlett is a Bartlett-windowed sinc filter (3 lobes). -var Bartlett ResampleFilter - -// Lanczos filter (3 lobes). -var Lanczos ResampleFilter - -// Hann is a Hann-windowed sinc filter (3 lobes). -var Hann ResampleFilter - -// Hamming is a Hamming-windowed sinc filter (3 lobes). -var Hamming ResampleFilter - -// Blackman is a Blackman-windowed sinc filter (3 lobes). -var Blackman ResampleFilter - -// Welch is a Welch-windowed sinc filter (parabolic window, 3 lobes). -var Welch ResampleFilter - -// Cosine is a Cosine-windowed sinc filter (3 lobes). -var Cosine ResampleFilter - -func bcspline(x, b, c float64) float64 { - var y float64 - x = math.Abs(x) - if x < 1.0 { - 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 y -} - -func sinc(x float64) float64 { - if x == 0 { - return 1 - } - return math.Sin(math.Pi*x) / (math.Pi * x) -} - -func init() { - NearestNeighbor = ResampleFilter{ - Support: 0.0, // special case - not applying the filter - } - - Box = ResampleFilter{ - Support: 0.5, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x <= 0.5 { - return 1.0 - } - return 0 - }, - } - - Linear = ResampleFilter{ - Support: 1.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 1.0 { - return 1.0 - x - } - return 0 - }, - } - - Hermite = ResampleFilter{ - Support: 1.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 1.0 { - return bcspline(x, 0.0, 0.0) - } - return 0 - }, - } - - MitchellNetravali = ResampleFilter{ - Support: 2.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 2.0 { - return bcspline(x, 1.0/3.0, 1.0/3.0) - } - return 0 - }, - } - - CatmullRom = ResampleFilter{ - Support: 2.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 2.0 { - return bcspline(x, 0.0, 0.5) - } - return 0 - }, - } - - BSpline = ResampleFilter{ - Support: 2.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 2.0 { - return bcspline(x, 1.0, 0.0) - } - return 0 - }, - } - - Gaussian = ResampleFilter{ - Support: 2.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 2.0 { - return math.Exp(-2 * x * x) - } - return 0 - }, - } - - Bartlett = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * (3.0 - x) / 3.0 - } - return 0 - }, - } - - Lanczos = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * sinc(x/3.0) - } - return 0 - }, - } - - Hann = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * (0.5 + 0.5*math.Cos(math.Pi*x/3.0)) - } - return 0 - }, - } - - Hamming = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * (0.54 + 0.46*math.Cos(math.Pi*x/3.0)) - } - return 0 - }, - } - - Blackman = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * (0.42 - 0.5*math.Cos(math.Pi*x/3.0+math.Pi) + 0.08*math.Cos(2.0*math.Pi*x/3.0)) - } - return 0 - }, - } - - Welch = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * (1.0 - (x * x / 9.0)) - } - return 0 - }, - } - - Cosine = ResampleFilter{ - Support: 3.0, - Kernel: func(x float64) float64 { - x = math.Abs(x) - if x < 3.0 { - return sinc(x) * math.Cos((math.Pi/2.0)*(x/3.0)) - } - return 0 - }, - } -} diff --git a/vendor/github.com/disintegration/imaging/scanner.go b/vendor/github.com/disintegration/imaging/scanner.go deleted file mode 100644 index c4dbfe1..0000000 --- a/vendor/github.com/disintegration/imaging/scanner.go +++ /dev/null @@ -1,250 +0,0 @@ -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/tools.go b/vendor/github.com/disintegration/imaging/tools.go deleted file mode 100644 index 7887946..0000000 --- a/vendor/github.com/disintegration/imaging/tools.go +++ /dev/null @@ -1,247 +0,0 @@ -package imaging - -import ( - "bytes" - "image" - "image/color" - "math" -) - -// New creates a new image with the specified width and height, and fills it with the specified color. -func New(width, height int, fillColor color.Color) *image.NRGBA { - if width <= 0 || height <= 0 { - return &image.NRGBA{} - } - - c := color.NRGBAModel.Convert(fillColor).(color.NRGBA) - if (c == color.NRGBA{0, 0, 0, 0}) { - return image.NewNRGBA(image.Rect(0, 0, width, height)) - } - - return &image.NRGBA{ - Pix: bytes.Repeat([]byte{c.R, c.G, c.B, c.A}, width*height), - Stride: 4 * width, - Rect: image.Rect(0, 0, width, height), - } -} - -// 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 -} - -// Anchor is the anchor point for image alignment. -type Anchor int - -// Anchor point positions. -const ( - Center Anchor = iota - TopLeft - Top - TopRight - Left - Right - BottomLeft - Bottom - BottomRight -) - -func anchorPt(b image.Rectangle, w, h int, anchor Anchor) image.Point { - var x, y int - switch anchor { - case TopLeft: - x = b.Min.X - y = b.Min.Y - case Top: - x = b.Min.X + (b.Dx()-w)/2 - y = b.Min.Y - case TopRight: - x = b.Max.X - w - y = b.Min.Y - case Left: - x = b.Min.X - y = b.Min.Y + (b.Dy()-h)/2 - case Right: - x = b.Max.X - w - y = b.Min.Y + (b.Dy()-h)/2 - case BottomLeft: - x = b.Min.X - y = b.Max.Y - h - case Bottom: - x = b.Min.X + (b.Dx()-w)/2 - y = b.Max.Y - h - case BottomRight: - x = b.Max.X - w - y = b.Max.Y - h - default: - x = b.Min.X + (b.Dx()-w)/2 - y = b.Min.Y + (b.Dy()-h)/2 - } - return image.Pt(x, y) -} - -// 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 { - 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 -// from the image using the specified anchor point and returns the cropped image. -func CropAnchor(img image.Image, width, height int, anchor Anchor) *image.NRGBA { - srcBounds := img.Bounds() - pt := anchorPt(srcBounds, width, height, anchor) - r := image.Rect(0, 0, width, height).Add(pt) - b := srcBounds.Intersect(r) - return Crop(img, b) -} - -// CropCenter cuts out a rectangular region with the specified size -// from the center of the image and returns the cropped image. -func CropCenter(img image.Image, width, height int) *image.NRGBA { - return CropAnchor(img, width, height, Center) -} - -// 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 { - 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 -} - -// PasteCenter pastes the img image to the center of the background image and returns the combined image. -func PasteCenter(background, img image.Image) *image.NRGBA { - bgBounds := background.Bounds() - bgW := bgBounds.Dx() - bgH := bgBounds.Dy() - bgMinX := bgBounds.Min.X - bgMinY := bgBounds.Min.Y - - centerX := bgMinX + bgW/2 - centerY := bgMinY + bgH/2 - - x0 := centerX - img.Bounds().Dx()/2 - y0 := centerY - img.Bounds().Dy()/2 - - return Paste(background, img, image.Pt(x0, y0)) -} - -// Overlay draws the img image over the background image at given position -// and returns the combined image. Opacity parameter is the opacity of the img -// image layer, used to compose the images, it must be from 0.0 to 1.0. -// -// Usage examples: -// -// // 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. -// 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) // 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]) - - 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(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 -} - -// OverlayCenter overlays the img image to the center of the background image and -// returns the combined image. Opacity parameter is the opacity of the img -// image layer, used to compose the images, it must be from 0.0 to 1.0. -func OverlayCenter(background, img image.Image, opacity float64) *image.NRGBA { - bgBounds := background.Bounds() - bgW := bgBounds.Dx() - bgH := bgBounds.Dy() - bgMinX := bgBounds.Min.X - bgMinY := bgBounds.Min.Y - - centerX := bgMinX + bgW/2 - centerY := bgMinY + bgH/2 - - x0 := centerX - img.Bounds().Dx()/2 - y0 := centerY - img.Bounds().Dy()/2 - - return Overlay(background, img, image.Point{x0, y0}, opacity) -} diff --git a/vendor/github.com/disintegration/imaging/transform.go b/vendor/github.com/disintegration/imaging/transform.go deleted file mode 100644 index d788d0d..0000000 --- a/vendor/github.com/disintegration/imaging/transform.go +++ /dev/null @@ -1,271 +0,0 @@ -package imaging - -import ( - "image" - "image/color" - "math" -) - -// FlipH flips the image horizontally (from left to right) and returns the transformed image. -func FlipH(img image.Image) *image.NRGBA { - src := newScanner(img) - dstW := src.w - dstH := src.h - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 := newScanner(img) - dstW := src.w - dstH := src.h - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 := newScanner(img) - dstW := src.h - dstH := src.w - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 := newScanner(img) - dstW := src.h - dstH := src.w - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 counter-clockwise and returns the transformed image. -func Rotate90(img image.Image) *image.NRGBA { - src := newScanner(img) - dstW := src.h - dstH := src.w - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 counter-clockwise and returns the transformed image. -func Rotate180(img image.Image) *image.NRGBA { - src := newScanner(img) - dstW := src.w - dstH := src.h - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 counter-clockwise and returns the transformed image. -func Rotate270(img image.Image) *image.NRGBA { - src := newScanner(img) - dstW := src.h - dstH := src.w - rowSize := dstW * 4 - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - 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 -} - -// Rotate rotates an image by the given angle counter-clockwise . -// The angle parameter is the rotation angle in degrees. -// The bgColor parameter specifies the color of the uncovered zone after the rotation. -func Rotate(img image.Image, angle float64, bgColor color.Color) *image.NRGBA { - angle = angle - math.Floor(angle/360)*360 - - switch angle { - case 0: - return Clone(img) - case 90: - return Rotate90(img) - case 180: - return Rotate180(img) - case 270: - return Rotate270(img) - } - - src := toNRGBA(img) - srcW := src.Bounds().Max.X - srcH := src.Bounds().Max.Y - dstW, dstH := rotatedSize(srcW, srcH, angle) - dst := image.NewNRGBA(image.Rect(0, 0, dstW, dstH)) - - if dstW <= 0 || dstH <= 0 { - return dst - } - - srcXOff := float64(srcW)/2 - 0.5 - srcYOff := float64(srcH)/2 - 0.5 - dstXOff := float64(dstW)/2 - 0.5 - dstYOff := float64(dstH)/2 - 0.5 - - bgColorNRGBA := color.NRGBAModel.Convert(bgColor).(color.NRGBA) - sin, cos := math.Sincos(math.Pi * angle / 180) - - 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 - interpolatePoint(dst, dstX, dstY, src, xf, yf, bgColorNRGBA) - } - } - }) - - return dst -} - -func rotatePoint(x, y, sin, cos float64) (float64, float64) { - return x*cos - y*sin, x*sin + y*cos -} - -func rotatedSize(w, h int, angle float64) (int, int) { - if w <= 0 || h <= 0 { - return 0, 0 - } - - sin, cos := math.Sincos(math.Pi * angle / 180) - x1, y1 := rotatePoint(float64(w-1), 0, sin, cos) - x2, y2 := rotatePoint(float64(w-1), float64(h-1), sin, cos) - x3, y3 := rotatePoint(0, float64(h-1), sin, cos) - - minx := math.Min(x1, math.Min(x2, math.Min(x3, 0))) - maxx := math.Max(x1, math.Max(x2, math.Max(x3, 0))) - miny := math.Min(y1, math.Min(y2, math.Min(y3, 0))) - maxy := math.Max(y1, math.Max(y2, math.Max(y3, 0))) - - neww := maxx - minx + 1 - if neww-math.Floor(neww) > 0.1 { - neww++ - } - newh := maxy - miny + 1 - if newh-math.Floor(newh) > 0.1 { - newh++ - } - - return int(neww), int(newh) -} - -func interpolatePoint(dst *image.NRGBA, dstX, dstY int, src *image.NRGBA, xf, yf float64, bgColor color.NRGBA) { - dstIndex := dstY*dst.Stride + dstX*4 - - x0 := int(math.Floor(xf)) - y0 := int(math.Floor(yf)) - bounds := src.Bounds() - if !image.Pt(x0, y0).In(image.Rect(bounds.Min.X-1, bounds.Min.Y-1, bounds.Max.X, bounds.Max.Y)) { - dst.Pix[dstIndex+0] = bgColor.R - dst.Pix[dstIndex+1] = bgColor.G - dst.Pix[dstIndex+2] = bgColor.B - dst.Pix[dstIndex+3] = bgColor.A - return - } - - xq := xf - float64(x0) - yq := yf - float64(y0) - - var pxs [4]color.NRGBA - var cfs [4]float64 - - for i := 0; i < 2; i++ { - for j := 0; j < 2; j++ { - k := i*2 + j - pt := image.Pt(x0+j, y0+i) - if pt.In(bounds) { - l := pt.Y*src.Stride + pt.X*4 - pxs[k].R = src.Pix[l+0] - pxs[k].G = src.Pix[l+1] - pxs[k].B = src.Pix[l+2] - pxs[k].A = src.Pix[l+3] - } else { - pxs[k] = bgColor - } - } - } - - cfs[0] = (1 - xq) * (1 - yq) - cfs[1] = xq * (1 - yq) - cfs[2] = (1 - xq) * yq - cfs[3] = xq * yq - - var r, g, b, a float64 - for i := range pxs { - wa := float64(pxs[i].A) * cfs[i] - r += float64(pxs[i].R) * wa - g += float64(pxs[i].G) * wa - b += float64(pxs[i].B) * wa - a += wa - } - - if a != 0 { - r /= a - g /= a - b /= a - } - - dst.Pix[dstIndex+0] = clamp(r) - dst.Pix[dstIndex+1] = clamp(g) - dst.Pix[dstIndex+2] = clamp(b) - dst.Pix[dstIndex+3] = clamp(a) -} diff --git a/vendor/github.com/disintegration/imaging/utils.go b/vendor/github.com/disintegration/imaging/utils.go deleted file mode 100644 index 3b6ad2e..0000000 --- a/vendor/github.com/disintegration/imaging/utils.go +++ /dev/null @@ -1,83 +0,0 @@ -package imaging - -import ( - "image" - "runtime" - "sync" -) - -// parallel processes the data in separate goroutines. -func parallel(start, stop int, fn func(<-chan int)) { - count := stop - start - if count < 1 { - return - } - - procs := runtime.GOMAXPROCS(0) - if procs > count { - procs = count - } - - c := make(chan int, count) - for i := start; i < stop; i++ { - c <- i - } - close(c) - - 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. -func absint(i int) int { - if i < 0 { - return -i - } - return i -} - -// clamp rounds and clamps float64 value to fit into uint8. -func clamp(x float64) uint8 { - v := int64(x + 0.5) - if v > 255 { - return 255 - } - if v > 0 { - return uint8(v) - } - 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) -} |