github.com/cellofellow/gopkg@v0.0.0-20140722061823-eec0544a62ad/image/raw/all_test.go (about) 1 // Copyright 2014 <chaishushan{AT}gmail.com>. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package raw 6 7 import ( 8 "fmt" 9 "image" 10 "image/color" 11 "image/draw" 12 "reflect" 13 "testing" 14 15 image_ext "github.com/chai2010/gopkg/image" 16 color_ext "github.com/chai2010/gopkg/image/color" 17 ) 18 19 type tTester struct { 20 Image draw.Image 21 Model color.Model 22 DataType reflect.Kind 23 Channels int 24 } 25 26 var tTesterList = []tTester{ 27 // Gray/Gray16/Gray32f 28 tTester{ 29 Image: image.NewGray(image.Rect(0, 0, 10, 10)), 30 Model: color.GrayModel, 31 DataType: reflect.Uint8, 32 Channels: 1, 33 }, 34 tTester{ 35 Image: image.NewGray16(image.Rect(0, 0, 10, 10)), 36 Model: color.Gray16Model, 37 DataType: reflect.Uint16, 38 Channels: 1, 39 }, 40 tTester{ 41 Image: image_ext.NewGray32f(image.Rect(0, 0, 10, 10)), 42 Model: color_ext.Gray32fModel, 43 DataType: reflect.Float32, 44 Channels: 1, 45 }, 46 // RGB/RGB48/RGB96f 47 tTester{ 48 Image: image_ext.NewRGB(image.Rect(0, 0, 10, 10)), 49 Model: color_ext.RGBModel, 50 DataType: reflect.Uint8, 51 Channels: 3, 52 }, 53 tTester{ 54 Image: image_ext.NewRGB48(image.Rect(0, 0, 10, 10)), 55 Model: color_ext.RGB48Model, 56 DataType: reflect.Uint16, 57 Channels: 3, 58 }, 59 tTester{ 60 Image: image_ext.NewRGB96f(image.Rect(0, 0, 10, 10)), 61 Model: color_ext.RGB96fModel, 62 DataType: reflect.Float32, 63 Channels: 3, 64 }, 65 // RGBA/RGBA48/RGBA128f 66 tTester{ 67 Image: image.NewRGBA(image.Rect(0, 0, 10, 10)), 68 Model: color.RGBAModel, 69 DataType: reflect.Uint8, 70 Channels: 4, 71 }, 72 tTester{ 73 Image: image.NewRGBA64(image.Rect(0, 0, 10, 10)), 74 Model: color.RGBA64Model, 75 DataType: reflect.Uint16, 76 Channels: 4, 77 }, 78 tTester{ 79 Image: image_ext.NewRGBA128f(image.Rect(0, 0, 10, 10)), 80 Model: color_ext.RGBA128fModel, 81 DataType: reflect.Float32, 82 Channels: 4, 83 }, 84 } 85 86 func TestEncodeAndDecode(t *testing.T) { 87 for _, v := range tTesterList { 88 v.Image.Set(6, 3, color.RGBA{0xAA, 0xBB, 0xCC, 0xDD}) 89 } 90 for i, v := range tTesterList { 91 encoder := Encoder{v.Channels, v.DataType} 92 decoder := Decoder{v.Channels, v.DataType, v.Image.Bounds().Dx(), v.Image.Bounds().Dy()} 93 94 data, err := encoder.Encode(v.Image, nil) 95 if err != nil { 96 t.Fatalf("%d: %v", i, err) 97 } 98 99 m, err := decoder.Decode(data, nil) 100 if err != nil { 101 t.Fatalf("%d: %v", i, err) 102 } 103 104 err = tCompareImage(v.Image, v.Channels, v.Model, m) 105 if err != nil { 106 t.Fatalf("%d: %v", i, err) 107 } 108 } 109 } 110 111 func TestEncodeAndDecode_YCbCr2Gray(t *testing.T) { 112 yuv := tNewYCbCr(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio420) 113 tSetYCbCr(yuv, 6, 3, color.Gray{0xAB}) 114 115 encoder := Encoder{1, reflect.Uint8} 116 decoder := Decoder{1, reflect.Uint8, yuv.Bounds().Dx(), yuv.Bounds().Dy()} 117 118 data, err := encoder.Encode(yuv, nil) 119 if err != nil { 120 t.Fatalf("%v", err) 121 } 122 m0, err := decoder.Decode(data, nil) 123 if err != nil { 124 t.Fatalf("%v", err) 125 } 126 127 m1, err := decoder.DecodeImage(yuv, nil) 128 if err != nil { 129 t.Fatalf("%v", err) 130 } 131 132 // check color 133 if m0.ColorModel() != color.GrayModel { 134 t.Fatalf("want %v, got %v", color.GrayModel, m0.ColorModel()) 135 } 136 if m1.ColorModel() != color.GrayModel { 137 t.Fatalf("want %v, got %v", color.GrayModel, m1.ColorModel()) 138 } 139 140 // check size 141 if m0.Bounds() != yuv.Bounds() { 142 t.Fatalf("want %v, got %v", yuv.Bounds(), m0.Bounds()) 143 } 144 if m1.Bounds() != yuv.Bounds() { 145 t.Fatalf("want %v, got %v", yuv.Bounds(), m1.Bounds()) 146 } 147 148 // check data 149 b := yuv.Bounds() 150 for y := b.Min.Y; y < b.Max.Y; y++ { 151 for x := b.Min.X; x < b.Max.X; x++ { 152 gray := color.GrayModel.Convert(yuv.At(x, y)).(color.Gray) 153 c0 := m0.At(x, y).(color.Gray) 154 c1 := m1.At(x, y).(color.Gray) 155 if c0 != gray { 156 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, gray, c0) 157 } 158 if c1 != gray { 159 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, gray, c1) 160 } 161 } 162 } 163 } 164 165 func TestEncodeAndDecode_YCbCr2RGB(t *testing.T) { 166 yuv := tNewYCbCr(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio420) 167 tSetYCbCr(yuv, 6, 3, color.RGBA{0xAA, 0xBB, 0xCC, 0xDD}) 168 169 encoder := Encoder{3, reflect.Uint8} 170 decoder := Decoder{3, reflect.Uint8, yuv.Bounds().Dx(), yuv.Bounds().Dy()} 171 172 data, err := encoder.Encode(yuv, nil) 173 if err != nil { 174 t.Fatalf("%v", err) 175 } 176 m0, err := decoder.Decode(data, nil) 177 if err != nil { 178 t.Fatalf("%v", err) 179 } 180 181 m1, err := decoder.DecodeImage(yuv, nil) 182 if err != nil { 183 t.Fatalf("%v", err) 184 } 185 186 // check color 187 if m0.ColorModel() != color_ext.RGBModel { 188 t.Fatalf("want %v, got %v", color_ext.RGBModel, m0.ColorModel()) 189 } 190 if m1.ColorModel() != color_ext.RGBModel { 191 t.Fatalf("want %v, got %v", color_ext.RGBModel, m1.ColorModel()) 192 } 193 194 // check size 195 if m0.Bounds() != yuv.Bounds() { 196 t.Fatalf("want %v, got %v", yuv.Bounds(), m0.Bounds()) 197 } 198 if m1.Bounds() != yuv.Bounds() { 199 t.Fatalf("want %v, got %v", yuv.Bounds(), m1.Bounds()) 200 } 201 202 // check data 203 b := yuv.Bounds() 204 for y := b.Min.Y; y < b.Max.Y; y++ { 205 for x := b.Min.X; x < b.Max.X; x++ { 206 rgb := color_ext.RGBModel.Convert(yuv.At(x, y)).(color_ext.RGB) 207 c0 := m0.At(x, y).(color_ext.RGB) 208 c1 := m1.At(x, y).(color_ext.RGB) 209 if c0 != rgb { 210 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, rgb, c0) 211 } 212 if c1 != rgb { 213 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, rgb, c1) 214 } 215 } 216 } 217 } 218 219 func TestEncodeAndDecode_YCbCr2RGBA(t *testing.T) { 220 yuv := tNewYCbCr(image.Rect(0, 0, 10, 10), image.YCbCrSubsampleRatio420) 221 tSetYCbCr(yuv, 6, 3, color.RGBA{0xAA, 0xBB, 0xCC, 0xDD}) 222 223 encoder := Encoder{4, reflect.Uint8} 224 decoder := Decoder{4, reflect.Uint8, yuv.Bounds().Dx(), yuv.Bounds().Dy()} 225 226 data, err := encoder.Encode(yuv, nil) 227 if err != nil { 228 t.Fatalf("%v", err) 229 } 230 m0, err := decoder.Decode(data, nil) 231 if err != nil { 232 t.Fatalf("%v", err) 233 } 234 235 m1, err := decoder.DecodeImage(yuv, nil) 236 if err != nil { 237 t.Fatalf("%v", err) 238 } 239 240 // check color 241 if m0.ColorModel() != color.RGBAModel { 242 t.Fatalf("want %v, got %v", color.RGBAModel, m0.ColorModel()) 243 } 244 if m1.ColorModel() != color.RGBAModel { 245 t.Fatalf("want %v, got %v", color.RGBAModel, m1.ColorModel()) 246 } 247 248 // check size 249 if m0.Bounds() != yuv.Bounds() { 250 t.Fatalf("want %v, got %v", yuv.Bounds(), m0.Bounds()) 251 } 252 if m1.Bounds() != yuv.Bounds() { 253 t.Fatalf("want %v, got %v", yuv.Bounds(), m1.Bounds()) 254 } 255 256 // check data 257 b := yuv.Bounds() 258 for y := b.Min.Y; y < b.Max.Y; y++ { 259 for x := b.Min.X; x < b.Max.X; x++ { 260 rgba := color.RGBAModel.Convert(yuv.At(x, y)).(color.RGBA) 261 c0 := m0.At(x, y).(color.RGBA) 262 c1 := m1.At(x, y).(color.RGBA) 263 if c0 != rgba { 264 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, rgba, c0) 265 } 266 if c1 != rgba { 267 t.Fatalf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, rgba, c1) 268 } 269 } 270 } 271 } 272 273 func tCompareImage(img0 image.Image, channels int, model color.Model, img1 image.Image) error { 274 if img1.ColorModel() != model { 275 return fmt.Errorf("img1 wrong image model: want %v, got %v", model, img1.ColorModel()) 276 } 277 if !img1.Bounds().Eq(img0.Bounds()) { 278 return fmt.Errorf("wrong image size: want %v, got %v", img0.Bounds(), img1.Bounds()) 279 } 280 281 switch img0.ColorModel() { 282 case color_ext.Gray32fModel: 283 b := img1.Bounds() 284 img0 := img0.(*image_ext.Gray32f) 285 img1 := img1.(*image_ext.Gray32f) 286 for y := b.Min.Y; y < b.Max.Y; y++ { 287 for x := b.Min.X; x < b.Max.X; x++ { 288 c0 := img0.Gray32fAt(x, y) 289 c1 := img1.Gray32fAt(x, y) 290 if c0 != c1 { 291 return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 292 } 293 } 294 } 295 case color_ext.RGB96fModel: 296 b := img1.Bounds() 297 img0 := img0.(*image_ext.RGB96f) 298 img1 := img1.(*image_ext.RGB96f) 299 for y := b.Min.Y; y < b.Max.Y; y++ { 300 for x := b.Min.X; x < b.Max.X; x++ { 301 c0 := img0.RGB96fAt(x, y) 302 c1 := img1.RGB96fAt(x, y) 303 if c0 != c1 { 304 return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 305 } 306 } 307 } 308 case color_ext.RGBA128fModel: 309 b := img1.Bounds() 310 img0 := img0.(*image_ext.RGBA128f) 311 img1 := img1.(*image_ext.RGBA128f) 312 for y := b.Min.Y; y < b.Max.Y; y++ { 313 for x := b.Min.X; x < b.Max.X; x++ { 314 c0 := img0.RGBA128fAt(x, y) 315 c1 := img1.RGBA128fAt(x, y) 316 if channels == 3 { 317 c0.A, c1.A = 0, 0 318 } 319 if c0 != c1 { 320 return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 321 } 322 } 323 } 324 default: 325 b := img1.Bounds() 326 for y := b.Min.Y; y < b.Max.Y; y++ { 327 for x := b.Min.X; x < b.Max.X; x++ { 328 switch channels { 329 case 4: 330 c0 := img0.At(x, y) 331 c1 := img1.At(x, y) 332 r0, g0, b0, a0 := c0.RGBA() 333 r1, g1, b1, a1 := c1.RGBA() 334 if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 { 335 return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 336 } 337 case 3: 338 c0 := img0.At(x, y) 339 c1 := img1.At(x, y) 340 r0, g0, b0, _ := c0.RGBA() 341 r1, g1, b1, _ := c1.RGBA() 342 if r0 != r1 || g0 != g1 || b0 != b1 { 343 return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 344 } 345 case 1: 346 c0 := color.GrayModel.Convert(img0.At(x, y)).(color.Gray) 347 c1 := color.GrayModel.Convert(img1.At(x, y)).(color.Gray) 348 if c0 != c1 { 349 return fmt.Errorf("pixel at (%d, %d) has wrong color: want %v, got %v", x, y, c0, c1) 350 } 351 } 352 } 353 } 354 } 355 return nil 356 } 357 358 // new a zero YCbCr 359 func tNewYCbCr(r image.Rectangle, subsampleRatio image.YCbCrSubsampleRatio) *image.YCbCr { 360 m := image.NewYCbCr(r, subsampleRatio) 361 for i := 0; i < len(m.Cb); i++ { 362 m.Cb[i] = tZeroYCbCr.Cb 363 } 364 for i := 0; i < len(m.Cr); i++ { 365 m.Cr[i] = tZeroYCbCr.Cr 366 } 367 return m 368 } 369 370 // YCbCr.Set 371 func tSetYCbCr(p *image.YCbCr, x, y int, c color.Color) { 372 if !(image.Point{x, y}.In(p.Rect)) { 373 return 374 } 375 yi := p.YOffset(x, y) 376 ci := p.COffset(x, y) 377 c1 := color.YCbCrModel.Convert(c).(color.YCbCr) 378 p.Y[yi] = c1.Y 379 p.Cb[ci] = c1.Cb 380 p.Cr[ci] = c1.Cr 381 } 382 383 var tZeroYCbCr = func() (c color.YCbCr) { 384 c.Y, c.Cb, c.Cr = color.RGBToYCbCr(0, 0, 0) 385 return 386 }()