1// +build go1.5 2 3/* 4Copyright (c) 2014, Charlie Vieth <charlie.vieth@gmail.com> 5 6Permission to use, copy, modify, and/or distribute this software for any purpose 7with or without fee is hereby granted, provided that the above copyright notice 8and this permission notice appear in all copies. 9 10THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 11REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 12FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 13INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 14OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 15TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 16THIS SOFTWARE. 17*/ 18 19package resize 20 21import ( 22 "image" 23 "image/color" 24 "testing" 25) 26 27type Image interface { 28 image.Image 29 SubImage(image.Rectangle) image.Image 30} 31 32func TestImage(t *testing.T) { 33 testImage := []Image{ 34 newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio420), 35 newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio422), 36 newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio440), 37 newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio444), 38 newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio411), 39 newYCC(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio410), 40 } 41 for _, m := range testImage { 42 if !image.Rect(0, 0, 10, 10).Eq(m.Bounds()) { 43 t.Errorf("%T: want bounds %v, got %v", 44 m, image.Rect(0, 0, 10, 10), m.Bounds()) 45 continue 46 } 47 m = m.SubImage(image.Rect(3, 2, 9, 8)).(Image) 48 if !image.Rect(3, 2, 9, 8).Eq(m.Bounds()) { 49 t.Errorf("%T: sub-image want bounds %v, got %v", 50 m, image.Rect(3, 2, 9, 8), m.Bounds()) 51 continue 52 } 53 // Test that taking an empty sub-image starting at a corner does not panic. 54 m.SubImage(image.Rect(0, 0, 0, 0)) 55 m.SubImage(image.Rect(10, 0, 10, 0)) 56 m.SubImage(image.Rect(0, 10, 0, 10)) 57 m.SubImage(image.Rect(10, 10, 10, 10)) 58 } 59} 60 61func TestConvertYCbCr(t *testing.T) { 62 testImage := []Image{ 63 image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio420), 64 image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio422), 65 image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio440), 66 image.NewYCbCr(image.Rect(0, 0, 50, 50), image.YCbCrSubsampleRatio444), 67 image.NewYCbCr(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio411), 68 image.NewYCbCr(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio410), 69 } 70 for _, img := range testImage { 71 m := img.(*image.YCbCr) 72 for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { 73 for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { 74 yi := m.YOffset(x, y) 75 ci := m.COffset(x, y) 76 m.Y[yi] = uint8(16*y + x) 77 m.Cb[ci] = uint8(y + 16*x) 78 m.Cr[ci] = uint8(y + 16*x) 79 } 80 } 81 82 // test conversion from YCbCr to ycc 83 yc := imageYCbCrToYCC(m) 84 for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { 85 for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { 86 ystride := 3 * (m.Rect.Max.X - m.Rect.Min.X) 87 xstride := 3 88 yi := m.YOffset(x, y) 89 ci := m.COffset(x, y) 90 si := (y * ystride) + (x * xstride) 91 if m.Y[yi] != yc.Pix[si] { 92 t.Errorf("Err Y - found: %d expected: %d x: %d y: %d yi: %d si: %d", 93 m.Y[yi], yc.Pix[si], x, y, yi, si) 94 } 95 if m.Cb[ci] != yc.Pix[si+1] { 96 t.Errorf("Err Cb - found: %d expected: %d x: %d y: %d ci: %d si: %d", 97 m.Cb[ci], yc.Pix[si+1], x, y, ci, si+1) 98 } 99 if m.Cr[ci] != yc.Pix[si+2] { 100 t.Errorf("Err Cr - found: %d expected: %d x: %d y: %d ci: %d si: %d", 101 m.Cr[ci], yc.Pix[si+2], x, y, ci, si+2) 102 } 103 } 104 } 105 106 // test conversion from ycc back to YCbCr 107 ym := yc.YCbCr() 108 for y := m.Rect.Min.Y; y < m.Rect.Max.Y; y++ { 109 for x := m.Rect.Min.X; x < m.Rect.Max.X; x++ { 110 yi := m.YOffset(x, y) 111 ci := m.COffset(x, y) 112 if m.Y[yi] != ym.Y[yi] { 113 t.Errorf("Err Y - found: %d expected: %d x: %d y: %d yi: %d", 114 m.Y[yi], ym.Y[yi], x, y, yi) 115 } 116 if m.Cb[ci] != ym.Cb[ci] { 117 t.Errorf("Err Cb - found: %d expected: %d x: %d y: %d ci: %d", 118 m.Cb[ci], ym.Cb[ci], x, y, ci) 119 } 120 if m.Cr[ci] != ym.Cr[ci] { 121 t.Errorf("Err Cr - found: %d expected: %d x: %d y: %d ci: %d", 122 m.Cr[ci], ym.Cr[ci], x, y, ci) 123 } 124 } 125 } 126 } 127} 128 129func TestYCbCr(t *testing.T) { 130 rects := []image.Rectangle{ 131 image.Rect(0, 0, 16, 16), 132 image.Rect(1, 0, 16, 16), 133 image.Rect(0, 1, 16, 16), 134 image.Rect(1, 1, 16, 16), 135 image.Rect(1, 1, 15, 16), 136 image.Rect(1, 1, 16, 15), 137 image.Rect(1, 1, 15, 15), 138 image.Rect(2, 3, 14, 15), 139 image.Rect(7, 0, 7, 16), 140 image.Rect(0, 8, 16, 8), 141 image.Rect(0, 0, 10, 11), 142 image.Rect(5, 6, 16, 16), 143 image.Rect(7, 7, 8, 8), 144 image.Rect(7, 8, 8, 9), 145 image.Rect(8, 7, 9, 8), 146 image.Rect(8, 8, 9, 9), 147 image.Rect(7, 7, 17, 17), 148 image.Rect(8, 8, 17, 17), 149 image.Rect(9, 9, 17, 17), 150 image.Rect(10, 10, 17, 17), 151 } 152 subsampleRatios := []image.YCbCrSubsampleRatio{ 153 image.YCbCrSubsampleRatio444, 154 image.YCbCrSubsampleRatio422, 155 image.YCbCrSubsampleRatio420, 156 image.YCbCrSubsampleRatio440, 157 } 158 deltas := []image.Point{ 159 image.Pt(0, 0), 160 image.Pt(1000, 1001), 161 image.Pt(5001, -400), 162 image.Pt(-701, -801), 163 } 164 for _, r := range rects { 165 for _, subsampleRatio := range subsampleRatios { 166 for _, delta := range deltas { 167 testYCbCr(t, r, subsampleRatio, delta) 168 } 169 } 170 if testing.Short() { 171 break 172 } 173 } 174} 175 176func testYCbCr(t *testing.T, r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio, delta image.Point) { 177 // Create a YCbCr image m, whose bounds are r translated by (delta.X, delta.Y). 178 r1 := r.Add(delta) 179 img := image.NewYCbCr(r1, subsampleRatio) 180 181 // Initialize img's pixels. For 422 and 420 subsampling, some of the Cb and Cr elements 182 // will be set multiple times. That's OK. We just want to avoid a uniform image. 183 for y := r1.Min.Y; y < r1.Max.Y; y++ { 184 for x := r1.Min.X; x < r1.Max.X; x++ { 185 yi := img.YOffset(x, y) 186 ci := img.COffset(x, y) 187 img.Y[yi] = uint8(16*y + x) 188 img.Cb[ci] = uint8(y + 16*x) 189 img.Cr[ci] = uint8(y + 16*x) 190 } 191 } 192 193 m := imageYCbCrToYCC(img) 194 195 // Make various sub-images of m. 196 for y0 := delta.Y + 3; y0 < delta.Y+7; y0++ { 197 for y1 := delta.Y + 8; y1 < delta.Y+13; y1++ { 198 for x0 := delta.X + 3; x0 < delta.X+7; x0++ { 199 for x1 := delta.X + 8; x1 < delta.X+13; x1++ { 200 subRect := image.Rect(x0, y0, x1, y1) 201 sub := m.SubImage(subRect).(*ycc) 202 203 // For each point in the sub-image's bounds, check that m.At(x, y) equals sub.At(x, y). 204 for y := sub.Rect.Min.Y; y < sub.Rect.Max.Y; y++ { 205 for x := sub.Rect.Min.X; x < sub.Rect.Max.X; x++ { 206 color0 := m.At(x, y).(color.YCbCr) 207 color1 := sub.At(x, y).(color.YCbCr) 208 if color0 != color1 { 209 t.Errorf("r=%v, subsampleRatio=%v, delta=%v, x=%d, y=%d, color0=%v, color1=%v", 210 r, subsampleRatio, delta, x, y, color0, color1) 211 return 212 } 213 } 214 } 215 } 216 } 217 } 218 } 219} 220