| // Copyright 2014 The 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 portable |
| |
| import ( |
| "image" |
| "image/color" |
| "testing" |
| ) |
| |
| type interpTest struct { |
| desc string |
| src []uint8 |
| srcWidth int |
| x, y float32 |
| 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 TestBilinear(t *testing.T) { |
| for _, p := range interpTests { |
| src := p.newSrc() |
| |
| c0 := bilinearGeneral(src, p.x, p.y) |
| c0R, c0G, c0B, c0A := c0.RGBA() |
| r := uint8(c0R >> 8) |
| g := uint8(c0G >> 8) |
| b := uint8(c0B >> 8) |
| a := uint8(c0A >> 8) |
| |
| if r != g || r != b || a != 0xff { |
| t.Errorf("expect channels to match, got %v", c0) |
| continue |
| } |
| if r != p.expect { |
| t.Errorf("%s: got 0x%02x want 0x%02x", p.desc, r, p.expect) |
| continue |
| } |
| |
| // fast path for *image.RGBA |
| c1 := bilinearRGBA(src, p.x, p.y) |
| if r != c1.R || g != c1.G || b != c1.B || a != c1.A { |
| t.Errorf("%s: RGBA fast path mismatch got %v want %v", p.desc, c1, c0) |
| continue |
| } |
| |
| // fast path for *image.Alpha |
| alpha := image.NewAlpha(src.Bounds()) |
| for y := src.Bounds().Min.Y; y < src.Bounds().Max.Y; y++ { |
| for x := src.Bounds().Min.X; x < src.Bounds().Max.X; x++ { |
| r, _, _, _ := src.At(x, y).RGBA() |
| alpha.Set(x, y, color.Alpha{A: uint8(r >> 8)}) |
| } |
| } |
| c2 := bilinearAlpha(alpha, p.x, p.y) |
| if c2.A != r { |
| t.Errorf("%s: Alpha fast path mismatch got %v want %v", p.desc, c2, c0) |
| 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 float32 |
| want uint32 |
| }{ |
| {1, 1, 0x11}, |
| {3, 1, 0x22}, |
| {1, 3, 0x33}, |
| {3, 3, 0x44}, |
| {2, 2, 0x2b}, |
| } |
| |
| for _, p := range tests { |
| r, _, _, _ := bilinear(src1, p.x, p.y).RGBA() |
| r >>= 8 |
| if r != p.want { |
| t.Errorf("(%.0f, %.0f): got 0x%02x want 0x%02x", p.x, p.y, r, p.want) |
| } |
| } |
| } |