Source file
src/image/image_test.go
Documentation: image
1
2
3
4
5 package image
6
7 import (
8 "image/color"
9 "image/color/palette"
10 "testing"
11 )
12
13 type image interface {
14 Image
15 Opaque() bool
16 Set(int, int, color.Color)
17 SubImage(Rectangle) Image
18 }
19
20 func cmp(cm color.Model, c0, c1 color.Color) bool {
21 r0, g0, b0, a0 := cm.Convert(c0).RGBA()
22 r1, g1, b1, a1 := cm.Convert(c1).RGBA()
23 return r0 == r1 && g0 == g1 && b0 == b1 && a0 == a1
24 }
25
26 var testImages = []struct {
27 name string
28 image func() image
29 }{
30 {"rgba", func() image { return NewRGBA(Rect(0, 0, 10, 10)) }},
31 {"rgba64", func() image { return NewRGBA64(Rect(0, 0, 10, 10)) }},
32 {"nrgba", func() image { return NewNRGBA(Rect(0, 0, 10, 10)) }},
33 {"nrgba64", func() image { return NewNRGBA64(Rect(0, 0, 10, 10)) }},
34 {"alpha", func() image { return NewAlpha(Rect(0, 0, 10, 10)) }},
35 {"alpha16", func() image { return NewAlpha16(Rect(0, 0, 10, 10)) }},
36 {"gray", func() image { return NewGray(Rect(0, 0, 10, 10)) }},
37 {"gray16", func() image { return NewGray16(Rect(0, 0, 10, 10)) }},
38 {"paletted", func() image {
39 return NewPaletted(Rect(0, 0, 10, 10), color.Palette{
40 Transparent,
41 Opaque,
42 })
43 }},
44 }
45
46 func TestImage(t *testing.T) {
47 for _, tc := range testImages {
48 m := tc.image()
49 if !Rect(0, 0, 10, 10).Eq(m.Bounds()) {
50 t.Errorf("%T: want bounds %v, got %v", m, Rect(0, 0, 10, 10), m.Bounds())
51 continue
52 }
53 if !cmp(m.ColorModel(), Transparent, m.At(6, 3)) {
54 t.Errorf("%T: at (6, 3), want a zero color, got %v", m, m.At(6, 3))
55 continue
56 }
57 m.Set(6, 3, Opaque)
58 if !cmp(m.ColorModel(), Opaque, m.At(6, 3)) {
59 t.Errorf("%T: at (6, 3), want a non-zero color, got %v", m, m.At(6, 3))
60 continue
61 }
62 if !m.SubImage(Rect(6, 3, 7, 4)).(image).Opaque() {
63 t.Errorf("%T: at (6, 3) was not opaque", m)
64 continue
65 }
66 m = m.SubImage(Rect(3, 2, 9, 8)).(image)
67 if !Rect(3, 2, 9, 8).Eq(m.Bounds()) {
68 t.Errorf("%T: sub-image want bounds %v, got %v", m, Rect(3, 2, 9, 8), m.Bounds())
69 continue
70 }
71 if !cmp(m.ColorModel(), Opaque, m.At(6, 3)) {
72 t.Errorf("%T: sub-image at (6, 3), want a non-zero color, got %v", m, m.At(6, 3))
73 continue
74 }
75 if !cmp(m.ColorModel(), Transparent, m.At(3, 3)) {
76 t.Errorf("%T: sub-image at (3, 3), want a zero color, got %v", m, m.At(3, 3))
77 continue
78 }
79 m.Set(3, 3, Opaque)
80 if !cmp(m.ColorModel(), Opaque, m.At(3, 3)) {
81 t.Errorf("%T: sub-image at (3, 3), want a non-zero color, got %v", m, m.At(3, 3))
82 continue
83 }
84
85 m.SubImage(Rect(0, 0, 0, 0))
86 m.SubImage(Rect(10, 0, 10, 0))
87 m.SubImage(Rect(0, 10, 0, 10))
88 m.SubImage(Rect(10, 10, 10, 10))
89 }
90 }
91
92 func TestNewXxxBadRectangle(t *testing.T) {
93
94 call := func(f func(Rectangle), r Rectangle) (ok bool) {
95 defer func() {
96 if recover() != nil {
97 ok = false
98 }
99 }()
100 f(r)
101 return true
102 }
103
104 testCases := []struct {
105 name string
106 f func(Rectangle)
107 }{
108 {"RGBA", func(r Rectangle) { NewRGBA(r) }},
109 {"RGBA64", func(r Rectangle) { NewRGBA64(r) }},
110 {"NRGBA", func(r Rectangle) { NewNRGBA(r) }},
111 {"NRGBA64", func(r Rectangle) { NewNRGBA64(r) }},
112 {"Alpha", func(r Rectangle) { NewAlpha(r) }},
113 {"Alpha16", func(r Rectangle) { NewAlpha16(r) }},
114 {"Gray", func(r Rectangle) { NewGray(r) }},
115 {"Gray16", func(r Rectangle) { NewGray16(r) }},
116 {"CMYK", func(r Rectangle) { NewCMYK(r) }},
117 {"Paletted", func(r Rectangle) { NewPaletted(r, color.Palette{color.Black, color.White}) }},
118 {"YCbCr", func(r Rectangle) { NewYCbCr(r, YCbCrSubsampleRatio422) }},
119 {"NYCbCrA", func(r Rectangle) { NewNYCbCrA(r, YCbCrSubsampleRatio444) }},
120 }
121
122 for _, tc := range testCases {
123
124
125 for _, negDx := range []bool{false, true} {
126 for _, negDy := range []bool{false, true} {
127 r := Rectangle{
128 Min: Point{15, 28},
129 Max: Point{16, 29},
130 }
131 if negDx {
132 r.Max.X = 14
133 }
134 if negDy {
135 r.Max.Y = 27
136 }
137
138 got := call(tc.f, r)
139 want := !negDx && !negDy
140 if got != want {
141 t.Errorf("New%s: negDx=%t, negDy=%t: got %t, want %t",
142 tc.name, negDx, negDy, got, want)
143 }
144 }
145 }
146
147
148
149 {
150 zeroAsUint := uint(0)
151 maxUint := zeroAsUint - 1
152 maxInt := int(maxUint / 2)
153 got := call(tc.f, Rectangle{
154 Min: Point{0, 0},
155 Max: Point{maxInt, maxInt},
156 })
157 if got {
158 t.Errorf("New%s: overflow: got ok, want !ok", tc.name)
159 }
160 }
161 }
162 }
163
164 func Test16BitsPerColorChannel(t *testing.T) {
165 testColorModel := []color.Model{
166 color.RGBA64Model,
167 color.NRGBA64Model,
168 color.Alpha16Model,
169 color.Gray16Model,
170 }
171 for _, cm := range testColorModel {
172 c := cm.Convert(color.RGBA64{0x1234, 0x1234, 0x1234, 0x1234})
173 r, _, _, _ := c.RGBA()
174 if r != 0x1234 {
175 t.Errorf("%T: want red value 0x%04x got 0x%04x", c, 0x1234, r)
176 continue
177 }
178 }
179 testImage := []image{
180 NewRGBA64(Rect(0, 0, 10, 10)),
181 NewNRGBA64(Rect(0, 0, 10, 10)),
182 NewAlpha16(Rect(0, 0, 10, 10)),
183 NewGray16(Rect(0, 0, 10, 10)),
184 }
185 for _, m := range testImage {
186 m.Set(1, 2, color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357})
187 r, _, _, _ := m.At(1, 2).RGBA()
188 if r != 0x1357 {
189 t.Errorf("%T: want red value 0x%04x got 0x%04x", m, 0x1357, r)
190 continue
191 }
192 }
193 }
194
195 func TestRGBA64Image(t *testing.T) {
196
197 memset := func(s []byte, v byte) {
198 for i := range s {
199 s[i] = v
200 }
201 }
202
203 r := Rect(0, 0, 3, 2)
204 testCases := []Image{
205 NewAlpha(r),
206 NewAlpha16(r),
207 NewCMYK(r),
208 NewGray(r),
209 NewGray16(r),
210 NewNRGBA(r),
211 NewNRGBA64(r),
212 NewNYCbCrA(r, YCbCrSubsampleRatio444),
213 NewPaletted(r, palette.Plan9),
214 NewRGBA(r),
215 NewRGBA64(r),
216 NewUniform(color.RGBA64{}),
217 NewYCbCr(r, YCbCrSubsampleRatio444),
218 r,
219 }
220 for _, tc := range testCases {
221 switch tc := tc.(type) {
222
223
224
225
226
227
228
229
230
231
232
233
234 case interface {
235 SetRGBA64(x, y int, c color.RGBA64)
236 }:
237 tc.SetRGBA64(1, 1, color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF})
238
239 case *NYCbCrA:
240 memset(tc.YCbCr.Y, 0x77)
241 memset(tc.YCbCr.Cb, 0x88)
242 memset(tc.YCbCr.Cr, 0x99)
243 memset(tc.A, 0xAA)
244
245 case *Uniform:
246 tc.C = color.RGBA64{0x7FFF, 0x3FFF, 0x0000, 0x7FFF}
247
248 case *YCbCr:
249 memset(tc.Y, 0x77)
250 memset(tc.Cb, 0x88)
251 memset(tc.Cr, 0x99)
252
253 case Rectangle:
254
255
256
257 default:
258 t.Errorf("could not initialize pixels for %T", tc)
259 continue
260 }
261
262
263 rgba64Image, ok := tc.(RGBA64Image)
264 if !ok {
265 t.Errorf("%T is not an RGBA64Image", tc)
266 continue
267 }
268 got := rgba64Image.RGBA64At(1, 1)
269 wantR, wantG, wantB, wantA := tc.At(1, 1).RGBA()
270 if (uint32(got.R) != wantR) || (uint32(got.G) != wantG) ||
271 (uint32(got.B) != wantB) || (uint32(got.A) != wantA) {
272 t.Errorf("%T:\ngot (0x%04X, 0x%04X, 0x%04X, 0x%04X)\n"+
273 "want (0x%04X, 0x%04X, 0x%04X, 0x%04X)", tc,
274 got.R, got.G, got.B, got.A,
275 wantR, wantG, wantB, wantA)
276 continue
277 }
278 }
279 }
280
281 func BenchmarkAt(b *testing.B) {
282 for _, tc := range testImages {
283 b.Run(tc.name, func(b *testing.B) {
284 m := tc.image()
285 b.ReportAllocs()
286 b.ResetTimer()
287 for i := 0; i < b.N; i++ {
288 m.At(4, 5)
289 }
290 })
291 }
292 }
293
294 func BenchmarkSet(b *testing.B) {
295 c := color.Gray{0xff}
296 for _, tc := range testImages {
297 b.Run(tc.name, func(b *testing.B) {
298 m := tc.image()
299 b.ReportAllocs()
300 b.ResetTimer()
301 for i := 0; i < b.N; i++ {
302 m.Set(4, 5, c)
303 }
304 })
305 }
306 }
307
308 func BenchmarkRGBAAt(b *testing.B) {
309 m := NewRGBA(Rect(0, 0, 10, 10))
310 b.ResetTimer()
311
312 for i := 0; i < b.N; i++ {
313 m.RGBAAt(4, 5)
314 }
315 }
316
317 func BenchmarkRGBASetRGBA(b *testing.B) {
318 m := NewRGBA(Rect(0, 0, 10, 10))
319 c := color.RGBA{0xff, 0xff, 0xff, 0x13}
320 b.ResetTimer()
321
322 for i := 0; i < b.N; i++ {
323 m.SetRGBA(4, 5, c)
324 }
325 }
326
327 func BenchmarkRGBA64At(b *testing.B) {
328 m := NewRGBA64(Rect(0, 0, 10, 10))
329 b.ResetTimer()
330
331 for i := 0; i < b.N; i++ {
332 m.RGBA64At(4, 5)
333 }
334 }
335
336 func BenchmarkRGBA64SetRGBA64(b *testing.B) {
337 m := NewRGBA64(Rect(0, 0, 10, 10))
338 c := color.RGBA64{0xffff, 0xffff, 0xffff, 0x1357}
339 b.ResetTimer()
340
341 for i := 0; i < b.N; i++ {
342 m.SetRGBA64(4, 5, c)
343 }
344 }
345
346 func BenchmarkNRGBAAt(b *testing.B) {
347 m := NewNRGBA(Rect(0, 0, 10, 10))
348 b.ResetTimer()
349
350 for i := 0; i < b.N; i++ {
351 m.NRGBAAt(4, 5)
352 }
353 }
354
355 func BenchmarkNRGBASetNRGBA(b *testing.B) {
356 m := NewNRGBA(Rect(0, 0, 10, 10))
357 c := color.NRGBA{0xff, 0xff, 0xff, 0x13}
358 b.ResetTimer()
359
360 for i := 0; i < b.N; i++ {
361 m.SetNRGBA(4, 5, c)
362 }
363 }
364
365 func BenchmarkNRGBA64At(b *testing.B) {
366 m := NewNRGBA64(Rect(0, 0, 10, 10))
367 b.ResetTimer()
368
369 for i := 0; i < b.N; i++ {
370 m.NRGBA64At(4, 5)
371 }
372 }
373
374 func BenchmarkNRGBA64SetNRGBA64(b *testing.B) {
375 m := NewNRGBA64(Rect(0, 0, 10, 10))
376 c := color.NRGBA64{0xffff, 0xffff, 0xffff, 0x1357}
377 b.ResetTimer()
378
379 for i := 0; i < b.N; i++ {
380 m.SetNRGBA64(4, 5, c)
381 }
382 }
383
384 func BenchmarkAlphaAt(b *testing.B) {
385 m := NewAlpha(Rect(0, 0, 10, 10))
386 b.ResetTimer()
387
388 for i := 0; i < b.N; i++ {
389 m.AlphaAt(4, 5)
390 }
391 }
392
393 func BenchmarkAlphaSetAlpha(b *testing.B) {
394 m := NewAlpha(Rect(0, 0, 10, 10))
395 c := color.Alpha{0x13}
396 b.ResetTimer()
397
398 for i := 0; i < b.N; i++ {
399 m.SetAlpha(4, 5, c)
400 }
401 }
402
403 func BenchmarkAlpha16At(b *testing.B) {
404 m := NewAlpha16(Rect(0, 0, 10, 10))
405 b.ResetTimer()
406
407 for i := 0; i < b.N; i++ {
408 m.Alpha16At(4, 5)
409 }
410 }
411
412 func BenchmarkAlphaSetAlpha16(b *testing.B) {
413 m := NewAlpha16(Rect(0, 0, 10, 10))
414 c := color.Alpha16{0x13}
415 b.ResetTimer()
416
417 for i := 0; i < b.N; i++ {
418 m.SetAlpha16(4, 5, c)
419 }
420 }
421
422 func BenchmarkGrayAt(b *testing.B) {
423 m := NewGray(Rect(0, 0, 10, 10))
424 b.ResetTimer()
425
426 for i := 0; i < b.N; i++ {
427 m.GrayAt(4, 5)
428 }
429 }
430
431 func BenchmarkGraySetGray(b *testing.B) {
432 m := NewGray(Rect(0, 0, 10, 10))
433 c := color.Gray{0x13}
434 b.ResetTimer()
435
436 for i := 0; i < b.N; i++ {
437 m.SetGray(4, 5, c)
438 }
439 }
440
441 func BenchmarkGray16At(b *testing.B) {
442 m := NewGray16(Rect(0, 0, 10, 10))
443 b.ResetTimer()
444
445 for i := 0; i < b.N; i++ {
446 m.Gray16At(4, 5)
447 }
448 }
449
450 func BenchmarkGraySetGray16(b *testing.B) {
451 m := NewGray16(Rect(0, 0, 10, 10))
452 c := color.Gray16{0x13}
453 b.ResetTimer()
454
455 for i := 0; i < b.N; i++ {
456 m.SetGray16(4, 5, c)
457 }
458 }
459
View as plain text