github.com/gidoBOSSftw5731/go/src@v0.0.0-20210226122457-d24b0edbf019/image/image_test.go (about) 1 // Copyright 2011 The Go Authors. 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 image 6 7 import ( 8 "image/color" 9 "testing" 10 ) 11 12 type image interface { 13 Image 14 Opaque() bool 15 Set(int, int, color.Color) 16 SubImage(Rectangle) Image 17 } 18 19 func cmp(cm color.Model, c0, c1 color.Color) bool { 20 r0, g0, b0, a0 := cm.Convert(c0).RGBA() 21 r1, g1, b1, a1 := cm.Convert(c1).RGBA() 22 return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1 23 } 24 25 var testImages = []struct { 26 name string 27 image func() image 28 }{ 29 {"rgba", func() image { return NewRGBA(Rect(0, 0, 10, 10)) }}, 30 {"rgba64", func() image { return NewRGBA64(Rect(0, 0, 10, 10)) }}, 31 {"nrgba", func() image { return NewNRGBA(Rect(0, 0, 10, 10)) }}, 32 {"nrgba64", func() image { return NewNRGBA64(Rect(0, 0, 10, 10)) }}, 33 {"alpha", func() image { return NewAlpha(Rect(0, 0, 10, 10)) }}, 34 {"alpha16", func() image { return NewAlpha16(Rect(0, 0, 10, 10)) }}, 35 {"gray", func() image { return NewGray(Rect(0, 0, 10, 10)) }}, 36 {"gray16", func() image { return NewGray16(Rect(0, 0, 10, 10)) }}, 37 {"paletted", func() image { 38 return NewPaletted(Rect(0, 0, 10, 10), color.Palette{ 39 Transparent, 40 Opaque, 41 }) 42 }}, 43 } 44 45 func TestImage(t *testing.T) { 46 for _, tc := range testImages { 47 m := tc.image() 48 if !Rect(0, 0, 10, 10).Eq(m.Bounds()) { 49 t.Errorf("%T: want bounds %v, got %v", m, Rect(0, 0, 10, 10), m.Bounds()) 50 continue 51 } 52 if !cmp(m.ColorModel(), Transparent, m.At(6, 3)) { 53 t.Errorf("%T: at (6, 3), want a zero color, got %v", m, m.At(6, 3)) 54 continue 55 } 56 m.Set(6, 3, Opaque) 57 if !cmp(m.ColorModel(), Opaque, m.At(6, 3)) { 58 t.Errorf("%T: at (6, 3), want a non-zero color, got %v", m, m.At(6, 3)) 59 continue 60 } 61 if !m.SubImage(Rect(6, 3, 7, 4)).(image).Opaque() { 62 t.Errorf("%T: at (6, 3) was not opaque", m) 63 continue 64 } 65 m = m.SubImage(Rect(3, 2, 9, 8)).(image) 66 if !Rect(3, 2, 9, 8).Eq(m.Bounds()) { 67 t.Errorf("%T: sub-image want bounds %v, got %v", m, Rect(3, 2, 9, 8), m.Bounds()) 68 continue 69 } 70 if !cmp(m.ColorModel(), Opaque, m.At(6, 3)) { 71 t.Errorf("%T: sub-image at (6, 3), want a non-zero color, got %v", m, m.At(6, 3)) 72 continue 73 } 74 if !cmp(m.ColorModel(), Transparent, m.At(3, 3)) { 75 t.Errorf("%T: sub-image at (3, 3), want a zero color, got %v", m, m.At(3, 3)) 76 continue 77 } 78 m.Set(3, 3, Opaque) 79 if !cmp(m.ColorModel(), Opaque, m.At(3, 3)) { 80 t.Errorf("%T: sub-image at (3, 3), want a non-zero color, got %v", m, m.At(3, 3)) 81 continue 82 } 83 // Test that taking an empty sub-image starting at a corner does not panic. 84 m.SubImage(Rect(0, 0, 0, 0)) 85 m.SubImage(Rect(10, 0, 10, 0)) 86 m.SubImage(Rect(0, 10, 0, 10)) 87 m.SubImage(Rect(10, 10, 10, 10)) 88 } 89 } 90 91 func TestNewXxxBadRectangle(t *testing.T) { 92 // call calls f(r) and reports whether it ran without panicking. 93 call := func(f func(Rectangle), r Rectangle) (ok bool) { 94 defer func() { 95 if recover() != nil { 96 ok = false 97 } 98 }() 99 f(r) 100 return true 101 } 102 103 testCases := []struct { 104 name string 105 f func(Rectangle) 106 }{ 107 {"RGBA", func(r Rectangle) { NewRGBA(r) }}, 108 {"RGBA64", func(r Rectangle) { NewRGBA64(r) }}, 109 {"NRGBA", func(r Rectangle) { NewNRGBA(r) }}, 110 {"NRGBA64", func(r Rectangle) { NewNRGBA64(r) }}, 111 {"Alpha", func(r Rectangle) { NewAlpha(r) }}, 112 {"Alpha16", func(r Rectangle) { NewAlpha16(r) }}, 113 {"Gray", func(r Rectangle) { NewGray(r) }}, 114 {"Gray16", func(r Rectangle) { NewGray16(r) }}, 115 {"CMYK", func(r Rectangle) { NewCMYK(r) }}, 116 {"Paletted", func(r Rectangle) { NewPaletted(r, color.Palette{color.Black, color.White}) }}, 117 {"YCbCr", func(r Rectangle) { NewYCbCr(r, YCbCrSubsampleRatio422) }}, 118 {"NYCbCrA", func(r Rectangle) { NewNYCbCrA(r, YCbCrSubsampleRatio444) }}, 119 } 120 121 for _, tc := range testCases { 122 // Calling NewXxx(r) should fail (panic, since NewXxx doesn't return an 123 // error) unless r's width and height are both non-negative. 124 for _, negDx := range []bool{false, true} { 125 for _, negDy := range []bool{false, true} { 126 r := Rectangle{ 127 Min: Point{15, 28}, 128 Max: Point{16, 29}, 129 } 130 if negDx { 131 r.Max.X = 14 132 } 133 if negDy { 134 r.Max.Y = 27 135 } 136 137 got := call(tc.f, r) 138 want := !negDx && !negDy 139 if got != want { 140 t.Errorf("New%s: negDx=%t, negDy=%t: got %t, want %t", 141 tc.name, negDx, negDy, got, want) 142 } 143 } 144 } 145 146 // Passing a Rectangle whose width and height is MaxInt should also fail 147 // (panic), due to overflow. 148 { 149 zeroAsUint := uint(0) 150 maxUint := zeroAsUint - 1 151 maxInt := int(maxUint / 2) 152 got := call(tc.f, Rectangle{ 153 Min: Point{0, 0}, 154 Max: Point{maxInt, maxInt}, 155 }) 156 if got { 157 t.Errorf("New%s: overflow: got ok, want !ok", tc.name) 158 } 159 } 160 } 161 } 162 163 func Test16BitsPerColorChannel(t *testing.T) { 164 testColorModel := []color.Model{ 165 color.RGBA64Model, 166 color.NRGBA64Model, 167 color.Alpha16Model, 168 color.Gray16Model, 169 } 170 for _, cm := range testColorModel { 171 c := cm.Convert(color.RGBA64{0x1234, 0x1234, 0x1234, 0x1234}) // Premultiplied alpha. 172 r, _, _, _ := c.RGBA() 173 if r != 0x1234 { 174 t.Errorf("%T: want red value 0x%04x got 0x%04x", c, 0x1234, r) 175 continue 176 } 177 } 178 testImage := []image{ 179 NewRGBA64(Rect(0, 0, 10, 10)), 180 NewNRGBA64(Rect(0, 0, 10, 10)), 181 NewAlpha16(Rect(0, 0, 10, 10)), 182 NewGray16(Rect(0, 0, 10, 10)), 183 } 184 for _, m := range testImage { 185 m.Set(1, 2, color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357}) // Non-premultiplied alpha. 186 r, _, _, _ := m.At(1, 2).RGBA() 187 if r != 0x1357 { 188 t.Errorf("%T: want red value 0x%04x got 0x%04x", m, 0x1357, r) 189 continue 190 } 191 } 192 } 193 194 func BenchmarkAt(b *testing.B) { 195 for _, tc := range testImages { 196 b.Run(tc.name, func(b *testing.B) { 197 m := tc.image() 198 b.ReportAllocs() 199 b.ResetTimer() 200 for i := 0; i < b.N; i++ { 201 m.At(4, 5) 202 } 203 }) 204 } 205 } 206 207 func BenchmarkSet(b *testing.B) { 208 c := color.Gray{0xff} 209 for _, tc := range testImages { 210 b.Run(tc.name, func(b *testing.B) { 211 m := tc.image() 212 b.ReportAllocs() 213 b.ResetTimer() 214 for i := 0; i < b.N; i++ { 215 m.Set(4, 5, c) 216 } 217 }) 218 } 219 } 220 221 func BenchmarkRGBAAt(b *testing.B) { 222 m := NewRGBA(Rect(0, 0, 10, 10)) 223 b.ResetTimer() 224 225 for i := 0; i < b.N; i++ { 226 m.RGBAAt(4, 5) 227 } 228 } 229 230 func BenchmarkRGBASetRGBA(b *testing.B) { 231 m := NewRGBA(Rect(0, 0, 10, 10)) 232 c := color.RGBA{0xff, 0xff, 0xff, 0x13} 233 b.ResetTimer() 234 235 for i := 0; i < b.N; i++ { 236 m.SetRGBA(4, 5, c) 237 } 238 } 239 240 func BenchmarkRGBA64At(b *testing.B) { 241 m := NewRGBA64(Rect(0, 0, 10, 10)) 242 b.ResetTimer() 243 244 for i := 0; i < b.N; i++ { 245 m.RGBA64At(4, 5) 246 } 247 } 248 249 func BenchmarkRGBA64SetRGBA64(b *testing.B) { 250 m := NewRGBA64(Rect(0, 0, 10, 10)) 251 c := color.RGBA64{0xffff, 0xffff, 0xffff, 0x1357} 252 b.ResetTimer() 253 254 for i := 0; i < b.N; i++ { 255 m.SetRGBA64(4, 5, c) 256 } 257 } 258 259 func BenchmarkNRGBAAt(b *testing.B) { 260 m := NewNRGBA(Rect(0, 0, 10, 10)) 261 b.ResetTimer() 262 263 for i := 0; i < b.N; i++ { 264 m.NRGBAAt(4, 5) 265 } 266 } 267 268 func BenchmarkNRGBASetNRGBA(b *testing.B) { 269 m := NewNRGBA(Rect(0, 0, 10, 10)) 270 c := color.NRGBA{0xff, 0xff, 0xff, 0x13} 271 b.ResetTimer() 272 273 for i := 0; i < b.N; i++ { 274 m.SetNRGBA(4, 5, c) 275 } 276 } 277 278 func BenchmarkNRGBA64At(b *testing.B) { 279 m := NewNRGBA64(Rect(0, 0, 10, 10)) 280 b.ResetTimer() 281 282 for i := 0; i < b.N; i++ { 283 m.NRGBA64At(4, 5) 284 } 285 } 286 287 func BenchmarkNRGBA64SetNRGBA64(b *testing.B) { 288 m := NewNRGBA64(Rect(0, 0, 10, 10)) 289 c := color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357} 290 b.ResetTimer() 291 292 for i := 0; i < b.N; i++ { 293 m.SetNRGBA64(4, 5, c) 294 } 295 } 296 297 func BenchmarkAlphaAt(b *testing.B) { 298 m := NewAlpha(Rect(0, 0, 10, 10)) 299 b.ResetTimer() 300 301 for i := 0; i < b.N; i++ { 302 m.AlphaAt(4, 5) 303 } 304 } 305 306 func BenchmarkAlphaSetAlpha(b *testing.B) { 307 m := NewAlpha(Rect(0, 0, 10, 10)) 308 c := color.Alpha{0x13} 309 b.ResetTimer() 310 311 for i := 0; i < b.N; i++ { 312 m.SetAlpha(4, 5, c) 313 } 314 } 315 316 func BenchmarkAlpha16At(b *testing.B) { 317 m := NewAlpha16(Rect(0, 0, 10, 10)) 318 b.ResetTimer() 319 320 for i := 0; i < b.N; i++ { 321 m.Alpha16At(4, 5) 322 } 323 } 324 325 func BenchmarkAlphaSetAlpha16(b *testing.B) { 326 m := NewAlpha16(Rect(0, 0, 10, 10)) 327 c := color.Alpha16{0x13} 328 b.ResetTimer() 329 330 for i := 0; i < b.N; i++ { 331 m.SetAlpha16(4, 5, c) 332 } 333 } 334 335 func BenchmarkGrayAt(b *testing.B) { 336 m := NewGray(Rect(0, 0, 10, 10)) 337 b.ResetTimer() 338 339 for i := 0; i < b.N; i++ { 340 m.GrayAt(4, 5) 341 } 342 } 343 344 func BenchmarkGraySetGray(b *testing.B) { 345 m := NewGray(Rect(0, 0, 10, 10)) 346 c := color.Gray{0x13} 347 b.ResetTimer() 348 349 for i := 0; i < b.N; i++ { 350 m.SetGray(4, 5, c) 351 } 352 } 353 354 func BenchmarkGray16At(b *testing.B) { 355 m := NewGray16(Rect(0, 0, 10, 10)) 356 b.ResetTimer() 357 358 for i := 0; i < b.N; i++ { 359 m.Gray16At(4, 5) 360 } 361 } 362 363 func BenchmarkGraySetGray16(b *testing.B) { 364 m := NewGray16(Rect(0, 0, 10, 10)) 365 c := color.Gray16{0x13} 366 b.ResetTimer() 367 368 for i := 0; i < b.N; i++ { 369 m.SetGray16(4, 5, c) 370 } 371 }