From f43d35507827216071896cae83544fef1c4c35eb Mon Sep 17 00:00:00 2001 From: Jack Date: Wed, 23 Sep 2015 19:54:07 -0700 Subject: godep save --- .../p/graphics-go/graphics/Makefile | 15 - .../p/graphics-go/graphics/affine.go | 174 ------ .../code.google.com/p/graphics-go/graphics/blur.go | 68 --- .../p/graphics-go/graphics/blur_test.go | 207 ------- .../p/graphics-go/graphics/convolve/Makefile | 11 - .../p/graphics-go/graphics/convolve/convolve.go | 274 --------- .../graphics-go/graphics/convolve/convolve_test.go | 78 --- .../p/graphics-go/graphics/detect/Makefile | 15 - .../p/graphics-go/graphics/detect/detect.go | 133 ----- .../p/graphics-go/graphics/detect/detect_test.go | 77 --- .../p/graphics-go/graphics/detect/doc.go | 31 -- .../p/graphics-go/graphics/detect/integral.go | 93 ---- .../p/graphics-go/graphics/detect/integral_test.go | 156 ------ .../p/graphics-go/graphics/detect/opencv_parser.go | 125 ----- .../graphics/detect/opencv_parser_test.go | 75 --- .../p/graphics-go/graphics/detect/projector.go | 55 -- .../graphics-go/graphics/detect/projector_test.go | 49 -- .../p/graphics-go/graphics/graphicstest/Makefile | 11 - .../graphics/graphicstest/graphicstest.go | 112 ---- .../p/graphics-go/graphics/interp/Makefile | 13 - .../p/graphics-go/graphics/interp/bilinear.go | 206 ------- .../p/graphics-go/graphics/interp/bilinear_test.go | 143 ----- .../p/graphics-go/graphics/interp/doc.go | 25 - .../p/graphics-go/graphics/interp/interp.go | 29 - .../p/graphics-go/graphics/rotate.go | 35 -- .../p/graphics-go/graphics/rotate_test.go | 169 ------ .../p/graphics-go/graphics/scale.go | 31 -- .../p/graphics-go/graphics/scale_test.go | 153 ----- .../p/graphics-go/graphics/shared_test.go | 69 --- .../p/graphics-go/graphics/thumbnail.go | 41 -- .../p/graphics-go/graphics/thumbnail_test.go | 53 -- .../src/github.com/nfnt/resize/.travis.yml | 7 - .../_workspace/src/github.com/nfnt/resize/LICENSE | 13 - .../src/github.com/nfnt/resize/README.md | 149 ----- .../src/github.com/nfnt/resize/converter.go | 452 --------------- .../src/github.com/nfnt/resize/converter_test.go | 43 -- .../src/github.com/nfnt/resize/filters.go | 143 ----- .../src/github.com/nfnt/resize/nearest.go | 318 ----------- .../src/github.com/nfnt/resize/nearest_test.go | 57 -- .../src/github.com/nfnt/resize/resize.go | 614 --------------------- .../src/github.com/nfnt/resize/resize_test.go | 314 ----------- .../src/github.com/nfnt/resize/thumbnail.go | 55 -- .../src/github.com/nfnt/resize/thumbnail_test.go | 47 -- .../_workspace/src/github.com/nfnt/resize/ycc.go | 227 -------- .../src/github.com/nfnt/resize/ycc_test.go | 214 ------- 45 files changed, 5379 deletions(-) delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/Makefile delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/Makefile delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/Makefile delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/doc.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/Makefile delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/graphicstest.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/Makefile delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/doc.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/interp.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/shared_test.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail.go delete mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail_test.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/.travis.yml delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/LICENSE delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/README.md delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/converter.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/converter_test.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/filters.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/nearest.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/nearest_test.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/resize.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/resize_test.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/thumbnail.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/thumbnail_test.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/ycc.go delete mode 100644 Godeps/_workspace/src/github.com/nfnt/resize/ycc_test.go (limited to 'Godeps/_workspace/src') diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/Makefile b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/Makefile deleted file mode 100644 index 28a06f0e8..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2011 The Graphics-Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=code.google.com/p/graphics-go/graphics -GOFILES=\ - affine.go\ - blur.go\ - rotate.go\ - scale.go\ - thumbnail.go\ - -include $(GOROOT)/src/Make.pkg diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go deleted file mode 100644 index 0ac2ec9da..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/interp" - "errors" - "image" - "image/draw" - "math" -) - -// I is the identity Affine transform matrix. -var I = Affine{ - 1, 0, 0, - 0, 1, 0, - 0, 0, 1, -} - -// Affine is a 3x3 2D affine transform matrix. -// M(i,j) is Affine[i*3+j]. -type Affine [9]float64 - -// Mul returns the multiplication of two affine transform matrices. -func (a Affine) Mul(b Affine) Affine { - return Affine{ - a[0]*b[0] + a[1]*b[3] + a[2]*b[6], - a[0]*b[1] + a[1]*b[4] + a[2]*b[7], - a[0]*b[2] + a[1]*b[5] + a[2]*b[8], - a[3]*b[0] + a[4]*b[3] + a[5]*b[6], - a[3]*b[1] + a[4]*b[4] + a[5]*b[7], - a[3]*b[2] + a[4]*b[5] + a[5]*b[8], - a[6]*b[0] + a[7]*b[3] + a[8]*b[6], - a[6]*b[1] + a[7]*b[4] + a[8]*b[7], - a[6]*b[2] + a[7]*b[5] + a[8]*b[8], - } -} - -func (a Affine) transformRGBA(dst *image.RGBA, src *image.RGBA, i interp.RGBA) error { - srcb := src.Bounds() - b := dst.Bounds() - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - sx, sy := a.pt(x, y) - if inBounds(srcb, sx, sy) { - c := i.RGBA(src, sx, sy) - off := (y-dst.Rect.Min.Y)*dst.Stride + (x-dst.Rect.Min.X)*4 - dst.Pix[off+0] = c.R - dst.Pix[off+1] = c.G - dst.Pix[off+2] = c.B - dst.Pix[off+3] = c.A - } - } - } - return nil -} - -// Transform applies the affine transform to src and produces dst. -func (a Affine) Transform(dst draw.Image, src image.Image, i interp.Interp) error { - if dst == nil { - return errors.New("graphics: dst is nil") - } - if src == nil { - return errors.New("graphics: src is nil") - } - - // RGBA fast path. - dstRGBA, dstOk := dst.(*image.RGBA) - srcRGBA, srcOk := src.(*image.RGBA) - interpRGBA, interpOk := i.(interp.RGBA) - if dstOk && srcOk && interpOk { - return a.transformRGBA(dstRGBA, srcRGBA, interpRGBA) - } - - srcb := src.Bounds() - b := dst.Bounds() - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - sx, sy := a.pt(x, y) - if inBounds(srcb, sx, sy) { - dst.Set(x, y, i.Interp(src, sx, sy)) - } - } - } - return nil -} - -func inBounds(b image.Rectangle, x, y float64) bool { - if x < float64(b.Min.X) || x >= float64(b.Max.X) { - return false - } - if y < float64(b.Min.Y) || y >= float64(b.Max.Y) { - return false - } - return true -} - -func (a Affine) pt(x0, y0 int) (x1, y1 float64) { - fx := float64(x0) + 0.5 - fy := float64(y0) + 0.5 - x1 = fx*a[0] + fy*a[1] + a[2] - y1 = fx*a[3] + fy*a[4] + a[5] - return x1, y1 -} - -// TransformCenter applies the affine transform to src and produces dst. -// Equivalent to -// a.CenterFit(dst, src).Transform(dst, src, i). -func (a Affine) TransformCenter(dst draw.Image, src image.Image, i interp.Interp) error { - if dst == nil { - return errors.New("graphics: dst is nil") - } - if src == nil { - return errors.New("graphics: src is nil") - } - - return a.CenterFit(dst.Bounds(), src.Bounds()).Transform(dst, src, i) -} - -// Scale produces a scaling transform of factors x and y. -func (a Affine) Scale(x, y float64) Affine { - return a.Mul(Affine{ - 1 / x, 0, 0, - 0, 1 / y, 0, - 0, 0, 1, - }) -} - -// Rotate produces a clockwise rotation transform of angle, in radians. -func (a Affine) Rotate(angle float64) Affine { - s, c := math.Sincos(angle) - return a.Mul(Affine{ - +c, +s, +0, - -s, +c, +0, - +0, +0, +1, - }) -} - -// Shear produces a shear transform by the slopes x and y. -func (a Affine) Shear(x, y float64) Affine { - d := 1 - x*y - return a.Mul(Affine{ - +1 / d, -x / d, 0, - -y / d, +1 / d, 0, - 0, 0, 1, - }) -} - -// Translate produces a translation transform with pixel distances x and y. -func (a Affine) Translate(x, y float64) Affine { - return a.Mul(Affine{ - 1, 0, -x, - 0, 1, -y, - 0, 0, +1, - }) -} - -// Center produces the affine transform, centered around the provided point. -func (a Affine) Center(x, y float64) Affine { - return I.Translate(-x, -y).Mul(a).Translate(x, y) -} - -// CenterFit produces the affine transform, centered around the rectangles. -// It is equivalent to -// I.Translate(-
).Mul(a).Translate(
) -func (a Affine) CenterFit(dst, src image.Rectangle) Affine { - dx := float64(dst.Min.X) + float64(dst.Dx())/2 - dy := float64(dst.Min.Y) + float64(dst.Dy())/2 - sx := float64(src.Min.X) + float64(src.Dx())/2 - sy := float64(src.Min.Y) + float64(src.Dy())/2 - return I.Translate(-sx, -sy).Mul(a).Translate(dx, dy) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur.go deleted file mode 100644 index 9a54d5ad5..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/convolve" - "errors" - "image" - "image/draw" - "math" -) - -// DefaultStdDev is the default blurring parameter. -var DefaultStdDev = 0.5 - -// BlurOptions are the blurring parameters. -// StdDev is the standard deviation of the normal, higher is blurrier. -// Size is the size of the kernel. If zero, it is set to Ceil(6 * StdDev). -type BlurOptions struct { - StdDev float64 - Size int -} - -// Blur produces a blurred version of the image, using a Gaussian blur. -func Blur(dst draw.Image, src image.Image, opt *BlurOptions) error { - if dst == nil { - return errors.New("graphics: dst is nil") - } - if src == nil { - return errors.New("graphics: src is nil") - } - - sd := DefaultStdDev - size := 0 - - if opt != nil { - sd = opt.StdDev - size = opt.Size - } - - if size < 1 { - size = int(math.Ceil(sd * 6)) - } - - kernel := make([]float64, 2*size+1) - for i := 0; i <= size; i++ { - x := float64(i) / sd - x = math.Pow(1/math.SqrtE, x*x) - kernel[size-i] = x - kernel[size+i] = x - } - - // Normalize the weights to sum to 1.0. - kSum := 0.0 - for _, k := range kernel { - kSum += k - } - for i, k := range kernel { - kernel[i] = k / kSum - } - - return convolve.Convolve(dst, src, &convolve.SeparableKernel{ - X: kernel, - Y: kernel, - }) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur_test.go deleted file mode 100644 index 1d84fa604..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/blur_test.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/graphicstest" - "image" - "image/color" - "testing" - - _ "image/png" -) - -var blurOneColorTests = []transformOneColorTest{ - { - "1x1-blank", 1, 1, 1, 1, - &BlurOptions{0.83, 1}, - []uint8{0xff}, - []uint8{0xff}, - }, - { - "1x1-spreadblank", 1, 1, 1, 1, - &BlurOptions{0.83, 2}, - []uint8{0xff}, - []uint8{0xff}, - }, - { - "3x3-blank", 3, 3, 3, 3, - &BlurOptions{0.83, 2}, - []uint8{ - 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, - }, - []uint8{ - 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, - }, - }, - { - "3x3-dot", 3, 3, 3, 3, - &BlurOptions{0.34, 1}, - []uint8{ - 0x00, 0x00, 0x00, - 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0x03, 0x00, - 0x03, 0xf2, 0x03, - 0x00, 0x03, 0x00, - }, - }, - { - "5x5-dot", 5, 5, 5, 5, - &BlurOptions{0.34, 1}, - []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x03, 0xf2, 0x03, 0x00, - 0x00, 0x00, 0x03, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - { - "5x5-dot-spread", 5, 5, 5, 5, - &BlurOptions{0.85, 1}, - []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x20, 0x10, 0x00, - 0x00, 0x20, 0x40, 0x20, 0x00, - 0x00, 0x10, 0x20, 0x10, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, - { - "4x4-box", 4, 4, 4, 4, - &BlurOptions{0.34, 1}, - []uint8{ - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0x03, 0x03, 0x00, - 0x03, 0xf8, 0xf8, 0x03, - 0x03, 0xf8, 0xf8, 0x03, - 0x00, 0x03, 0x03, 0x00, - }, - }, - { - "5x5-twodots", 5, 5, 5, 5, - &BlurOptions{0.34, 1}, - []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x96, 0x00, 0x96, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x02, 0x00, - 0x02, 0x8e, 0x04, 0x8e, 0x02, - 0x00, 0x02, 0x00, 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - }, - }, -} - -func TestBlurOneColor(t *testing.T) { - for _, oc := range blurOneColorTests { - dst := oc.newDst() - src := oc.newSrc() - opt := oc.opt.(*BlurOptions) - if err := Blur(dst, src, opt); err != nil { - t.Fatal(err) - } - - if !checkTransformTest(t, &oc, dst) { - continue - } - } -} - -func TestBlurEmpty(t *testing.T) { - empty := image.NewRGBA(image.Rect(0, 0, 0, 0)) - if err := Blur(empty, empty, nil); err != nil { - t.Fatal(err) - } -} - -func TestBlurGopher(t *testing.T) { - src, err := graphicstest.LoadImage("../testdata/gopher.png") - if err != nil { - t.Fatal(err) - } - - dst := image.NewRGBA(src.Bounds()) - if err = Blur(dst, src, &BlurOptions{StdDev: 1.1}); err != nil { - t.Fatal(err) - } - - cmp, err := graphicstest.LoadImage("../testdata/gopher-blur.png") - if err != nil { - t.Fatal(err) - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0x101) - if err != nil { - t.Fatal(err) - } -} - -func benchBlur(b *testing.B, bounds image.Rectangle) { - b.StopTimer() - - // Construct a fuzzy image. - src := image.NewRGBA(bounds) - for y := bounds.Min.Y; y < bounds.Max.Y; y++ { - for x := bounds.Min.X; x < bounds.Max.X; x++ { - src.SetRGBA(x, y, color.RGBA{ - uint8(5 * x % 0x100), - uint8(7 * y % 0x100), - uint8((7*x + 5*y) % 0x100), - 0xff, - }) - } - } - dst := image.NewRGBA(bounds) - - b.StartTimer() - for i := 0; i < b.N; i++ { - Blur(dst, src, &BlurOptions{0.84, 3}) - } -} - -func BenchmarkBlur400x400x3(b *testing.B) { - benchBlur(b, image.Rect(0, 0, 400, 400)) -} - -// Exactly twice the pixel count of 400x400. -func BenchmarkBlur400x800x3(b *testing.B) { - benchBlur(b, image.Rect(0, 0, 400, 800)) -} - -// Exactly twice the pixel count of 400x800 -func BenchmarkBlur400x1600x3(b *testing.B) { - benchBlur(b, image.Rect(0, 0, 400, 1600)) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/Makefile b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/Makefile deleted file mode 100644 index a5691fa30..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2011 The Graphics-Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=code.google.com/p/graphics-go/graphics/convolve -GOFILES=\ - convolve.go\ - -include $(GOROOT)/src/Make.pkg diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve.go deleted file mode 100644 index da69496d0..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve.go +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package convolve - -import ( - "errors" - "fmt" - "image" - "image/draw" - "math" -) - -// clamp clamps x to the range [x0, x1]. -func clamp(x, x0, x1 float64) float64 { - if x < x0 { - return x0 - } - if x > x1 { - return x1 - } - return x -} - -// Kernel is a square matrix that defines a convolution. -type Kernel interface { - // Weights returns the square matrix of weights in row major order. - Weights() []float64 -} - -// SeparableKernel is a linearly separable, square convolution kernel. -// X and Y are the per-axis weights. Each slice must be the same length, and -// have an odd length. The middle element of each slice is the weight for the -// central pixel. For example, the horizontal Sobel kernel is: -// sobelX := &SeparableKernel{ -// X: []float64{-1, 0, +1}, -// Y: []float64{1, 2, 1}, -// } -type SeparableKernel struct { - X, Y []float64 -} - -func (k *SeparableKernel) Weights() []float64 { - n := len(k.X) - w := make([]float64, n*n) - for y := 0; y < n; y++ { - for x := 0; x < n; x++ { - w[y*n+x] = k.X[x] * k.Y[y] - } - } - return w -} - -// fullKernel is a square convolution kernel. -type fullKernel []float64 - -func (k fullKernel) Weights() []float64 { return k } - -func kernelSize(w []float64) (size int, err error) { - size = int(math.Sqrt(float64(len(w)))) - if size*size != len(w) { - return 0, errors.New("graphics: kernel is not square") - } - if size%2 != 1 { - return 0, errors.New("graphics: kernel size is not odd") - } - return size, nil -} - -// NewKernel returns a square convolution kernel. -func NewKernel(w []float64) (Kernel, error) { - if _, err := kernelSize(w); err != nil { - return nil, err - } - return fullKernel(w), nil -} - -func convolveRGBASep(dst *image.RGBA, src image.Image, k *SeparableKernel) error { - if len(k.X) != len(k.Y) { - return fmt.Errorf("graphics: kernel not square (x %d, y %d)", len(k.X), len(k.Y)) - } - if len(k.X)%2 != 1 { - return fmt.Errorf("graphics: kernel length (%d) not odd", len(k.X)) - } - radius := (len(k.X) - 1) / 2 - - // buf holds the result of vertically blurring src. - bounds := dst.Bounds() - width, height := bounds.Dx(), bounds.Dy() - buf := make([]float64, width*height*4) - for y := bounds.Min.Y; y < bounds.Max.Y; y++ { - for x := bounds.Min.X; x < bounds.Max.X; x++ { - var r, g, b, a float64 - // k0 is the kernel weight for the center pixel. This may be greater - // than kernel[0], near the boundary of the source image, to avoid - // vignetting. - k0 := k.X[radius] - - // Add the pixels from above. - for i := 1; i <= radius; i++ { - f := k.Y[radius-i] - if y-i < bounds.Min.Y { - k0 += f - } else { - or, og, ob, oa := src.At(x, y-i).RGBA() - r += float64(or>>8) * f - g += float64(og>>8) * f - b += float64(ob>>8) * f - a += float64(oa>>8) * f - } - } - - // Add the pixels from below. - for i := 1; i <= radius; i++ { - f := k.Y[radius+i] - if y+i >= bounds.Max.Y { - k0 += f - } else { - or, og, ob, oa := src.At(x, y+i).RGBA() - r += float64(or>>8) * f - g += float64(og>>8) * f - b += float64(ob>>8) * f - a += float64(oa>>8) * f - } - } - - // Add the central pixel. - or, og, ob, oa := src.At(x, y).RGBA() - r += float64(or>>8) * k0 - g += float64(og>>8) * k0 - b += float64(ob>>8) * k0 - a += float64(oa>>8) * k0 - - // Write to buf. - o := (y-bounds.Min.Y)*width*4 + (x-bounds.Min.X)*4 - buf[o+0] = r - buf[o+1] = g - buf[o+2] = b - buf[o+3] = a - } - } - - // dst holds the result of horizontally blurring buf. - for y := 0; y < height; y++ { - for x := 0; x < width; x++ { - var r, g, b, a float64 - k0, off := k.X[radius], y*width*4+x*4 - - // Add the pixels from the left. - for i := 1; i <= radius; i++ { - f := k.X[radius-i] - if x-i < 0 { - k0 += f - } else { - o := off - i*4 - r += buf[o+0] * f - g += buf[o+1] * f - b += buf[o+2] * f - a += buf[o+3] * f - } - } - - // Add the pixels from the right. - for i := 1; i <= radius; i++ { - f := k.X[radius+i] - if x+i >= width { - k0 += f - } else { - o := off + i*4 - r += buf[o+0] * f - g += buf[o+1] * f - b += buf[o+2] * f - a += buf[o+3] * f - } - } - - // Add the central pixel. - r += buf[off+0] * k0 - g += buf[off+1] * k0 - b += buf[off+2] * k0 - a += buf[off+3] * k0 - - // Write to dst, clamping to the range [0, 255]. - dstOff := (y-dst.Rect.Min.Y)*dst.Stride + (x-dst.Rect.Min.X)*4 - dst.Pix[dstOff+0] = uint8(clamp(r+0.5, 0, 255)) - dst.Pix[dstOff+1] = uint8(clamp(g+0.5, 0, 255)) - dst.Pix[dstOff+2] = uint8(clamp(b+0.5, 0, 255)) - dst.Pix[dstOff+3] = uint8(clamp(a+0.5, 0, 255)) - } - } - - return nil -} - -func convolveRGBA(dst *image.RGBA, src image.Image, k Kernel) error { - b := dst.Bounds() - bs := src.Bounds() - w := k.Weights() - size, err := kernelSize(w) - if err != nil { - return err - } - radius := (size - 1) / 2 - - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - if !image.Pt(x, y).In(bs) { - continue - } - - var r, g, b, a, adj float64 - for cy := y - radius; cy <= y+radius; cy++ { - for cx := x - radius; cx <= x+radius; cx++ { - factor := w[(cy-y+radius)*size+cx-x+radius] - if !image.Pt(cx, cy).In(bs) { - adj += factor - } else { - sr, sg, sb, sa := src.At(cx, cy).RGBA() - r += float64(sr>>8) * factor - g += float64(sg>>8) * factor - b += float64(sb>>8) * factor - a += float64(sa>>8) * factor - } - } - } - - if adj != 0 { - sr, sg, sb, sa := src.At(x, y).RGBA() - r += float64(sr>>8) * adj - g += float64(sg>>8) * adj - b += float64(sb>>8) * adj - a += float64(sa>>8) * adj - } - - off := (y-dst.Rect.Min.Y)*dst.Stride + (x-dst.Rect.Min.X)*4 - dst.Pix[off+0] = uint8(clamp(r+0.5, 0, 0xff)) - dst.Pix[off+1] = uint8(clamp(g+0.5, 0, 0xff)) - dst.Pix[off+2] = uint8(clamp(b+0.5, 0, 0xff)) - dst.Pix[off+3] = uint8(clamp(a+0.5, 0, 0xff)) - } - } - - return nil -} - -// Convolve produces dst by applying the convolution kernel k to src. -func Convolve(dst draw.Image, src image.Image, k Kernel) (err error) { - if dst == nil || src == nil || k == nil { - return nil - } - - b := dst.Bounds() - dstRgba, ok := dst.(*image.RGBA) - if !ok { - dstRgba = image.NewRGBA(b) - } - - switch k := k.(type) { - case *SeparableKernel: - err = convolveRGBASep(dstRgba, src, k) - default: - err = convolveRGBA(dstRgba, src, k) - } - - if err != nil { - return err - } - - if !ok { - draw.Draw(dst, b, dstRgba, b.Min, draw.Src) - } - return nil -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve_test.go deleted file mode 100644 index f34d7afc8..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/convolve/convolve_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package convolve - -import ( - "code.google.com/p/graphics-go/graphics/graphicstest" - "image" - "reflect" - "testing" - - _ "image/png" -) - -func TestSeparableWeights(t *testing.T) { - sobelXFull := []float64{ - -1, 0, 1, - -2, 0, 2, - -1, 0, 1, - } - sobelXSep := &SeparableKernel{ - X: []float64{-1, 0, +1}, - Y: []float64{1, 2, 1}, - } - w := sobelXSep.Weights() - if !reflect.DeepEqual(w, sobelXFull) { - t.Errorf("got %v want %v", w, sobelXFull) - } -} - -func TestConvolve(t *testing.T) { - kernFull, err := NewKernel([]float64{ - 0, 0, 0, - 1, 1, 1, - 0, 0, 0, - }) - if err != nil { - t.Fatal(err) - } - - kernSep := &SeparableKernel{ - X: []float64{1, 1, 1}, - Y: []float64{0, 1, 0}, - } - - src, err := graphicstest.LoadImage("../../testdata/gopher.png") - if err != nil { - t.Fatal(err) - } - b := src.Bounds() - - sep := image.NewRGBA(b) - if err = Convolve(sep, src, kernSep); err != nil { - t.Fatal(err) - } - - full := image.NewRGBA(b) - Convolve(full, src, kernFull) - - err = graphicstest.ImageWithinTolerance(sep, full, 0x101) - if err != nil { - t.Fatal(err) - } -} - -func TestConvolveNil(t *testing.T) { - if err := Convolve(nil, nil, nil); err != nil { - t.Fatal(err) - } -} - -func TestConvolveEmpty(t *testing.T) { - empty := image.NewRGBA(image.Rect(0, 0, 0, 0)) - if err := Convolve(empty, empty, nil); err != nil { - t.Fatal(err) - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/Makefile b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/Makefile deleted file mode 100644 index 0b1c6cb3e..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright 2011 The Graphics-Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=code.google.com/p/graphics-go/graphics -GOFILES=\ - detect.go\ - doc.go\ - integral.go\ - opencv_parser.go\ - projector.go\ - -include $(GOROOT)/src/Make.pkg diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect.go deleted file mode 100644 index dde941cbe..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect.go +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "image" - "math" -) - -// Feature is a Haar-like feature. -type Feature struct { - Rect image.Rectangle - Weight float64 -} - -// Classifier is a set of features with a threshold. -type Classifier struct { - Feature []Feature - Threshold float64 - Left float64 - Right float64 -} - -// CascadeStage is a cascade of classifiers. -type CascadeStage struct { - Classifier []Classifier - Threshold float64 -} - -// Cascade is a degenerate tree of Haar-like classifiers. -type Cascade struct { - Stage []CascadeStage - Size image.Point -} - -// Match returns true if the full image is classified as an object. -func (c *Cascade) Match(m image.Image) bool { - return c.classify(newWindow(m)) -} - -// Find returns a set of areas of m that match the feature cascade c. -func (c *Cascade) Find(m image.Image) []image.Rectangle { - // TODO(crawshaw): Consider de-duping strategies. - matches := []image.Rectangle{} - w := newWindow(m) - - b := m.Bounds() - origScale := c.Size - for s := origScale; s.X < b.Dx() && s.Y < b.Dy(); s = s.Add(s.Div(10)) { - // translate region and classify - tx := image.Pt(s.X/10, 0) - ty := image.Pt(0, s.Y/10) - for r := image.Rect(0, 0, s.X, s.Y).Add(b.Min); r.In(b); r = r.Add(ty) { - for r1 := r; r1.In(b); r1 = r1.Add(tx) { - if c.classify(w.subWindow(r1)) { - matches = append(matches, r1) - } - } - } - } - return matches -} - -type window struct { - mi *integral - miSq *integral - rect image.Rectangle - invArea float64 - stdDev float64 -} - -func (w *window) init() { - w.invArea = 1 / float64(w.rect.Dx()*w.rect.Dy()) - mean := float64(w.mi.sum(w.rect)) * w.invArea - vr := float64(w.miSq.sum(w.rect))*w.invArea - mean*mean - if vr < 0 { - vr = 1 - } - w.stdDev = math.Sqrt(vr) -} - -func newWindow(m image.Image) *window { - mi, miSq := newIntegrals(m) - res := &window{ - mi: mi, - miSq: miSq, - rect: m.Bounds(), - } - res.init() - return res -} - -func (w *window) subWindow(r image.Rectangle) *window { - res := &window{ - mi: w.mi, - miSq: w.miSq, - rect: r, - } - res.init() - return res -} - -func (c *Classifier) classify(w *window, pr *projector) float64 { - s := 0.0 - for _, f := range c.Feature { - s += float64(w.mi.sum(pr.rect(f.Rect))) * f.Weight - } - s *= w.invArea // normalize to maintain scale invariance - if s < c.Threshold*w.stdDev { - return c.Left - } - return c.Right -} - -func (s *CascadeStage) classify(w *window, pr *projector) bool { - sum := 0.0 - for _, c := range s.Classifier { - sum += c.classify(w, pr) - } - return sum >= s.Threshold -} - -func (c *Cascade) classify(w *window) bool { - pr := newProjector(w.rect, image.Rectangle{image.Pt(0, 0), c.Size}) - for _, s := range c.Stage { - if !s.classify(w, pr) { - return false - } - } - return true -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect_test.go deleted file mode 100644 index 8a2df113d..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/detect_test.go +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "image" - "image/draw" - "testing" -) - -var ( - c0 = Classifier{ - Feature: []Feature{ - Feature{Rect: image.Rect(0, 0, 3, 4), Weight: 4.0}, - }, - Threshold: 0.2, - Left: 0.8, - Right: 0.2, - } - c1 = Classifier{ - Feature: []Feature{ - Feature{Rect: image.Rect(3, 4, 4, 5), Weight: 4.0}, - }, - Threshold: 0.2, - Left: 0.8, - Right: 0.2, - } - c2 = Classifier{ - Feature: []Feature{ - Feature{Rect: image.Rect(0, 0, 1, 1), Weight: +4.0}, - Feature{Rect: image.Rect(0, 0, 2, 2), Weight: -1.0}, - }, - Threshold: 0.2, - Left: 0.8, - Right: 0.2, - } -) - -func TestClassifier(t *testing.T) { - m := image.NewGray(image.Rect(0, 0, 20, 20)) - b := m.Bounds() - draw.Draw(m, image.Rect(0, 0, 20, 20), image.White, image.ZP, draw.Src) - draw.Draw(m, image.Rect(3, 4, 4, 5), image.Black, image.ZP, draw.Src) - w := newWindow(m) - pr := newProjector(b, b) - - if res := c0.classify(w, pr); res != c0.Right { - t.Errorf("c0 got %f want %f", res, c0.Right) - } - if res := c1.classify(w, pr); res != c1.Left { - t.Errorf("c1 got %f want %f", res, c1.Left) - } - if res := c2.classify(w, pr); res != c1.Left { - t.Errorf("c2 got %f want %f", res, c1.Left) - } -} - -func TestClassifierScale(t *testing.T) { - m := image.NewGray(image.Rect(0, 0, 50, 50)) - b := m.Bounds() - draw.Draw(m, image.Rect(0, 0, 8, 10), image.White, b.Min, draw.Src) - draw.Draw(m, image.Rect(8, 10, 10, 13), image.Black, b.Min, draw.Src) - w := newWindow(m) - pr := newProjector(b, image.Rect(0, 0, 20, 20)) - - if res := c0.classify(w, pr); res != c0.Right { - t.Errorf("scaled c0 got %f want %f", res, c0.Right) - } - if res := c1.classify(w, pr); res != c1.Left { - t.Errorf("scaled c1 got %f want %f", res, c1.Left) - } - if res := c2.classify(w, pr); res != c1.Left { - t.Errorf("scaled c2 got %f want %f", res, c1.Left) - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/doc.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/doc.go deleted file mode 100644 index a0f4e94cd..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/doc.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package detect implements an object detector cascade. - -The technique used is a degenerate tree of Haar-like classifiers, commonly -used for face detection. It is described in - - P. Viola, M. Jones. - Rapid Object Detection using a Boosted Cascade of Simple Features, 2001 - IEEE Conference on Computer Vision and Pattern Recognition - -A Cascade can be constructed manually from a set of Classifiers in stages, -or can be loaded from an XML file in the OpenCV format with - - classifier, _, err := detect.ParseOpenCV(r) - -The classifier can be used to determine if a full image is detected as an -object using Detect - - if classifier.Match(m) { - // m is an image of a face. - } - -It is also possible to search an image for occurrences of an object - - objs := classifier.Find(m) -*/ -package detect diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral.go deleted file mode 100644 index 814ced590..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "image" - "image/draw" -) - -// integral is an image.Image-like structure that stores the cumulative -// sum of the preceding pixels. This allows for O(1) summation of any -// rectangular region within the image. -type integral struct { - // pix holds the cumulative sum of the image's pixels. The pixel at - // (x, y) starts at pix[(y-rect.Min.Y)*stride + (x-rect.Min.X)*1]. - pix []uint64 - stride int - rect image.Rectangle -} - -func (p *integral) at(x, y int) uint64 { - return p.pix[(y-p.rect.Min.Y)*p.stride+(x-p.rect.Min.X)] -} - -func (p *integral) sum(b image.Rectangle) uint64 { - c := p.at(b.Max.X-1, b.Max.Y-1) - inY := b.Min.Y > p.rect.Min.Y - inX := b.Min.X > p.rect.Min.X - if inY && inX { - c += p.at(b.Min.X-1, b.Min.Y-1) - } - if inY { - c -= p.at(b.Max.X-1, b.Min.Y-1) - } - if inX { - c -= p.at(b.Min.X-1, b.Max.Y-1) - } - return c -} - -func (m *integral) integrate() { - b := m.rect - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - c := uint64(0) - if y > b.Min.Y && x > b.Min.X { - c += m.at(x-1, y) - c += m.at(x, y-1) - c -= m.at(x-1, y-1) - } else if y > b.Min.Y { - c += m.at(b.Min.X, y-1) - } else if x > b.Min.X { - c += m.at(x-1, b.Min.Y) - } - m.pix[(y-m.rect.Min.Y)*m.stride+(x-m.rect.Min.X)] += c - } - } -} - -// newIntegrals returns the integral and the squared integral. -func newIntegrals(src image.Image) (*integral, *integral) { - b := src.Bounds() - srcg, ok := src.(*image.Gray) - if !ok { - srcg = image.NewGray(b) - draw.Draw(srcg, b, src, b.Min, draw.Src) - } - - m := integral{ - pix: make([]uint64, b.Max.Y*b.Max.X), - stride: b.Max.X, - rect: b, - } - mSq := integral{ - pix: make([]uint64, b.Max.Y*b.Max.X), - stride: b.Max.X, - rect: b, - } - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - os := (y-b.Min.Y)*srcg.Stride + x - b.Min.X - om := (y-b.Min.Y)*m.stride + x - b.Min.X - c := uint64(srcg.Pix[os]) - m.pix[om] = c - mSq.pix[om] = c * c - } - } - m.integrate() - mSq.integrate() - return &m, &mSq -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral_test.go deleted file mode 100644 index 0bc321a4d..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/integral_test.go +++ /dev/null @@ -1,156 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "bytes" - "fmt" - "image" - "testing" -) - -type integralTest struct { - x int - y int - src []uint8 - res []uint8 -} - -var integralTests = []integralTest{ - { - 1, 1, - []uint8{0x01}, - []uint8{0x01}, - }, - { - 2, 2, - []uint8{ - 0x01, 0x02, - 0x03, 0x04, - }, - []uint8{ - 0x01, 0x03, - 0x04, 0x0a, - }, - }, - { - 4, 4, - []uint8{ - 0x02, 0x03, 0x00, 0x01, - 0x01, 0x02, 0x01, 0x05, - 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, - }, - []uint8{ - 0x02, 0x05, 0x05, 0x06, - 0x03, 0x08, 0x09, 0x0f, - 0x04, 0x0a, 0x0c, 0x13, - 0x05, 0x0c, 0x0f, 0x17, - }, - }, -} - -func sprintBox(box []byte, width, height int) string { - buf := bytes.NewBuffer(nil) - i := 0 - for y := 0; y < height; y++ { - for x := 0; x < width; x++ { - fmt.Fprintf(buf, " 0x%02x,", box[i]) - i++ - } - buf.WriteByte('\n') - } - return buf.String() -} - -func TestIntegral(t *testing.T) { - for i, oc := range integralTests { - src := &image.Gray{ - Pix: oc.src, - Stride: oc.x, - Rect: image.Rect(0, 0, oc.x, oc.y), - } - dst, _ := newIntegrals(src) - res := make([]byte, len(dst.pix)) - for i, p := range dst.pix { - res[i] = byte(p) - } - - if !bytes.Equal(res, oc.res) { - got := sprintBox(res, oc.x, oc.y) - want := sprintBox(oc.res, oc.x, oc.y) - t.Errorf("%d: got\n%s\n want\n%s", i, got, want) - } - } -} - -func TestIntegralSum(t *testing.T) { - src := &image.Gray{ - Pix: []uint8{ - 0x02, 0x03, 0x00, 0x01, 0x03, - 0x01, 0x02, 0x01, 0x05, 0x05, - 0x01, 0x01, 0x01, 0x01, 0x02, - 0x01, 0x01, 0x01, 0x01, 0x07, - 0x02, 0x01, 0x00, 0x03, 0x01, - }, - Stride: 5, - Rect: image.Rect(0, 0, 5, 5), - } - img, _ := newIntegrals(src) - - type sumTest struct { - rect image.Rectangle - sum uint64 - } - - var sumTests = []sumTest{ - {image.Rect(0, 0, 1, 1), 2}, - {image.Rect(0, 0, 2, 1), 5}, - {image.Rect(0, 0, 1, 3), 4}, - {image.Rect(1, 1, 3, 3), 5}, - {image.Rect(2, 2, 4, 4), 4}, - {image.Rect(4, 3, 5, 5), 8}, - {image.Rect(2, 4, 3, 5), 0}, - } - - for _, st := range sumTests { - s := img.sum(st.rect) - if s != st.sum { - t.Errorf("%v: got %d want %d", st.rect, s, st.sum) - return - } - } -} - -func TestIntegralSubImage(t *testing.T) { - m0 := &image.Gray{ - Pix: []uint8{ - 0x02, 0x03, 0x00, 0x01, 0x03, - 0x01, 0x02, 0x01, 0x05, 0x05, - 0x01, 0x04, 0x01, 0x01, 0x02, - 0x01, 0x02, 0x01, 0x01, 0x07, - 0x02, 0x01, 0x09, 0x03, 0x01, - }, - Stride: 5, - Rect: image.Rect(0, 0, 5, 5), - } - b := image.Rect(1, 1, 4, 4) - m1 := m0.SubImage(b) - mi0, _ := newIntegrals(m0) - mi1, _ := newIntegrals(m1) - - sum0 := mi0.sum(b) - sum1 := mi1.sum(b) - if sum0 != sum1 { - t.Errorf("b got %d want %d", sum0, sum1) - } - - r0 := image.Rect(2, 2, 4, 4) - sum0 = mi0.sum(r0) - sum1 = mi1.sum(r0) - if sum0 != sum1 { - t.Errorf("r0 got %d want %d", sum1, sum0) - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser.go deleted file mode 100644 index 51ded1a1c..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser.go +++ /dev/null @@ -1,125 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "bytes" - "encoding/xml" - "errors" - "fmt" - "image" - "io" - "io/ioutil" - "strconv" - "strings" -) - -type xmlFeature struct { - Rects []string `xml:"grp>feature>rects>grp"` - Tilted int `xml:"grp>feature>tilted"` - Threshold float64 `xml:"grp>threshold"` - Left float64 `xml:"grp>left_val"` - Right float64 `xml:"grp>right_val"` -} - -type xmlStages struct { - Trees []xmlFeature `xml:"trees>grp"` - Stage_threshold float64 `xml:"stage_threshold"` - Parent int `xml:"parent"` - Next int `xml:"next"` -} - -type opencv_storage struct { - Any struct { - XMLName xml.Name - Type string `xml:"type_id,attr"` - Size string `xml:"size"` - Stages []xmlStages `xml:"stages>grp"` - } `xml:",any"` -} - -func buildFeature(r string) (f Feature, err error) { - var x, y, w, h int - var weight float64 - _, err = fmt.Sscanf(r, "%d %d %d %d %f", &x, &y, &w, &h, &weight) - if err != nil { - return - } - f.Rect = image.Rect(x, y, x+w, y+h) - f.Weight = weight - return -} - -func buildCascade(s *opencv_storage) (c *Cascade, name string, err error) { - if s.Any.Type != "opencv-haar-classifier" { - err = fmt.Errorf("got %s want opencv-haar-classifier", s.Any.Type) - return - } - name = s.Any.XMLName.Local - - c = &Cascade{} - sizes := strings.Split(s.Any.Size, " ") - w, err := strconv.Atoi(sizes[0]) - if err != nil { - return nil, "", err - } - h, err := strconv.Atoi(sizes[1]) - if err != nil { - return nil, "", err - } - c.Size = image.Pt(w, h) - c.Stage = []CascadeStage{} - - for _, stage := range s.Any.Stages { - cs := CascadeStage{ - Classifier: []Classifier{}, - Threshold: stage.Stage_threshold, - } - for _, tree := range stage.Trees { - if tree.Tilted != 0 { - err = errors.New("Cascade does not support tilted features") - return - } - - cls := Classifier{ - Feature: []Feature{}, - Threshold: tree.Threshold, - Left: tree.Left, - Right: tree.Right, - } - - for _, rect := range tree.Rects { - f, err := buildFeature(rect) - if err != nil { - return nil, "", err - } - cls.Feature = append(cls.Feature, f) - } - - cs.Classifier = append(cs.Classifier, cls) - } - c.Stage = append(c.Stage, cs) - } - - return -} - -// ParseOpenCV produces a detection Cascade from an OpenCV XML file. -func ParseOpenCV(r io.Reader) (cascade *Cascade, name string, err error) { - // BUG(crawshaw): tag-based parsing doesn't seem to work with <_> - buf, err := ioutil.ReadAll(r) - if err != nil { - return - } - buf = bytes.Replace(buf, []byte("<_>"), []byte(""), -1) - buf = bytes.Replace(buf, []byte(""), []byte(""), -1) - - s := &opencv_storage{} - err = xml.Unmarshal(buf, s) - if err != nil { - return - } - return buildCascade(s) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser_test.go deleted file mode 100644 index 343390499..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/opencv_parser_test.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "image" - "os" - "reflect" - "testing" -) - -var ( - classifier0 = Classifier{ - Feature: []Feature{ - Feature{Rect: image.Rect(0, 0, 3, 4), Weight: -1}, - Feature{Rect: image.Rect(3, 4, 5, 6), Weight: 3.1}, - }, - Threshold: 0.03, - Left: 0.01, - Right: 0.8, - } - classifier1 = Classifier{ - Feature: []Feature{ - Feature{Rect: image.Rect(3, 7, 17, 11), Weight: -3.2}, - Feature{Rect: image.Rect(3, 9, 17, 11), Weight: 2.}, - }, - Threshold: 0.11, - Left: 0.03, - Right: 0.83, - } - classifier2 = Classifier{ - Feature: []Feature{ - Feature{Rect: image.Rect(1, 1, 3, 3), Weight: -1.}, - Feature{Rect: image.Rect(3, 3, 5, 5), Weight: 2.5}, - }, - Threshold: 0.07, - Left: 0.2, - Right: 0.4, - } - cascade = Cascade{ - Stage: []CascadeStage{ - CascadeStage{ - Classifier: []Classifier{classifier0, classifier1}, - Threshold: 0.82, - }, - CascadeStage{ - Classifier: []Classifier{classifier2}, - Threshold: 0.22, - }, - }, - Size: image.Pt(20, 20), - } -) - -func TestParseOpenCV(t *testing.T) { - file, err := os.Open("../../testdata/opencv.xml") - if err != nil { - t.Fatal(err) - } - defer file.Close() - - cascadeFile, name, err := ParseOpenCV(file) - if err != nil { - t.Fatal(err) - } - if name != "name_of_cascade" { - t.Fatalf("name: got %s want name_of_cascade", name) - } - - if !reflect.DeepEqual(cascade, *cascadeFile) { - t.Errorf("got\n %v want\n %v", *cascadeFile, cascade) - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector.go deleted file mode 100644 index 1ebd6db59..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector.go +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "image" -) - -// projector allows projecting from a source Rectangle onto a target Rectangle. -type projector struct { - // rx, ry is the scaling factor. - rx, ry float64 - // dx, dy is the translation factor. - dx, dy float64 - // r is the clipping region of the target. - r image.Rectangle -} - -// newProjector creates a Projector with source src and target dst. -func newProjector(dst image.Rectangle, src image.Rectangle) *projector { - return &projector{ - rx: float64(dst.Dx()) / float64(src.Dx()), - ry: float64(dst.Dy()) / float64(src.Dy()), - dx: float64(dst.Min.X - src.Min.X), - dy: float64(dst.Min.Y - src.Min.Y), - r: dst, - } -} - -// pt projects p from the source rectangle onto the target rectangle. -func (s *projector) pt(p image.Point) image.Point { - return image.Point{ - clamp(s.rx*float64(p.X)+s.dx, s.r.Min.X, s.r.Max.X), - clamp(s.ry*float64(p.Y)+s.dy, s.r.Min.Y, s.r.Max.Y), - } -} - -// rect projects r from the source rectangle onto the target rectangle. -func (s *projector) rect(r image.Rectangle) image.Rectangle { - return image.Rectangle{s.pt(r.Min), s.pt(r.Max)} -} - -// clamp rounds and clamps o to the integer range [x0, x1]. -func clamp(o float64, x0, x1 int) int { - x := int(o + 0.5) - if x < x0 { - return x0 - } - if x > x1 { - return x1 - } - return x -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector_test.go deleted file mode 100644 index c6d0b0cd5..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/detect/projector_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package detect - -import ( - "image" - "reflect" - "testing" -) - -type projectorTest struct { - dst image.Rectangle - src image.Rectangle - pdst image.Rectangle - psrc image.Rectangle -} - -var projectorTests = []projectorTest{ - { - image.Rect(0, 0, 6, 6), - image.Rect(0, 0, 2, 2), - image.Rect(0, 0, 6, 6), - image.Rect(0, 0, 2, 2), - }, - { - image.Rect(0, 0, 6, 6), - image.Rect(0, 0, 2, 2), - image.Rect(3, 3, 6, 6), - image.Rect(1, 1, 2, 2), - }, - { - image.Rect(30, 30, 40, 40), - image.Rect(10, 10, 20, 20), - image.Rect(32, 33, 34, 37), - image.Rect(12, 13, 14, 17), - }, -} - -func TestProjector(t *testing.T) { - for i, tt := range projectorTests { - pr := newProjector(tt.dst, tt.src) - res := pr.rect(tt.psrc) - if !reflect.DeepEqual(res, tt.pdst) { - t.Errorf("%d: got %v want %v", i, res, tt.pdst) - } - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/Makefile b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/Makefile deleted file mode 100644 index 7bfdf22d8..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2011 The Graphics-Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=code.google.com/p/graphics-go/graphics/graphicstest -GOFILES=\ - graphicstest.go\ - -include $(GOROOT)/src/Make.pkg diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/graphicstest.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/graphicstest.go deleted file mode 100644 index ceb3a974d..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/graphicstest/graphicstest.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphicstest - -import ( - "bytes" - "errors" - "fmt" - "image" - "image/color" - "os" -) - -// LoadImage decodes an image from a file. -func LoadImage(path string) (img image.Image, err error) { - file, err := os.Open(path) - if err != nil { - return - } - defer file.Close() - img, _, err = image.Decode(file) - return -} - -func delta(u0, u1 uint32) int { - d := int(u0) - int(u1) - if d < 0 { - return -d - } - return d -} - -func withinTolerance(c0, c1 color.Color, tol int) bool { - r0, g0, b0, a0 := c0.RGBA() - r1, g1, b1, a1 := c1.RGBA() - r := delta(r0, r1) - g := delta(g0, g1) - b := delta(b0, b1) - a := delta(a0, a1) - return r <= tol && g <= tol && b <= tol && a <= tol -} - -// ImageWithinTolerance checks that each pixel varies by no more than tol. -func ImageWithinTolerance(m0, m1 image.Image, tol int) error { - b0 := m0.Bounds() - b1 := m1.Bounds() - if !b0.Eq(b1) { - return errors.New(fmt.Sprintf("got bounds %v want %v", b0, b1)) - } - - for y := b0.Min.Y; y < b0.Max.Y; y++ { - for x := b0.Min.X; x < b0.Max.X; x++ { - c0 := m0.At(x, y) - c1 := m1.At(x, y) - if !withinTolerance(c0, c1, tol) { - e := fmt.Sprintf("got %v want %v at (%d, %d)", c0, c1, x, y) - return errors.New(e) - } - } - } - return nil -} - -// SprintBox pretty prints the array as a hexidecimal matrix. -func SprintBox(box []byte, width, height int) string { - buf := bytes.NewBuffer(nil) - i := 0 - for y := 0; y < height; y++ { - for x := 0; x < width; x++ { - fmt.Fprintf(buf, " 0x%02x,", box[i]) - i++ - } - buf.WriteByte('\n') - } - return buf.String() -} - -// SprintImageR pretty prints the red channel of src. It looks like SprintBox. -func SprintImageR(src *image.RGBA) string { - w, h := src.Rect.Dx(), src.Rect.Dy() - i := 0 - box := make([]byte, w*h) - for y := src.Rect.Min.Y; y < src.Rect.Max.Y; y++ { - for x := src.Rect.Min.X; x < src.Rect.Max.X; x++ { - off := (y-src.Rect.Min.Y)*src.Stride + (x-src.Rect.Min.X)*4 - box[i] = src.Pix[off] - i++ - } - } - return SprintBox(box, w, h) -} - -// MakeRGBA returns an image with R, G, B taken from src. -func MakeRGBA(src []uint8, width int) *image.RGBA { - b := image.Rect(0, 0, width, len(src)/width) - ret := image.NewRGBA(b) - i := 0 - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - ret.SetRGBA(x, y, color.RGBA{ - R: src[i], - G: src[i], - B: src[i], - A: 0xff, - }) - i++ - } - } - return ret -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/Makefile b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/Makefile deleted file mode 100644 index 4d8f524fb..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2012 The Graphics-Go Authors. All rights reserved. -# Use of this source code is governed by a BSD-style -# license that can be found in the LICENSE file. - -include $(GOROOT)/src/Make.inc - -TARG=code.google.com/p/graphics-go/graphics/interp -GOFILES=\ - bilinear.go\ - doc.go\ - interp.go\ - -include $(GOROOT)/src/Make.pkg diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear.go deleted file mode 100644 index e18321a15..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear.go +++ /dev/null @@ -1,206 +0,0 @@ -// Copyright 2012 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package interp - -import ( - "image" - "image/color" - "math" -) - -// Bilinear implements bilinear interpolation. -var Bilinear Interp = bilinear{} - -type bilinear struct{} - -func (i bilinear) Interp(src image.Image, x, y float64) color.Color { - if src, ok := src.(*image.RGBA); ok { - return i.RGBA(src, x, y) - } - return bilinearGeneral(src, x, y) -} - -func bilinearGeneral(src image.Image, x, y float64) color.Color { - p := findLinearSrc(src.Bounds(), x, y) - var fr, fg, fb, fa float64 - var r, g, b, a uint32 - - r, g, b, a = src.At(p.low.X, p.low.Y).RGBA() - fr += float64(r) * p.frac00 - fg += float64(g) * p.frac00 - fb += float64(b) * p.frac00 - fa += float64(a) * p.frac00 - - r, g, b, a = src.At(p.high.X, p.low.Y).RGBA() - fr += float64(r) * p.frac01 - fg += float64(g) * p.frac01 - fb += float64(b) * p.frac01 - fa += float64(a) * p.frac01 - - r, g, b, a = src.At(p.low.X, p.high.Y).RGBA() - fr += float64(r) * p.frac10 - fg += float64(g) * p.frac10 - fb += float64(b) * p.frac10 - fa += float64(a) * p.frac10 - - r, g, b, a = src.At(p.high.X, p.high.Y).RGBA() - fr += float64(r) * p.frac11 - fg += float64(g) * p.frac11 - fb += float64(b) * p.frac11 - fa += float64(a) * p.frac11 - - var c color.RGBA64 - c.R = uint16(fr + 0.5) - c.G = uint16(fg + 0.5) - c.B = uint16(fb + 0.5) - c.A = uint16(fa + 0.5) - return c -} - -func (bilinear) RGBA(src *image.RGBA, x, y float64) color.RGBA { - p := findLinearSrc(src.Bounds(), x, y) - - // Array offsets for the surrounding pixels. - off00 := offRGBA(src, p.low.X, p.low.Y) - off01 := offRGBA(src, p.high.X, p.low.Y) - off10 := offRGBA(src, p.low.X, p.high.Y) - off11 := offRGBA(src, p.high.X, p.high.Y) - - var fr, fg, fb, fa float64 - - fr += float64(src.Pix[off00+0]) * p.frac00 - fg += float64(src.Pix[off00+1]) * p.frac00 - fb += float64(src.Pix[off00+2]) * p.frac00 - fa += float64(src.Pix[off00+3]) * p.frac00 - - fr += float64(src.Pix[off01+0]) * p.frac01 - fg += float64(src.Pix[off01+1]) * p.frac01 - fb += float64(src.Pix[off01+2]) * p.frac01 - fa += float64(src.Pix[off01+3]) * p.frac01 - - fr += float64(src.Pix[off10+0]) * p.frac10 - fg += float64(src.Pix[off10+1]) * p.frac10 - fb += float64(src.Pix[off10+2]) * p.frac10 - fa += float64(src.Pix[off10+3]) * p.frac10 - - fr += float64(src.Pix[off11+0]) * p.frac11 - fg += float64(src.Pix[off11+1]) * p.frac11 - fb += float64(src.Pix[off11+2]) * p.frac11 - fa += float64(src.Pix[off11+3]) * p.frac11 - - var c color.RGBA - c.R = uint8(fr + 0.5) - c.G = uint8(fg + 0.5) - c.B = uint8(fb + 0.5) - c.A = uint8(fa + 0.5) - return c -} - -func (bilinear) Gray(src *image.Gray, x, y float64) color.Gray { - p := findLinearSrc(src.Bounds(), x, y) - - // Array offsets for the surrounding pixels. - off00 := offGray(src, p.low.X, p.low.Y) - off01 := offGray(src, p.high.X, p.low.Y) - off10 := offGray(src, p.low.X, p.high.Y) - off11 := offGray(src, p.high.X, p.high.Y) - - var fc float64 - fc += float64(src.Pix[off00]) * p.frac00 - fc += float64(src.Pix[off01]) * p.frac01 - fc += float64(src.Pix[off10]) * p.frac10 - fc += float64(src.Pix[off11]) * p.frac11 - - var c color.Gray - c.Y = uint8(fc + 0.5) - return c -} - -type bilinearSrc struct { - // Top-left and bottom-right interpolation sources - low, high image.Point - // Fraction of each pixel to take. The 0 suffix indicates - // top/left, and the 1 suffix indicates bottom/right. - frac00, frac01, frac10, frac11 float64 -} - -func findLinearSrc(b image.Rectangle, sx, sy float64) bilinearSrc { - maxX := float64(b.Max.X) - maxY := float64(b.Max.Y) - minX := float64(b.Min.X) - minY := float64(b.Min.Y) - lowX := math.Floor(sx - 0.5) - lowY := math.Floor(sy - 0.5) - if lowX < minX { - lowX = minX - } - if lowY < minY { - lowY = minY - } - - highX := math.Ceil(sx - 0.5) - highY := math.Ceil(sy - 0.5) - if highX >= maxX { - highX = maxX - 1 - } - if highY >= maxY { - highY = maxY - 1 - } - - // In the variables below, the 0 suffix indicates top/left, and the - // 1 suffix indicates bottom/right. - - // Center of each surrounding pixel. - x00 := lowX + 0.5 - y00 := lowY + 0.5 - x01 := highX + 0.5 - y01 := lowY + 0.5 - x10 := lowX + 0.5 - y10 := highY + 0.5 - x11 := highX + 0.5 - y11 := highY + 0.5 - - p := bilinearSrc{ - low: image.Pt(int(lowX), int(lowY)), - high: image.Pt(int(highX), int(highY)), - } - - // Literally, edge cases. If we are close enough to the edge of - // the image, curtail the interpolation sources. - if lowX == highX && lowY == highY { - p.frac00 = 1.0 - } else if sy-minY <= 0.5 && sx-minX <= 0.5 { - p.frac00 = 1.0 - } else if maxY-sy <= 0.5 && maxX-sx <= 0.5 { - p.frac11 = 1.0 - } else if sy-minY <= 0.5 || lowY == highY { - p.frac00 = x01 - sx - p.frac01 = sx - x00 - } else if sx-minX <= 0.5 || lowX == highX { - p.frac00 = y10 - sy - p.frac10 = sy - y00 - } else if maxY-sy <= 0.5 { - p.frac10 = x11 - sx - p.frac11 = sx - x10 - } else if maxX-sx <= 0.5 { - p.frac01 = y11 - sy - p.frac11 = sy - y01 - } else { - p.frac00 = (x01 - sx) * (y10 - sy) - p.frac01 = (sx - x00) * (y11 - sy) - p.frac10 = (x11 - sx) * (sy - y00) - p.frac11 = (sx - x10) * (sy - y01) - } - - return p -} - -// TODO(crawshaw): When we have inlining, consider func (p *RGBA) Off(x, y) int -func offRGBA(src *image.RGBA, x, y int) int { - return (y-src.Rect.Min.Y)*src.Stride + (x-src.Rect.Min.X)*4 -} -func offGray(src *image.Gray, x, y int) int { - return (y-src.Rect.Min.Y)*src.Stride + (x - src.Rect.Min.X) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear_test.go deleted file mode 100644 index 242d70546..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/bilinear_test.go +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2012 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package interp - -import ( - "image" - "image/color" - "testing" -) - -type interpTest struct { - desc string - src []uint8 - srcWidth int - x, y float64 - expect uint8 -} - -func (p *interpTest) newSrc() *image.RGBA { - b := image.Rect(0, 0, p.srcWidth, len(p.src)/p.srcWidth) - src := image.NewRGBA(b) - i := 0 - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - src.SetRGBA(x, y, color.RGBA{ - R: p.src[i], - G: p.src[i], - B: p.src[i], - A: 0xff, - }) - i++ - } - } - return src -} - -var interpTests = []interpTest{ - { - desc: "center of a single white pixel should match that pixel", - src: []uint8{0x00}, - srcWidth: 1, - x: 0.5, - y: 0.5, - expect: 0x00, - }, - { - desc: "middle of a square is equally weighted", - src: []uint8{ - 0x00, 0xff, - 0xff, 0x00, - }, - srcWidth: 2, - x: 1.0, - y: 1.0, - expect: 0x80, - }, - { - desc: "center of a pixel is just that pixel", - src: []uint8{ - 0x00, 0xff, - 0xff, 0x00, - }, - srcWidth: 2, - x: 1.5, - y: 0.5, - expect: 0xff, - }, - { - desc: "asymmetry abounds", - src: []uint8{ - 0xaa, 0x11, 0x55, - 0xff, 0x95, 0xdd, - }, - srcWidth: 3, - x: 2.0, - y: 1.0, - expect: 0x76, // (0x11 + 0x55 + 0x95 + 0xdd) / 4 - }, -} - -func TestBilinearRGBA(t *testing.T) { - for _, p := range interpTests { - src := p.newSrc() - - // Fast path. - c := Bilinear.(RGBA).RGBA(src, p.x, p.y) - if c.R != c.G || c.R != c.B || c.A != 0xff { - t.Errorf("expect channels to match, got %v", c) - continue - } - if c.R != p.expect { - t.Errorf("%s: got 0x%02x want 0x%02x", p.desc, c.R, p.expect) - continue - } - - // Standard Interp should use the fast path. - cStd := Bilinear.Interp(src, p.x, p.y) - if cStd != c { - t.Errorf("%s: standard mismatch got %v want %v", p.desc, cStd, c) - continue - } - - // General case should match the fast path. - cGen := color.RGBAModel.Convert(bilinearGeneral(src, p.x, p.y)) - r0, g0, b0, a0 := c.RGBA() - r1, g1, b1, a1 := cGen.RGBA() - if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { - t.Errorf("%s: general case mismatch got %v want %v", p.desc, c, cGen) - continue - } - } -} - -func TestBilinearSubImage(t *testing.T) { - b0 := image.Rect(0, 0, 4, 4) - src0 := image.NewRGBA(b0) - b1 := image.Rect(1, 1, 3, 3) - src1 := src0.SubImage(b1).(*image.RGBA) - src1.Set(1, 1, color.RGBA{0x11, 0, 0, 0xff}) - src1.Set(2, 1, color.RGBA{0x22, 0, 0, 0xff}) - src1.Set(1, 2, color.RGBA{0x33, 0, 0, 0xff}) - src1.Set(2, 2, color.RGBA{0x44, 0, 0, 0xff}) - - tests := []struct { - x, y float64 - want uint8 - }{ - {1, 1, 0x11}, - {3, 1, 0x22}, - {1, 3, 0x33}, - {3, 3, 0x44}, - {2, 2, 0x2b}, - } - - for _, p := range tests { - c := Bilinear.(RGBA).RGBA(src1, p.x, p.y) - if c.R != p.want { - t.Errorf("(%.0f, %.0f): got 0x%02x want 0x%02x", p.x, p.y, c.R, p.want) - } - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/doc.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/doc.go deleted file mode 100644 index b115534cc..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/doc.go +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2012 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -/* -Package interp implements image interpolation. - -An interpolator provides the Interp interface, which can be used -to interpolate a pixel: - - c := interp.Bilinear.Interp(src, 1.2, 1.8) - -To interpolate a large number of RGBA or Gray pixels, an implementation -may provide a fast-path by implementing the RGBA or Gray interfaces. - - i1, ok := i.(interp.RGBA) - if ok { - c := i1.RGBA(src, 1.2, 1.8) - // use c.R, c.G, etc - return - } - c := i.Interp(src, 1.2, 1.8) - // use generic color.Color -*/ -package interp diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/interp.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/interp.go deleted file mode 100644 index 560637d4a..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/interp/interp.go +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2012 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package interp - -import ( - "image" - "image/color" -) - -// Interp interpolates an image's color at fractional co-ordinates. -type Interp interface { - // Interp interpolates (x, y). - Interp(src image.Image, x, y float64) color.Color -} - -// RGBA is a fast-path interpolation implementation for image.RGBA. -// It is common for an Interp to also implement RGBA. -type RGBA interface { - // RGBA interpolates (x, y). - RGBA(src *image.RGBA, x, y float64) color.RGBA -} - -// Gray is a fast-path interpolation implementation for image.Gray. -type Gray interface { - // Gray interpolates (x, y). - Gray(src *image.Gray, x, y float64) color.Gray -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate.go deleted file mode 100644 index 62bde1a08..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/interp" - "errors" - "image" - "image/draw" -) - -// RotateOptions are the rotation parameters. -// Angle is the angle, in radians, to rotate the image clockwise. -type RotateOptions struct { - Angle float64 -} - -// Rotate produces a rotated version of src, drawn onto dst. -func Rotate(dst draw.Image, src image.Image, opt *RotateOptions) error { - if dst == nil { - return errors.New("graphics: dst is nil") - } - if src == nil { - return errors.New("graphics: src is nil") - } - - angle := 0.0 - if opt != nil { - angle = opt.Angle - } - - return I.Rotate(angle).TransformCenter(dst, src, interp.Bilinear) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate_test.go deleted file mode 100644 index bfc532a0a..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/rotate_test.go +++ /dev/null @@ -1,169 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/graphicstest" - "image" - "math" - "testing" - - _ "image/png" -) - -var rotateOneColorTests = []transformOneColorTest{ - { - "onepixel-onequarter", 1, 1, 1, 1, - &RotateOptions{math.Pi / 2}, - []uint8{0xff}, - []uint8{0xff}, - }, - { - "onepixel-partial", 1, 1, 1, 1, - &RotateOptions{math.Pi * 2.0 / 3.0}, - []uint8{0xff}, - []uint8{0xff}, - }, - { - "onepixel-complete", 1, 1, 1, 1, - &RotateOptions{2 * math.Pi}, - []uint8{0xff}, - []uint8{0xff}, - }, - { - "even-onequarter", 2, 2, 2, 2, - &RotateOptions{math.Pi / 2.0}, - []uint8{ - 0xff, 0x00, - 0x00, 0xff, - }, - []uint8{ - 0x00, 0xff, - 0xff, 0x00, - }, - }, - { - "even-complete", 2, 2, 2, 2, - &RotateOptions{2.0 * math.Pi}, - []uint8{ - 0xff, 0x00, - 0x00, 0xff, - }, - []uint8{ - 0xff, 0x00, - 0x00, 0xff, - }, - }, - { - "line-partial", 3, 3, 3, 3, - &RotateOptions{math.Pi * 1.0 / 3.0}, - []uint8{ - 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, - }, - []uint8{ - 0xa2, 0x80, 0x00, - 0x22, 0xff, 0x22, - 0x00, 0x80, 0xa2, - }, - }, - { - "line-offset-partial", 3, 3, 3, 3, - &RotateOptions{math.Pi * 3 / 2}, - []uint8{ - 0x00, 0x00, 0x00, - 0x00, 0xff, 0xff, - 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0xff, 0x00, - 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, - }, - }, - { - "dot-partial", 4, 4, 4, 4, - &RotateOptions{math.Pi}, - []uint8{ - 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - }, - []uint8{ - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, - }, - }, -} - -func TestRotateOneColor(t *testing.T) { - for _, oc := range rotateOneColorTests { - src := oc.newSrc() - dst := oc.newDst() - - if err := Rotate(dst, src, oc.opt.(*RotateOptions)); err != nil { - t.Errorf("rotate %s: %v", oc.desc, err) - continue - } - if !checkTransformTest(t, &oc, dst) { - continue - } - } -} - -func TestRotateEmpty(t *testing.T) { - empty := image.NewRGBA(image.Rect(0, 0, 0, 0)) - if err := Rotate(empty, empty, nil); err != nil { - t.Fatal(err) - } -} - -func TestRotateGopherSide(t *testing.T) { - src, err := graphicstest.LoadImage("../testdata/gopher.png") - if err != nil { - t.Fatal(err) - } - - srcb := src.Bounds() - dst := image.NewRGBA(image.Rect(0, 0, srcb.Dy(), srcb.Dx())) - if err := Rotate(dst, src, &RotateOptions{math.Pi / 2.0}); err != nil { - t.Fatal(err) - } - - cmp, err := graphicstest.LoadImage("../testdata/gopher-rotate-side.png") - if err != nil { - t.Fatal(err) - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0x101) - if err != nil { - t.Fatal(err) - } -} - -func TestRotateGopherPartial(t *testing.T) { - src, err := graphicstest.LoadImage("../testdata/gopher.png") - if err != nil { - t.Fatal(err) - } - - srcb := src.Bounds() - dst := image.NewRGBA(image.Rect(0, 0, srcb.Dx(), srcb.Dy())) - if err := Rotate(dst, src, &RotateOptions{math.Pi / 3.0}); err != nil { - t.Fatal(err) - } - - cmp, err := graphicstest.LoadImage("../testdata/gopher-rotate-partial.png") - if err != nil { - t.Fatal(err) - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0x101) - if err != nil { - t.Fatal(err) - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale.go deleted file mode 100644 index 7a7fe9696..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/interp" - "errors" - "image" - "image/draw" -) - -// Scale produces a scaled version of the image using bilinear interpolation. -func Scale(dst draw.Image, src image.Image) error { - if dst == nil { - return errors.New("graphics: dst is nil") - } - if src == nil { - return errors.New("graphics: src is nil") - } - - b := dst.Bounds() - srcb := src.Bounds() - if b.Empty() || srcb.Empty() { - return nil - } - sx := float64(b.Dx()) / float64(srcb.Dx()) - sy := float64(b.Dy()) / float64(srcb.Dy()) - return I.Scale(sx, sy).Transform(dst, src, interp.Bilinear) -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale_test.go deleted file mode 100644 index 9c2468f11..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/scale_test.go +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/graphicstest" - "image" - "testing" - - _ "image/png" -) - -var scaleOneColorTests = []transformOneColorTest{ - { - "down-half", - 1, 1, - 2, 2, - nil, - []uint8{ - 0x80, 0x00, - 0x00, 0x80, - }, - []uint8{ - 0x40, - }, - }, - { - "up-double", - 4, 4, - 2, 2, - nil, - []uint8{ - 0x80, 0x00, - 0x00, 0x80, - }, - []uint8{ - 0x80, 0x60, 0x20, 0x00, - 0x60, 0x50, 0x30, 0x20, - 0x20, 0x30, 0x50, 0x60, - 0x00, 0x20, 0x60, 0x80, - }, - }, - { - "up-doublewidth", - 4, 2, - 2, 2, - nil, - []uint8{ - 0x80, 0x00, - 0x00, 0x80, - }, - []uint8{ - 0x80, 0x60, 0x20, 0x00, - 0x00, 0x20, 0x60, 0x80, - }, - }, - { - "up-doubleheight", - 2, 4, - 2, 2, - nil, - []uint8{ - 0x80, 0x00, - 0x00, 0x80, - }, - []uint8{ - 0x80, 0x00, - 0x60, 0x20, - 0x20, 0x60, - 0x00, 0x80, - }, - }, - { - "up-partial", - 3, 3, - 2, 2, - nil, - []uint8{ - 0x80, 0x00, - 0x00, 0x80, - }, - []uint8{ - 0x80, 0x40, 0x00, - 0x40, 0x40, 0x40, - 0x00, 0x40, 0x80, - }, - }, -} - -func TestScaleOneColor(t *testing.T) { - for _, oc := range scaleOneColorTests { - dst := oc.newDst() - src := oc.newSrc() - if err := Scale(dst, src); err != nil { - t.Errorf("scale %s: %v", oc.desc, err) - continue - } - - if !checkTransformTest(t, &oc, dst) { - continue - } - } -} - -func TestScaleEmpty(t *testing.T) { - empty := image.NewRGBA(image.Rect(0, 0, 0, 0)) - if err := Scale(empty, empty); err != nil { - t.Fatal(err) - } -} - -func TestScaleGopher(t *testing.T) { - dst := image.NewRGBA(image.Rect(0, 0, 100, 150)) - - src, err := graphicstest.LoadImage("../testdata/gopher.png") - if err != nil { - t.Error(err) - return - } - - // Down-sample. - if err := Scale(dst, src); err != nil { - t.Fatal(err) - } - cmp, err := graphicstest.LoadImage("../testdata/gopher-100x150.png") - if err != nil { - t.Error(err) - return - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0) - if err != nil { - t.Error(err) - return - } - - // Up-sample. - dst = image.NewRGBA(image.Rect(0, 0, 500, 750)) - if err := Scale(dst, src); err != nil { - t.Fatal(err) - } - cmp, err = graphicstest.LoadImage("../testdata/gopher-500x750.png") - if err != nil { - t.Error(err) - return - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0) - if err != nil { - t.Error(err) - return - } -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/shared_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/shared_test.go deleted file mode 100644 index e1cd21fb3..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/shared_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "bytes" - "code.google.com/p/graphics-go/graphics/graphicstest" - "image" - "image/color" - "testing" -) - -type transformOneColorTest struct { - desc string - dstWidth int - dstHeight int - srcWidth int - srcHeight int - opt interface{} - src []uint8 - res []uint8 -} - -func (oc *transformOneColorTest) newSrc() *image.RGBA { - b := image.Rect(0, 0, oc.srcWidth, oc.srcHeight) - src := image.NewRGBA(b) - i := 0 - for y := b.Min.Y; y < b.Max.Y; y++ { - for x := b.Min.X; x < b.Max.X; x++ { - src.SetRGBA(x, y, color.RGBA{ - R: oc.src[i], - G: oc.src[i], - B: oc.src[i], - A: oc.src[i], - }) - i++ - } - } - return src -} - -func (oc *transformOneColorTest) newDst() *image.RGBA { - return image.NewRGBA(image.Rect(0, 0, oc.dstWidth, oc.dstHeight)) -} - -func checkTransformTest(t *testing.T, oc *transformOneColorTest, dst *image.RGBA) bool { - for ch := 0; ch < 4; ch++ { - i := 0 - res := make([]byte, len(oc.res)) - for y := 0; y < oc.dstHeight; y++ { - for x := 0; x < oc.dstWidth; x++ { - off := (y-dst.Rect.Min.Y)*dst.Stride + (x-dst.Rect.Min.X)*4 - res[i] = dst.Pix[off+ch] - i++ - } - } - - if !bytes.Equal(res, oc.res) { - got := graphicstest.SprintBox(res, oc.dstWidth, oc.dstHeight) - want := graphicstest.SprintBox(oc.res, oc.dstWidth, oc.dstHeight) - t.Errorf("%s: ch=%d\n got\n%s\n want\n%s", oc.desc, ch, got, want) - return false - } - } - - return true -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail.go deleted file mode 100644 index d3ad7e8f7..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail.go +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "image" - "image/draw" -) - -// Thumbnail scales and crops src so it fits in dst. -func Thumbnail(dst draw.Image, src image.Image) error { - // Scale down src in the dimension that is closer to dst. - sb := src.Bounds() - db := dst.Bounds() - rx := float64(sb.Dx()) / float64(db.Dx()) - ry := float64(sb.Dy()) / float64(db.Dy()) - var b image.Rectangle - if rx < ry { - b = image.Rect(0, 0, db.Dx(), int(float64(sb.Dy())/rx)) - } else { - b = image.Rect(0, 0, int(float64(sb.Dx())/ry), db.Dy()) - } - - buf := image.NewRGBA(b) - if err := Scale(buf, src); err != nil { - return err - } - - // Crop. - // TODO(crawshaw): improve on center-alignment. - var pt image.Point - if rx < ry { - pt.Y = (b.Dy() - db.Dy()) / 2 - } else { - pt.X = (b.Dx() - db.Dx()) / 2 - } - draw.Draw(dst, db, buf, pt, draw.Src) - return nil -} diff --git a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail_test.go b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail_test.go deleted file mode 100644 index d12659f17..000000000 --- a/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/thumbnail_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2011 The Graphics-Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package graphics - -import ( - "code.google.com/p/graphics-go/graphics/graphicstest" - "image" - "testing" - - _ "image/png" -) - -func TestThumbnailGopher(t *testing.T) { - dst := image.NewRGBA(image.Rect(0, 0, 80, 80)) - - src, err := graphicstest.LoadImage("../testdata/gopher.png") - if err != nil { - t.Fatal(err) - } - if err := Thumbnail(dst, src); err != nil { - t.Fatal(err) - } - cmp, err := graphicstest.LoadImage("../testdata/gopher-thumb-80x80.png") - if err != nil { - t.Fatal(err) - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0) - if err != nil { - t.Error(err) - } -} - -func TestThumbnailLongGopher(t *testing.T) { - dst := image.NewRGBA(image.Rect(0, 0, 50, 150)) - - src, err := graphicstest.LoadImage("../testdata/gopher.png") - if err != nil { - t.Fatal(err) - } - if err := Thumbnail(dst, src); err != nil { - t.Fatal(err) - } - cmp, err := graphicstest.LoadImage("../testdata/gopher-thumb-50x150.png") - if err != nil { - t.Fatal(err) - } - err = graphicstest.ImageWithinTolerance(dst, cmp, 0) - if err != nil { - t.Error(err) - } -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/.travis.yml b/Godeps/_workspace/src/github.com/nfnt/resize/.travis.yml deleted file mode 100644 index 57bd4a76e..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/.travis.yml +++ /dev/null @@ -1,7 +0,0 @@ -language: go - -go: - - 1.1 - - 1.2 - - 1.3 - - tip diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/LICENSE b/Godeps/_workspace/src/github.com/nfnt/resize/LICENSE deleted file mode 100644 index 7836cad5f..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/LICENSE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/README.md b/Godeps/_workspace/src/github.com/nfnt/resize/README.md deleted file mode 100644 index 2aefa75c9..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/README.md +++ /dev/null @@ -1,149 +0,0 @@ -Resize -====== - -Image resizing for the [Go programming language](http://golang.org) with common interpolation methods. - -[![Build Status](https://travis-ci.org/nfnt/resize.svg)](https://travis-ci.org/nfnt/resize) - -Installation ------------- - -```bash -$ go get github.com/nfnt/resize -``` - -It's that easy! - -Usage ------ - -This package needs at least Go 1.1. Import package with - -```go -import "github.com/nfnt/resize" -``` - -The resize package provides 2 functions: - -* `resize.Resize` creates a scaled image with new dimensions (`width`, `height`) using the interpolation function `interp`. - If either `width` or `height` is set to 0, it will be set to an aspect ratio preserving value. -* `resize.Thumbnail` downscales an image preserving its aspect ratio to the maximum dimensions (`maxWidth`, `maxHeight`). - It will return the original image if original sizes are smaller than the provided dimensions. - -```go -resize.Resize(width, height uint, img image.Image, interp resize.InterpolationFunction) image.Image -resize.Thumbnail(maxWidth, maxHeight uint, img image.Image, interp resize.InterpolationFunction) image.Image -``` - -The provided interpolation functions are (from fast to slow execution time) - -- `NearestNeighbor`: [Nearest-neighbor interpolation](http://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) -- `Bilinear`: [Bilinear interpolation](http://en.wikipedia.org/wiki/Bilinear_interpolation) -- `Bicubic`: [Bicubic interpolation](http://en.wikipedia.org/wiki/Bicubic_interpolation) -- `MitchellNetravali`: [Mitchell-Netravali interpolation](http://dl.acm.org/citation.cfm?id=378514) -- `Lanczos2`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=2 -- `Lanczos3`: [Lanczos resampling](http://en.wikipedia.org/wiki/Lanczos_resampling) with a=3 - -Which of these methods gives the best results depends on your use case. - -Sample usage: - -```go -package main - -import ( - "github.com/nfnt/resize" - "image/jpeg" - "log" - "os" -) - -func main() { - // open "test.jpg" - file, err := os.Open("test.jpg") - if err != nil { - log.Fatal(err) - } - - // decode jpeg into image.Image - img, err := jpeg.Decode(file) - if err != nil { - log.Fatal(err) - } - file.Close() - - // resize to width 1000 using Lanczos resampling - // and preserve aspect ratio - m := resize.Resize(1000, 0, img, resize.Lanczos3) - - out, err := os.Create("test_resized.jpg") - if err != nil { - log.Fatal(err) - } - defer out.Close() - - // write new image to file - jpeg.Encode(out, m, nil) -} -``` - -Caveats -------- - -* Optimized access routines are used for `image.RGBA`, `image.NRGBA`, `image.RGBA64`, `image.NRGBA64`, `image.YCbCr`, `image.Gray`, and `image.Gray16` types. All other image types are accessed in a generic way that will result in slow processing speed. -* JPEG images are stored in `image.YCbCr`. This image format stores data in a way that will decrease processing speed. A resize may be up to 2 times slower than with `image.RGBA`. - - -Downsizing Samples -------- - -Downsizing is not as simple as it might look like. Images have to be filtered before they are scaled down, otherwise aliasing might occur. -Filtering is highly subjective: Applying too much will blur the whole image, too little will make aliasing become apparent. -Resize tries to provide sane defaults that should suffice in most cases. - -### Artificial sample - -Original image -![Rings](http://nfnt.github.com/img/rings_lg_orig.png) - - - - - - - - - - - - - - -

Nearest-Neighbor

Bilinear

Bicubic

Mitchell-Netravali

Lanczos2

Lanczos3
- -### Real-Life sample - -Original image -![Original](http://nfnt.github.com/img/IMG_3694_720.jpg) - - - - - - - - - - - - - - -

Nearest-Neighbor

Bilinear

Bicubic

Mitchell-Netravali

Lanczos2

Lanczos3
- - -License -------- - -Copyright (c) 2012 Jan Schlicht -Resize is released under a MIT style license. diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/converter.go b/Godeps/_workspace/src/github.com/nfnt/resize/converter.go deleted file mode 100644 index b3dd06b8d..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/converter.go +++ /dev/null @@ -1,452 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import "image" - -// Keep value in [0,255] range. -func clampUint8(in int32) uint8 { - // casting a negative int to an uint will result in an overflown - // large uint. this behavior will be exploited here and in other functions - // to achieve a higher performance. - if uint32(in) < 256 { - return uint8(in) - } - if in > 255 { - return 255 - } - return 0 -} - -// Keep value in [0,65535] range. -func clampUint16(in int64) uint16 { - if uint64(in) < 65536 { - return uint16(in) - } - if in > 65535 { - return 65535 - } - return 0 -} - -func resizeGeneric(in image.Image, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() - - // reverse alpha-premultiplication. - if a != 0 { - r *= 0xffff - r /= a - g *= 0xffff - g /= a - b *= 0xffff - b /= a - } - - rgba[0] += int64(coeff) * int64(r) - rgba[1] += int64(coeff) * int64(g) - rgba[2] += int64(coeff) * int64(b) - rgba[3] += int64(coeff) * int64(a) - sum += int64(coeff) - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := clampUint16(rgba[0] / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - value = clampUint16(rgba[1] / sum) - out.Pix[offset+2] = uint8(value >> 8) - out.Pix[offset+3] = uint8(value) - value = clampUint16(rgba[2] / sum) - out.Pix[offset+4] = uint8(value >> 8) - out.Pix[offset+5] = uint8(value) - value = clampUint16(rgba[3] / sum) - out.Pix[offset+6] = uint8(value >> 8) - out.Pix[offset+7] = uint8(value) - } - } -} - -func resizeRGBA(in *image.RGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - - r := uint32(row[xi+0]) - g := uint32(row[xi+1]) - b := uint32(row[xi+2]) - a := uint32(row[xi+3]) - - // reverse alpha-premultiplication. - if a != 0 { - r *= 0xff - r /= a - g *= 0xff - g /= a - b *= 0xff - b /= a - } - - rgba[0] += int32(coeff) * int32(r) - rgba[1] += int32(coeff) * int32(g) - rgba[2] += int32(coeff) * int32(b) - rgba[3] += int32(coeff) * int32(a) - sum += int32(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - out.Pix[xo+0] = clampUint8(rgba[0] / sum) - out.Pix[xo+1] = clampUint8(rgba[1] / sum) - out.Pix[xo+2] = clampUint8(rgba[2] / sum) - out.Pix[xo+3] = clampUint8(rgba[3] / sum) - } - } -} - -func resizeNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - rgba[0] += int32(coeff) * int32(row[xi+0]) - rgba[1] += int32(coeff) * int32(row[xi+1]) - rgba[2] += int32(coeff) * int32(row[xi+2]) - rgba[3] += int32(coeff) * int32(row[xi+3]) - sum += int32(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - out.Pix[xo+0] = clampUint8(rgba[0] / sum) - out.Pix[xo+1] = clampUint8(rgba[1] / sum) - out.Pix[xo+2] = clampUint8(rgba[2] / sum) - out.Pix[xo+3] = clampUint8(rgba[3] / sum) - } - } -} - -func resizeRGBA64(in *image.RGBA64, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - - r := uint32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - g := uint32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) - b := uint32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) - a := uint32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) - - // reverse alpha-premultiplication. - if a != 0 { - r *= 0xffff - r /= a - g *= 0xffff - g /= a - b *= 0xffff - b /= a - } - - rgba[0] += int64(coeff) * int64(r) - rgba[1] += int64(coeff) * int64(g) - rgba[2] += int64(coeff) * int64(b) - rgba[3] += int64(coeff) * int64(a) - sum += int64(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := clampUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = clampUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = clampUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = clampUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func resizeNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - rgba[0] += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) - rgba[1] += int64(coeff) * int64(uint16(row[xi+2])<<8|uint16(row[xi+3])) - rgba[2] += int64(coeff) * int64(uint16(row[xi+4])<<8|uint16(row[xi+5])) - rgba[3] += int64(coeff) * int64(uint16(row[xi+6])<<8|uint16(row[xi+7])) - sum += int64(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := clampUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = clampUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = clampUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = clampUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func resizeGray(in *image.Gray, out *image.Gray, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[(x-newBounds.Min.X)*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - gray += int32(coeff) * int32(row[xi]) - sum += int32(coeff) - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x - newBounds.Min.X) - out.Pix[offset] = clampUint8(gray / sum) - } - } -} - -func resizeGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []int32, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray int64 - var sum int64 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 2 - case xi >= maxX: - xi = 2 * maxX - default: - xi = 0 - } - gray += int64(coeff) * int64(uint16(row[xi+0])<<8|uint16(row[xi+1])) - sum += int64(coeff) - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*2 - value := clampUint16(gray / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - } - } -} - -func resizeYCbCr(in *ycc, out *ycc, scale float64, coeffs []int16, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var p [3]int32 - var sum int32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - coeff := coeffs[ci+i] - if coeff != 0 { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 3 - case xi >= maxX: - xi = 3 * maxX - default: - xi = 0 - } - p[0] += int32(coeff) * int32(row[xi+0]) - p[1] += int32(coeff) * int32(row[xi+1]) - p[2] += int32(coeff) * int32(row[xi+2]) - sum += int32(coeff) - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*3 - out.Pix[xo+0] = clampUint8(p[0] / sum) - out.Pix[xo+1] = clampUint8(p[1] / sum) - out.Pix[xo+2] = clampUint8(p[2] / sum) - } - } -} - -func nearestYCbCr(in *ycc, out *ycc, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var p [3]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 3 - case xi >= maxX: - xi = 3 * maxX - default: - xi = 0 - } - p[0] += float32(row[xi+0]) - p[1] += float32(row[xi+1]) - p[2] += float32(row[xi+2]) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*3 - out.Pix[xo+0] = floatToUint8(p[0] / sum) - out.Pix[xo+1] = floatToUint8(p[1] / sum) - out.Pix[xo+2] = floatToUint8(p[2] / sum) - } - } -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/converter_test.go b/Godeps/_workspace/src/github.com/nfnt/resize/converter_test.go deleted file mode 100644 index 85639efc2..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/converter_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package resize - -import ( - "testing" -) - -func Test_ClampUint8(t *testing.T) { - var testData = []struct { - in int32 - expected uint8 - }{ - {0, 0}, - {255, 255}, - {128, 128}, - {-2, 0}, - {256, 255}, - } - for _, test := range testData { - actual := clampUint8(test.in) - if actual != test.expected { - t.Fail() - } - } -} - -func Test_ClampUint16(t *testing.T) { - var testData = []struct { - in int64 - expected uint16 - }{ - {0, 0}, - {65535, 65535}, - {128, 128}, - {-2, 0}, - {65536, 65535}, - } - for _, test := range testData { - actual := clampUint16(test.in) - if actual != test.expected { - t.Fail() - } - } -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/filters.go b/Godeps/_workspace/src/github.com/nfnt/resize/filters.go deleted file mode 100644 index 4ce04e389..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/filters.go +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "math" -) - -func nearest(in float64) float64 { - if in >= -0.5 && in < 0.5 { - return 1 - } - return 0 -} - -func linear(in float64) float64 { - in = math.Abs(in) - if in <= 1 { - return 1 - in - } - return 0 -} - -func cubic(in float64) float64 { - in = math.Abs(in) - if in <= 1 { - return in*in*(1.5*in-2.5) + 1.0 - } - if in <= 2 { - return in*(in*(2.5-0.5*in)-4.0) + 2.0 - } - return 0 -} - -func mitchellnetravali(in float64) float64 { - in = math.Abs(in) - if in <= 1 { - return (7.0*in*in*in - 12.0*in*in + 5.33333333333) * 0.16666666666 - } - if in <= 2 { - return (-2.33333333333*in*in*in + 12.0*in*in - 20.0*in + 10.6666666667) * 0.16666666666 - } - return 0 -} - -func sinc(x float64) float64 { - x = math.Abs(x) * math.Pi - if x >= 1.220703e-4 { - return math.Sin(x) / x - } - return 1 -} - -func lanczos2(in float64) float64 { - if in > -2 && in < 2 { - return sinc(in) * sinc(in*0.5) - } - return 0 -} - -func lanczos3(in float64) float64 { - if in > -3 && in < 3 { - return sinc(in) * sinc(in*0.3333333333333333) - } - return 0 -} - -// range [-256,256] -func createWeights8(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int16, []int, int) { - filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1)) - filterFactor := math.Min(1./(blur*scale), 1) - - coeffs := make([]int16, dy*filterLength) - start := make([]int, dy) - for y := 0; y < dy; y++ { - interpX := scale*(float64(y)+0.5) - 0.5 - start[y] = int(interpX) - filterLength/2 + 1 - interpX -= float64(start[y]) - for i := 0; i < filterLength; i++ { - in := (interpX - float64(i)) * filterFactor - coeffs[y*filterLength+i] = int16(kernel(in) * 256) - } - } - - return coeffs, start, filterLength -} - -// range [-65536,65536] -func createWeights16(dy, filterLength int, blur, scale float64, kernel func(float64) float64) ([]int32, []int, int) { - filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1)) - filterFactor := math.Min(1./(blur*scale), 1) - - coeffs := make([]int32, dy*filterLength) - start := make([]int, dy) - for y := 0; y < dy; y++ { - interpX := scale*(float64(y)+0.5) - 0.5 - start[y] = int(interpX) - filterLength/2 + 1 - interpX -= float64(start[y]) - for i := 0; i < filterLength; i++ { - in := (interpX - float64(i)) * filterFactor - coeffs[y*filterLength+i] = int32(kernel(in) * 65536) - } - } - - return coeffs, start, filterLength -} - -func createWeightsNearest(dy, filterLength int, blur, scale float64) ([]bool, []int, int) { - filterLength = filterLength * int(math.Max(math.Ceil(blur*scale), 1)) - filterFactor := math.Min(1./(blur*scale), 1) - - coeffs := make([]bool, dy*filterLength) - start := make([]int, dy) - for y := 0; y < dy; y++ { - interpX := scale*(float64(y)+0.5) - 0.5 - start[y] = int(interpX) - filterLength/2 + 1 - interpX -= float64(start[y]) - for i := 0; i < filterLength; i++ { - in := (interpX - float64(i)) * filterFactor - if in >= -0.5 && in < 0.5 { - coeffs[y*filterLength+i] = true - } else { - coeffs[y*filterLength+i] = false - } - } - } - - return coeffs, start, filterLength -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/nearest.go b/Godeps/_workspace/src/github.com/nfnt/resize/nearest.go deleted file mode 100644 index 888039d85..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/nearest.go +++ /dev/null @@ -1,318 +0,0 @@ -/* -Copyright (c) 2014, Charlie Vieth - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import "image" - -func floatToUint8(x float32) uint8 { - // Nearest-neighbor values are always - // positive no need to check lower-bound. - if x > 0xfe { - return 0xff - } - return uint8(x) -} - -func floatToUint16(x float32) uint16 { - if x > 0xfffe { - return 0xffff - } - return uint16(x) -} - -func nearestGeneric(in image.Image, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - r, g, b, a := in.At(xi+in.Bounds().Min.X, x+in.Bounds().Min.Y).RGBA() - rgba[0] += float32(r) - rgba[1] += float32(g) - rgba[2] += float32(b) - rgba[3] += float32(a) - sum++ - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := floatToUint16(rgba[0] / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - value = floatToUint16(rgba[1] / sum) - out.Pix[offset+2] = uint8(value >> 8) - out.Pix[offset+3] = uint8(value) - value = floatToUint16(rgba[2] / sum) - out.Pix[offset+4] = uint8(value >> 8) - out.Pix[offset+5] = uint8(value) - value = floatToUint16(rgba[3] / sum) - out.Pix[offset+6] = uint8(value >> 8) - out.Pix[offset+7] = uint8(value) - } - } -} - -func nearestRGBA(in *image.RGBA, out *image.RGBA, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - rgba[0] += float32(row[xi+0]) - rgba[1] += float32(row[xi+1]) - rgba[2] += float32(row[xi+2]) - rgba[3] += float32(row[xi+3]) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - out.Pix[xo+0] = floatToUint8(rgba[0] / sum) - out.Pix[xo+1] = floatToUint8(rgba[1] / sum) - out.Pix[xo+2] = floatToUint8(rgba[2] / sum) - out.Pix[xo+3] = floatToUint8(rgba[3] / sum) - } - } -} - -func nearestNRGBA(in *image.NRGBA, out *image.NRGBA, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 4 - case xi >= maxX: - xi = 4 * maxX - default: - xi = 0 - } - rgba[0] += float32(row[xi+0]) - rgba[1] += float32(row[xi+1]) - rgba[2] += float32(row[xi+2]) - rgba[3] += float32(row[xi+3]) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*4 - out.Pix[xo+0] = floatToUint8(rgba[0] / sum) - out.Pix[xo+1] = floatToUint8(rgba[1] / sum) - out.Pix[xo+2] = floatToUint8(rgba[2] / sum) - out.Pix[xo+3] = floatToUint8(rgba[3] / sum) - } - } -} - -func nearestRGBA64(in *image.RGBA64, out *image.RGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) - rgba[2] += float32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) - rgba[3] += float32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := floatToUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = floatToUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = floatToUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = floatToUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func nearestNRGBA64(in *image.NRGBA64, out *image.NRGBA64, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var rgba [4]float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 8 - case xi >= maxX: - xi = 8 * maxX - default: - xi = 0 - } - rgba[0] += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - rgba[1] += float32(uint16(row[xi+2])<<8 | uint16(row[xi+3])) - rgba[2] += float32(uint16(row[xi+4])<<8 | uint16(row[xi+5])) - rgba[3] += float32(uint16(row[xi+6])<<8 | uint16(row[xi+7])) - sum++ - } - } - - xo := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*8 - value := floatToUint16(rgba[0] / sum) - out.Pix[xo+0] = uint8(value >> 8) - out.Pix[xo+1] = uint8(value) - value = floatToUint16(rgba[1] / sum) - out.Pix[xo+2] = uint8(value >> 8) - out.Pix[xo+3] = uint8(value) - value = floatToUint16(rgba[2] / sum) - out.Pix[xo+4] = uint8(value >> 8) - out.Pix[xo+5] = uint8(value) - value = floatToUint16(rgba[3] / sum) - out.Pix[xo+6] = uint8(value >> 8) - out.Pix[xo+7] = uint8(value) - } - } -} - -func nearestGray(in *image.Gray, out *image.Gray, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case xi < 0: - xi = 0 - case xi >= maxX: - xi = maxX - } - gray += float32(row[xi]) - sum++ - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x - newBounds.Min.X) - out.Pix[offset] = floatToUint8(gray / sum) - } - } -} - -func nearestGray16(in *image.Gray16, out *image.Gray16, scale float64, coeffs []bool, offset []int, filterLength int) { - newBounds := out.Bounds() - maxX := in.Bounds().Dx() - 1 - - for x := newBounds.Min.X; x < newBounds.Max.X; x++ { - row := in.Pix[x*in.Stride:] - for y := newBounds.Min.Y; y < newBounds.Max.Y; y++ { - var gray float32 - var sum float32 - start := offset[y] - ci := y * filterLength - for i := 0; i < filterLength; i++ { - if coeffs[ci+i] { - xi := start + i - switch { - case uint(xi) < uint(maxX): - xi *= 2 - case xi >= maxX: - xi = 2 * maxX - default: - xi = 0 - } - gray += float32(uint16(row[xi+0])<<8 | uint16(row[xi+1])) - sum++ - } - } - - offset := (y-newBounds.Min.Y)*out.Stride + (x-newBounds.Min.X)*2 - value := floatToUint16(gray / sum) - out.Pix[offset+0] = uint8(value >> 8) - out.Pix[offset+1] = uint8(value) - } - } -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/nearest_test.go b/Godeps/_workspace/src/github.com/nfnt/resize/nearest_test.go deleted file mode 100644 index d4a76dda5..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/nearest_test.go +++ /dev/null @@ -1,57 +0,0 @@ -/* -Copyright (c) 2014, Charlie Vieth - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import "testing" - -func Test_FloatToUint8(t *testing.T) { - var testData = []struct { - in float32 - expected uint8 - }{ - {0, 0}, - {255, 255}, - {128, 128}, - {1, 1}, - {256, 255}, - } - for _, test := range testData { - actual := floatToUint8(test.in) - if actual != test.expected { - t.Fail() - } - } -} - -func Test_FloatToUint16(t *testing.T) { - var testData = []struct { - in float32 - expected uint16 - }{ - {0, 0}, - {65535, 65535}, - {128, 128}, - {1, 1}, - {65536, 65535}, - } - for _, test := range testData { - actual := floatToUint16(test.in) - if actual != test.expected { - t.Fail() - } - } -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/resize.go b/Godeps/_workspace/src/github.com/nfnt/resize/resize.go deleted file mode 100644 index c1672432e..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/resize.go +++ /dev/null @@ -1,614 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -// Package resize implements various image resizing methods. -// -// The package works with the Image interface described in the image package. -// Various interpolation methods are provided and multiple processors may be -// utilized in the computations. -// -// Example: -// imgResized := resize.Resize(1000, 0, imgOld, resize.MitchellNetravali) -package resize - -import ( - "image" - "runtime" - "sync" -) - -// An InterpolationFunction provides the parameters that describe an -// interpolation kernel. It returns the number of samples to take -// and the kernel function to use for sampling. -type InterpolationFunction int - -// InterpolationFunction constants -const ( - // Nearest-neighbor interpolation - NearestNeighbor InterpolationFunction = iota - // Bilinear interpolation - Bilinear - // Bicubic interpolation (with cubic hermite spline) - Bicubic - // Mitchell-Netravali interpolation - MitchellNetravali - // Lanczos interpolation (a=2) - Lanczos2 - // Lanczos interpolation (a=3) - Lanczos3 -) - -// kernal, returns an InterpolationFunctions taps and kernel. -func (i InterpolationFunction) kernel() (int, func(float64) float64) { - switch i { - case Bilinear: - return 2, linear - case Bicubic: - return 4, cubic - case MitchellNetravali: - return 4, mitchellnetravali - case Lanczos2: - return 4, lanczos2 - case Lanczos3: - return 6, lanczos3 - default: - // Default to NearestNeighbor. - return 2, nearest - } -} - -// values <1 will sharpen the image -var blur = 1.0 - -// Resize scales an image to new width and height using the interpolation function interp. -// A new image with the given dimensions will be returned. -// If one of the parameters width or height is set to 0, its size will be calculated so that -// the aspect ratio is that of the originating image. -// The resizing algorithm uses channels for parallel computation. -func Resize(width, height uint, img image.Image, interp InterpolationFunction) image.Image { - scaleX, scaleY := calcFactors(width, height, float64(img.Bounds().Dx()), float64(img.Bounds().Dy())) - if width == 0 { - width = uint(0.7 + float64(img.Bounds().Dx())/scaleX) - } - if height == 0 { - height = uint(0.7 + float64(img.Bounds().Dy())/scaleY) - } - - // Trivial case: return input image - if int(width) == img.Bounds().Dx() && int(height) == img.Bounds().Dy() { - return img - } - - if interp == NearestNeighbor { - return resizeNearest(width, height, scaleX, scaleY, img, interp) - } - - taps, kernel := interp.kernel() - cpus := runtime.GOMAXPROCS(0) - wg := sync.WaitGroup{} - - // Generic access to image.Image is slow in tight loops. - // The optimal access has to be determined from the concrete image type. - switch input := img.(type) { - case *image.RGBA: - // 8-bit precision - temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - resizeRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - resizeNRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA: - // 8-bit precision - temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - resizeNRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - resizeNRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - - case *image.YCbCr: - // 8-bit precision - // accessing the YCbCr arrays in a tight loop is slow. - // converting the image to ycc increases performance by 2x. - temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio) - result := newYCC(image.Rect(0, 0, int(width), int(height)), image.YCbCrSubsampleRatio444) - - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - in := imageYCbCrToYCC(input) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*ycc) - go func() { - defer wg.Done() - resizeYCbCr(in, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*ycc) - go func() { - defer wg.Done() - resizeYCbCr(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result.YCbCr() - case *image.RGBA64: - // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - resizeRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA64: - // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - resizeNRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray: - // 8-bit precision - temp := image.NewGray(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights8(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - resizeGray(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights8(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - resizeGray(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray16: - // 16-bit precision - temp := image.NewGray16(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray16(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - resizeGray16(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - resizeGray16(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - default: - // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeights16(temp.Bounds().Dy(), taps, blur, scaleX, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - resizeGeneric(img, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeights16(result.Bounds().Dy(), taps, blur, scaleY, kernel) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - resizeNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - } -} - -func resizeNearest(width, height uint, scaleX, scaleY float64, img image.Image, interp InterpolationFunction) image.Image { - taps, _ := interp.kernel() - cpus := runtime.GOMAXPROCS(0) - wg := sync.WaitGroup{} - - switch input := img.(type) { - case *image.RGBA: - // 8-bit precision - temp := image.NewRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - nearestRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA) - go func() { - defer wg.Done() - nearestRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA: - // 8-bit precision - temp := image.NewNRGBA(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - nearestNRGBA(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA) - go func() { - defer wg.Done() - nearestNRGBA(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.YCbCr: - // 8-bit precision - // accessing the YCbCr arrays in a tight loop is slow. - // converting the image to ycc increases performance by 2x. - temp := newYCC(image.Rect(0, 0, input.Bounds().Dy(), int(width)), input.SubsampleRatio) - result := newYCC(image.Rect(0, 0, int(width), int(height)), image.YCbCrSubsampleRatio444) - - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - in := imageYCbCrToYCC(input) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*ycc) - go func() { - defer wg.Done() - nearestYCbCr(in, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*ycc) - go func() { - defer wg.Done() - nearestYCbCr(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result.YCbCr() - case *image.RGBA64: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.NRGBA64: - // 16-bit precision - temp := image.NewNRGBA64(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewNRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - nearestNRGBA64(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.NRGBA64) - go func() { - defer wg.Done() - nearestNRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray: - // 8-bit precision - temp := image.NewGray(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - nearestGray(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray) - go func() { - defer wg.Done() - nearestGray(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - case *image.Gray16: - // 16-bit precision - temp := image.NewGray16(image.Rect(0, 0, input.Bounds().Dy(), int(width))) - result := image.NewGray16(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - nearestGray16(input, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.Gray16) - go func() { - defer wg.Done() - nearestGray16(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - default: - // 16-bit precision - temp := image.NewRGBA64(image.Rect(0, 0, img.Bounds().Dy(), int(width))) - result := image.NewRGBA64(image.Rect(0, 0, int(width), int(height))) - - // horizontal filter, results in transposed temporary image - coeffs, offset, filterLength := createWeightsNearest(temp.Bounds().Dy(), taps, blur, scaleX) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(temp, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestGeneric(img, slice, scaleX, coeffs, offset, filterLength) - }() - } - wg.Wait() - - // horizontal filter on transposed image, result is not transposed - coeffs, offset, filterLength = createWeightsNearest(result.Bounds().Dy(), taps, blur, scaleY) - wg.Add(cpus) - for i := 0; i < cpus; i++ { - slice := makeSlice(result, i, cpus).(*image.RGBA64) - go func() { - defer wg.Done() - nearestRGBA64(temp, slice, scaleY, coeffs, offset, filterLength) - }() - } - wg.Wait() - return result - } - -} - -// Calculates scaling factors using old and new image dimensions. -func calcFactors(width, height uint, oldWidth, oldHeight float64) (scaleX, scaleY float64) { - if width == 0 { - if height == 0 { - scaleX = 1.0 - scaleY = 1.0 - } else { - scaleY = oldHeight / float64(height) - scaleX = scaleY - } - } else { - scaleX = oldWidth / float64(width) - if height == 0 { - scaleY = scaleX - } else { - scaleY = oldHeight / float64(height) - } - } - return -} - -type imageWithSubImage interface { - image.Image - SubImage(image.Rectangle) image.Image -} - -func makeSlice(img imageWithSubImage, i, n int) image.Image { - return img.SubImage(image.Rect(img.Bounds().Min.X, img.Bounds().Min.Y+i*img.Bounds().Dy()/n, img.Bounds().Max.X, img.Bounds().Min.Y+(i+1)*img.Bounds().Dy()/n)) -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/resize_test.go b/Godeps/_workspace/src/github.com/nfnt/resize/resize_test.go deleted file mode 100644 index 6f6911316..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/resize_test.go +++ /dev/null @@ -1,314 +0,0 @@ -package resize - -import ( - "image" - "image/color" - "runtime" - "testing" -) - -var img = image.NewGray16(image.Rect(0, 0, 3, 3)) - -func init() { - runtime.GOMAXPROCS(runtime.NumCPU()) - img.Set(1, 1, color.White) -} - -func Test_Param1(t *testing.T) { - m := Resize(0, 0, img, NearestNeighbor) - if m.Bounds() != img.Bounds() { - t.Fail() - } -} - -func Test_Param2(t *testing.T) { - m := Resize(100, 0, img, NearestNeighbor) - if m.Bounds() != image.Rect(0, 0, 100, 100) { - t.Fail() - } -} - -func Test_ZeroImg(t *testing.T) { - zeroImg := image.NewGray16(image.Rect(0, 0, 0, 0)) - - m := Resize(0, 0, zeroImg, NearestNeighbor) - if m.Bounds() != zeroImg.Bounds() { - t.Fail() - } -} - -func Test_CorrectResize(t *testing.T) { - zeroImg := image.NewGray16(image.Rect(0, 0, 256, 256)) - - m := Resize(60, 0, zeroImg, NearestNeighbor) - if m.Bounds() != image.Rect(0, 0, 60, 60) { - t.Fail() - } -} - -func Test_SameColorWithRGBA(t *testing.T) { - img := image.NewRGBA(image.Rect(0, 0, 20, 20)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { - img.SetRGBA(x, y, color.RGBA{0x80, 0x80, 0x80, 0xFF}) - } - } - out := Resize(10, 10, img, Lanczos3) - for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { - for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA) - if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF { - t.Errorf("%+v", color) - } - } - } -} - -func Test_SameColorWithNRGBA(t *testing.T) { - img := image.NewNRGBA(image.Rect(0, 0, 20, 20)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { - img.SetNRGBA(x, y, color.NRGBA{0x80, 0x80, 0x80, 0xFF}) - } - } - out := Resize(10, 10, img, Lanczos3) - for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { - for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA) - if color.R != 0x80 || color.G != 0x80 || color.B != 0x80 || color.A != 0xFF { - t.Errorf("%+v", color) - } - } - } -} - -func Test_SameColorWithRGBA64(t *testing.T) { - img := image.NewRGBA64(image.Rect(0, 0, 20, 20)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { - img.SetRGBA64(x, y, color.RGBA64{0x8000, 0x8000, 0x8000, 0xFFFF}) - } - } - out := Resize(10, 10, img, Lanczos3) - for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { - for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA64) - if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF { - t.Errorf("%+v", color) - } - } - } -} - -func Test_SameColorWithNRGBA64(t *testing.T) { - img := image.NewNRGBA64(image.Rect(0, 0, 20, 20)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { - img.SetNRGBA64(x, y, color.NRGBA64{0x8000, 0x8000, 0x8000, 0xFFFF}) - } - } - out := Resize(10, 10, img, Lanczos3) - for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { - for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.NRGBA64) - if color.R != 0x8000 || color.G != 0x8000 || color.B != 0x8000 || color.A != 0xFFFF { - t.Errorf("%+v", color) - } - } - } -} - -func Test_SameColorWithGray(t *testing.T) { - img := image.NewGray(image.Rect(0, 0, 20, 20)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { - img.SetGray(x, y, color.Gray{0x80}) - } - } - out := Resize(10, 10, img, Lanczos3) - for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { - for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.Gray) - if color.Y != 0x80 { - t.Errorf("%+v", color) - } - } - } -} - -func Test_SameColorWithGray16(t *testing.T) { - img := image.NewGray16(image.Rect(0, 0, 20, 20)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { - img.SetGray16(x, y, color.Gray16{0x8000}) - } - } - out := Resize(10, 10, img, Lanczos3) - for y := out.Bounds().Min.Y; y < out.Bounds().Max.Y; y++ { - for x := out.Bounds().Min.X; x < out.Bounds().Max.X; x++ { - color := out.At(x, y).(color.Gray16) - if color.Y != 0x8000 { - t.Errorf("%+v", color) - } - } - } -} - -func Test_Bounds(t *testing.T) { - img := image.NewRGBA(image.Rect(20, 10, 200, 99)) - out := Resize(80, 80, img, Lanczos2) - out.At(0, 0) -} - -func Test_SameSizeReturnsOriginal(t *testing.T) { - img := image.NewRGBA(image.Rect(0, 0, 10, 10)) - out := Resize(0, 0, img, Lanczos2) - - if img != out { - t.Fail() - } - - out = Resize(10, 10, img, Lanczos2) - - if img != out { - t.Fail() - } -} - -func Test_PixelCoordinates(t *testing.T) { - checkers := image.NewGray(image.Rect(0, 0, 4, 4)) - checkers.Pix = []uint8{ - 255, 0, 255, 0, - 0, 255, 0, 255, - 255, 0, 255, 0, - 0, 255, 0, 255, - } - - resized := Resize(12, 12, checkers, NearestNeighbor).(*image.Gray) - - if resized.Pix[0] != 255 || resized.Pix[1] != 255 || resized.Pix[2] != 255 { - t.Fail() - } - - if resized.Pix[3] != 0 || resized.Pix[4] != 0 || resized.Pix[5] != 0 { - t.Fail() - } -} - -func Test_ResizeWithPremultipliedAlpha(t *testing.T) { - img := image.NewRGBA(image.Rect(0, 0, 1, 4)) - for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { - // 0x80 = 0.5 * 0xFF. - img.SetRGBA(0, y, color.RGBA{0x80, 0x80, 0x80, 0x80}) - } - - out := Resize(1, 2, img, MitchellNetravali) - - outputColor := out.At(0, 0).(color.NRGBA) - if outputColor.R != 0xFF { - t.Fail() - } -} - -const ( - // Use a small image size for benchmarks. We don't want memory performance - // to affect the benchmark results. - benchMaxX = 250 - benchMaxY = 250 - - // Resize values near the original size require increase the amount of time - // resize spends converting the image. - benchWidth = 200 - benchHeight = 200 -) - -func benchRGBA(b *testing.B, interp InterpolationFunction) { - m := image.NewRGBA(image.Rect(0, 0, benchMaxX, benchMaxY)) - // Initialize m's pixels to create a non-uniform image. - for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { - for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { - i := m.PixOffset(x, y) - m.Pix[i+0] = uint8(y + 4*x) - m.Pix[i+1] = uint8(y + 4*x) - m.Pix[i+2] = uint8(y + 4*x) - m.Pix[i+3] = uint8(4*y + x) - } - } - - var out image.Image - b.ResetTimer() - for i := 0; i < b.N; i++ { - out = Resize(benchWidth, benchHeight, m, interp) - } - out.At(0, 0) -} - -// The names of some interpolation functions are truncated so that the columns -// of 'go test -bench' line up. -func Benchmark_Nearest_RGBA(b *testing.B) { - benchRGBA(b, NearestNeighbor) -} - -func Benchmark_Bilinear_RGBA(b *testing.B) { - benchRGBA(b, Bilinear) -} - -func Benchmark_Bicubic_RGBA(b *testing.B) { - benchRGBA(b, Bicubic) -} - -func Benchmark_Mitchell_RGBA(b *testing.B) { - benchRGBA(b, MitchellNetravali) -} - -func Benchmark_Lanczos2_RGBA(b *testing.B) { - benchRGBA(b, Lanczos2) -} - -func Benchmark_Lanczos3_RGBA(b *testing.B) { - benchRGBA(b, Lanczos3) -} - -func benchYCbCr(b *testing.B, interp InterpolationFunction) { - m := image.NewYCbCr(image.Rect(0, 0, benchMaxX, benchMaxY), image.YCbCrSubsampleRatio422) - // Initialize m's pixels to create a non-uniform image. - for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { - for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { - yi := m.YOffset(x, y) - ci := m.COffset(x, y) - m.Y[yi] = uint8(16*y + x) - m.Cb[ci] = uint8(y + 16*x) - m.Cr[ci] = uint8(y + 16*x) - } - } - var out image.Image - b.ResetTimer() - for i := 0; i < b.N; i++ { - out = Resize(benchWidth, benchHeight, m, interp) - } - out.At(0, 0) -} - -func Benchmark_Nearest_YCC(b *testing.B) { - benchYCbCr(b, NearestNeighbor) -} - -func Benchmark_Bilinear_YCC(b *testing.B) { - benchYCbCr(b, Bilinear) -} - -func Benchmark_Bicubic_YCC(b *testing.B) { - benchYCbCr(b, Bicubic) -} - -func Benchmark_Mitchell_YCC(b *testing.B) { - benchYCbCr(b, MitchellNetravali) -} - -func Benchmark_Lanczos2_YCC(b *testing.B) { - benchYCbCr(b, Lanczos2) -} - -func Benchmark_Lanczos3_YCC(b *testing.B) { - benchYCbCr(b, Lanczos3) -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/thumbnail.go b/Godeps/_workspace/src/github.com/nfnt/resize/thumbnail.go deleted file mode 100644 index 9efc246be..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/thumbnail.go +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2012, Jan Schlicht - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "image" -) - -// Thumbnail will downscale provided image to max width and height preserving -// original aspect ratio and using the interpolation function interp. -// It will return original image, without processing it, if original sizes -// are already smaller than provided constraints. -func Thumbnail(maxWidth, maxHeight uint, img image.Image, interp InterpolationFunction) image.Image { - origBounds := img.Bounds() - origWidth := uint(origBounds.Dx()) - origHeight := uint(origBounds.Dy()) - newWidth, newHeight := origWidth, origHeight - - // Return original image if it have same or smaller size as constraints - if maxWidth >= origWidth && maxHeight >= origHeight { - return img - } - - // Preserve aspect ratio - if origWidth > maxWidth { - newHeight = uint(origHeight * maxWidth / origWidth) - if newHeight < 1 { - newHeight = 1 - } - newWidth = maxWidth - } - - if newHeight > maxHeight { - newWidth = uint(newWidth * maxHeight / newHeight) - if newWidth < 1 { - newWidth = 1 - } - newHeight = maxHeight - } - return Resize(newWidth, newHeight, img, interp) -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/thumbnail_test.go b/Godeps/_workspace/src/github.com/nfnt/resize/thumbnail_test.go deleted file mode 100644 index bd9875b2b..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/thumbnail_test.go +++ /dev/null @@ -1,47 +0,0 @@ -package resize - -import ( - "image" - "runtime" - "testing" -) - -func init() { - runtime.GOMAXPROCS(runtime.NumCPU()) -} - -var thumbnailTests = []struct { - origWidth int - origHeight int - maxWidth uint - maxHeight uint - expectedWidth uint - expectedHeight uint -}{ - {5, 5, 10, 10, 5, 5}, - {10, 10, 5, 5, 5, 5}, - {10, 50, 10, 10, 2, 10}, - {50, 10, 10, 10, 10, 2}, - {50, 100, 60, 90, 45, 90}, - {120, 100, 60, 90, 60, 50}, - {200, 250, 200, 150, 120, 150}, -} - -func TestThumbnail(t *testing.T) { - for i, tt := range thumbnailTests { - img := image.NewGray16(image.Rect(0, 0, tt.origWidth, tt.origHeight)) - - outImg := Thumbnail(tt.maxWidth, tt.maxHeight, img, NearestNeighbor) - - newWidth := uint(outImg.Bounds().Dx()) - newHeight := uint(outImg.Bounds().Dy()) - if newWidth != tt.expectedWidth || - newHeight != tt.expectedHeight { - t.Errorf("%d. Thumbnail(%v, %v, img, NearestNeighbor) => "+ - "width: %v, height: %v, want width: %v, height: %v", - i, tt.maxWidth, tt.maxHeight, - newWidth, newHeight, tt.expectedWidth, tt.expectedHeight, - ) - } - } -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/ycc.go b/Godeps/_workspace/src/github.com/nfnt/resize/ycc.go deleted file mode 100644 index 104159955..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/ycc.go +++ /dev/null @@ -1,227 +0,0 @@ -/* -Copyright (c) 2014, Charlie Vieth - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "image" - "image/color" -) - -// ycc is an in memory YCbCr image. The Y, Cb and Cr samples are held in a -// single slice to increase resizing performance. -type ycc struct { - // Pix holds the image's pixels, in Y, Cb, Cr order. The pixel at - // (x, y) starts at Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*3]. - Pix []uint8 - // Stride is the Pix stride (in bytes) between vertically adjacent pixels. - Stride int - // Rect is the image's bounds. - Rect image.Rectangle - // SubsampleRatio is the subsample ratio of the original YCbCr image. - SubsampleRatio image.YCbCrSubsampleRatio -} - -// PixOffset returns the index of the first element of Pix that corresponds to -// the pixel at (x, y). -func (p *ycc) PixOffset(x, y int) int { - return (y-p.Rect.Min.Y)*p.Stride + (x-p.Rect.Min.X)*3 -} - -func (p *ycc) Bounds() image.Rectangle { - return p.Rect -} - -func (p *ycc) ColorModel() color.Model { - return color.YCbCrModel -} - -func (p *ycc) At(x, y int) color.Color { - if !(image.Point{x, y}.In(p.Rect)) { - return color.YCbCr{} - } - i := p.PixOffset(x, y) - return color.YCbCr{ - p.Pix[i+0], - p.Pix[i+1], - p.Pix[i+2], - } -} - -func (p *ycc) Opaque() bool { - return true -} - -// SubImage returns an image representing the portion of the image p visible -// through r. The returned value shares pixels with the original image. -func (p *ycc) SubImage(r image.Rectangle) image.Image { - r = r.Intersect(p.Rect) - if r.Empty() { - return &ycc{SubsampleRatio: p.SubsampleRatio} - } - i := p.PixOffset(r.Min.X, r.Min.Y) - return &ycc{ - Pix: p.Pix[i:], - Stride: p.Stride, - Rect: r, - SubsampleRatio: p.SubsampleRatio, - } -} - -// newYCC returns a new ycc with the given bounds and subsample ratio. -func newYCC(r image.Rectangle, s image.YCbCrSubsampleRatio) *ycc { - w, h := r.Dx(), r.Dy() - buf := make([]uint8, 3*w*h) - return &ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: s} -} - -// YCbCr converts ycc to a YCbCr image with the same subsample ratio -// as the YCbCr image that ycc was generated from. -func (p *ycc) YCbCr() *image.YCbCr { - ycbcr := image.NewYCbCr(p.Rect, p.SubsampleRatio) - var off int - - switch ycbcr.SubsampleRatio { - case image.YCbCrSubsampleRatio422: - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - case image.YCbCrSubsampleRatio420: - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - case image.YCbCrSubsampleRatio440: - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y/2 - ycbcr.Rect.Min.Y/2) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - default: - // Default to 4:4:4 subsampling. - for y := ycbcr.Rect.Min.Y; y < ycbcr.Rect.Max.Y; y++ { - yy := (y - ycbcr.Rect.Min.Y) * ycbcr.YStride - cy := (y - ycbcr.Rect.Min.Y) * ycbcr.CStride - for x := ycbcr.Rect.Min.X; x < ycbcr.Rect.Max.X; x++ { - xx := (x - ycbcr.Rect.Min.X) - yi := yy + xx - ci := cy + xx - ycbcr.Y[yi] = p.Pix[off+0] - ycbcr.Cb[ci] = p.Pix[off+1] - ycbcr.Cr[ci] = p.Pix[off+2] - off += 3 - } - } - } - return ycbcr -} - -// imageYCbCrToYCC converts a YCbCr image to a ycc image for resizing. -func imageYCbCrToYCC(in *image.YCbCr) *ycc { - w, h := in.Rect.Dx(), in.Rect.Dy() - r := image.Rect(0, 0, w, h) - buf := make([]uint8, 3*w*h) - p := ycc{Pix: buf, Stride: 3 * w, Rect: r, SubsampleRatio: in.SubsampleRatio} - var off int - - switch in.SubsampleRatio { - case image.YCbCrSubsampleRatio422: - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y - in.Rect.Min.Y) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - case image.YCbCrSubsampleRatio420: - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y/2 - in.Rect.Min.Y/2) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx/2 - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - case image.YCbCrSubsampleRatio440: - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y/2 - in.Rect.Min.Y/2) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - default: - // Default to 4:4:4 subsampling. - for y := in.Rect.Min.Y; y < in.Rect.Max.Y; y++ { - yy := (y - in.Rect.Min.Y) * in.YStride - cy := (y - in.Rect.Min.Y) * in.CStride - for x := in.Rect.Min.X; x < in.Rect.Max.X; x++ { - xx := (x - in.Rect.Min.X) - yi := yy + xx - ci := cy + xx - p.Pix[off+0] = in.Y[yi] - p.Pix[off+1] = in.Cb[ci] - p.Pix[off+2] = in.Cr[ci] - off += 3 - } - } - } - return &p -} diff --git a/Godeps/_workspace/src/github.com/nfnt/resize/ycc_test.go b/Godeps/_workspace/src/github.com/nfnt/resize/ycc_test.go deleted file mode 100644 index 54d53d157..000000000 --- a/Godeps/_workspace/src/github.com/nfnt/resize/ycc_test.go +++ /dev/null @@ -1,214 +0,0 @@ -/* -Copyright (c) 2014, Charlie Vieth - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. -*/ - -package resize - -import ( - "image" - "image/color" - "testing" -) - -type Image interface { - image.Image - SubImage(image.Rectangle) image.Image -} - -func TestImage(t *testing.T) { - testImage := []Image{ - newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio420), - newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio422), - newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio440), - newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio444), - } - for _, m := range testImage { - if !image.Rect(0, 0, 10, 10).Eq(m.Bounds()) { - t.Errorf("%T: want bounds %v, got %v", - m, image.Rect(0, 0, 10, 10), m.Bounds()) - continue - } - m = m.SubImage(image.Rect(3, 2, 9, 8)).(Image) - if !image.Rect(3, 2, 9, 8).Eq(m.Bounds()) { - t.Errorf("%T: sub-image want bounds %v, got %v", - m, image.Rect(3, 2, 9, 8), m.Bounds()) - continue - } - // Test that taking an empty sub-image starting at a corner does not panic. - m.SubImage(image.Rect(0, 0, 0, 0)) - m.SubImage(image.Rect(10, 0, 10, 0)) - m.SubImage(image.Rect(0, 10, 0, 10)) - m.SubImage(image.Rect(10, 10, 10, 10)) - } -} - -func TestConvertYCbCr(t *testing.T) { - testImage := []Image{ - image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio420), - image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio422), - image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio440), - image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio444), - } - - for _, img := range testImage { - m := img.(*image.YCbCr) - for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { - for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { - yi := m.YOffset(x, y) - ci := m.COffset(x, y) - m.Y[yi] = uint8(16*y + x) - m.Cb[ci] = uint8(y + 16*x) - m.Cr[ci] = uint8(y + 16*x) - } - } - - // test conversion from YCbCr to ycc - yc := imageYCbCrToYCC(m) - for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { - for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { - ystride := 3 * (m.Rect.Max.X - m.Rect.Min.X) - xstride := 3 - yi := m.YOffset(x, y) - ci := m.COffset(x, y) - si := (y * ystride) + (x * xstride) - if m.Y[yi] != yc.Pix[si] { - t.Errorf("Err Y - found: %d expected: %d x: %d y: %d yi: %d si: %d", - m.Y[yi], yc.Pix[si], x, y, yi, si) - } - if m.Cb[ci] != yc.Pix[si+1] { - t.Errorf("Err Cb - found: %d expected: %d x: %d y: %d ci: %d si: %d", - m.Cb[ci], yc.Pix[si+1], x, y, ci, si+1) - } - if m.Cr[ci] != yc.Pix[si+2] { - t.Errorf("Err Cr - found: %d expected: %d x: %d y: %d ci: %d si: %d", - m.Cr[ci], yc.Pix[si+2], x, y, ci, si+2) - } - } - } - - // test conversion from ycc back to YCbCr - ym := yc.YCbCr() - for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { - for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { - yi := m.YOffset(x, y) - ci := m.COffset(x, y) - if m.Y[yi] != ym.Y[yi] { - t.Errorf("Err Y - found: %d expected: %d x: %d y: %d yi: %d", - m.Y[yi], ym.Y[yi], x, y, yi) - } - if m.Cb[ci] != ym.Cb[ci] { - t.Errorf("Err Cb - found: %d expected: %d x: %d y: %d ci: %d", - m.Cb[ci], ym.Cb[ci], x, y, ci) - } - if m.Cr[ci] != ym.Cr[ci] { - t.Errorf("Err Cr - found: %d expected: %d x: %d y: %d ci: %d", - m.Cr[ci], ym.Cr[ci], x, y, ci) - } - } - } - } -} - -func TestYCbCr(t *testing.T) { - rects := []image.Rectangle{ - image.Rect(0, 0, 16, 16), - image.Rect(1, 0, 16, 16), - image.Rect(0, 1, 16, 16), - image.Rect(1, 1, 16, 16), - image.Rect(1, 1, 15, 16), - image.Rect(1, 1, 16, 15), - image.Rect(1, 1, 15, 15), - image.Rect(2, 3, 14, 15), - image.Rect(7, 0, 7, 16), - image.Rect(0, 8, 16, 8), - image.Rect(0, 0, 10, 11), - image.Rect(5, 6, 16, 16), - image.Rect(7, 7, 8, 8), - image.Rect(7, 8, 8, 9), - image.Rect(8, 7, 9, 8), - image.Rect(8, 8, 9, 9), - image.Rect(7, 7, 17, 17), - image.Rect(8, 8, 17, 17), - image.Rect(9, 9, 17, 17), - image.Rect(10, 10, 17, 17), - } - subsampleRatios := []image.YCbCrSubsampleRatio{ - image.YCbCrSubsampleRatio444, - image.YCbCrSubsampleRatio422, - image.YCbCrSubsampleRatio420, - image.YCbCrSubsampleRatio440, - } - deltas := []image.Point{ - image.Pt(0, 0), - image.Pt(1000, 1001), - image.Pt(5001, -400), - image.Pt(-701, -801), - } - for _, r := range rects { - for _, subsampleRatio := range subsampleRatios { - for _, delta := range deltas { - testYCbCr(t, r, subsampleRatio, delta) - } - } - if testing.Short() { - break - } - } -} - -func testYCbCr(t *testing.T, r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio, delta image.Point) { - // Create a YCbCr image m, whose bounds are r translated by (delta.X, delta.Y). - r1 := r.Add(delta) - img := image.NewYCbCr(r1, subsampleRatio) - - // Initialize img's pixels. For 422 and 420 subsampling, some of the Cb and Cr elements - // will be set multiple times. That's OK. We just want to avoid a uniform image. - for y := r1.Min.Y; y < r1.Max.Y; y++ { - for x := r1.Min.X; x < r1.Max.X; x++ { - yi := img.YOffset(x, y) - ci := img.COffset(x, y) - img.Y[yi] = uint8(16*y + x) - img.Cb[ci] = uint8(y + 16*x) - img.Cr[ci] = uint8(y + 16*x) - } - } - - m := imageYCbCrToYCC(img) - - // Make various sub-images of m. - for y0 := delta.Y + 3; y0 < delta.Y+7; y0++ { - for y1 := delta.Y + 8; y1 < delta.Y+13; y1++ { - for x0 := delta.X + 3; x0 < delta.X+7; x0++ { - for x1 := delta.X + 8; x1 < delta.X+13; x1++ { - subRect := image.Rect(x0, y0, x1, y1) - sub := m.SubImage(subRect).(*ycc) - - // For each point in the sub-image's bounds, check that m.At(x, y) equals sub.At(x, y). - for y := sub.Rect.Min.Y; y < sub.Rect.Max.Y; y++ { - for x := sub.Rect.Min.X; x < sub.Rect.Max.X; x++ { - color0 := m.At(x, y).(color.YCbCr) - color1 := sub.At(x, y).(color.YCbCr) - if color0 != color1 { - t.Errorf("r=%v, subsampleRatio=%v, delta=%v, x=%d, y=%d, color0=%v, color1=%v", - r, subsampleRatio, delta, x, y, color0, color1) - return - } - } - } - } - } - } - } -} -- cgit v1.2.3-1-g7c22