From d83be6df2d8b0e2fef4cb6866cfdb6434bbef5c4 Mon Sep 17 00:00:00 2001 From: hmhealey Date: Thu, 17 Sep 2015 11:08:47 -0400 Subject: PLT-173 Added graphics-go and goexif libraries for image manipulation --- .../p/graphics-go/graphics/affine.go | 174 +++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go (limited to 'Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go') 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 new file mode 100644 index 000000000..0ac2ec9da --- /dev/null +++ b/Godeps/_workspace/src/code.google.com/p/graphics-go/graphics/affine.go @@ -0,0 +1,174 @@ +// 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) +} -- cgit v1.2.3-1-g7c22