Source file
src/image/color/ycbcr_test.go
1
2
3
4
5 package color
6
7 import (
8 "fmt"
9 "testing"
10 )
11
12 func delta(x, y uint8) uint8 {
13 if x >= y {
14 return x - y
15 }
16 return y - x
17 }
18
19 func eq(c0, c1 Color) error {
20 r0, g0, b0, a0 := c0.RGBA()
21 r1, g1, b1, a1 := c1.RGBA()
22 if r0 != r1 || g0 != g1 || b0 != b1 || a0 != a1 {
23 return fmt.Errorf("got 0x%04x 0x%04x 0x%04x 0x%04x\nwant 0x%04x 0x%04x 0x%04x 0x%04x",
24 r0, g0, b0, a0, r1, g1, b1, a1)
25 }
26 return nil
27 }
28
29
30
31 func TestYCbCrRoundtrip(t *testing.T) {
32 for r := 0; r < 256; r += 7 {
33 for g := 0; g < 256; g += 5 {
34 for b := 0; b < 256; b += 3 {
35 r0, g0, b0 := uint8(r), uint8(g), uint8(b)
36 y, cb, cr := RGBToYCbCr(r0, g0, b0)
37 r1, g1, b1 := YCbCrToRGB(y, cb, cr)
38 if delta(r0, r1) > 2 || delta(g0, g1) > 2 || delta(b0, b1) > 2 {
39 t.Fatalf("\nr0, g0, b0 = %d, %d, %d\ny, cb, cr = %d, %d, %d\nr1, g1, b1 = %d, %d, %d",
40 r0, g0, b0, y, cb, cr, r1, g1, b1)
41 }
42 }
43 }
44 }
45 }
46
47
48
49
50 func TestYCbCrToRGBConsistency(t *testing.T) {
51 for y := 0; y < 256; y += 7 {
52 for cb := 0; cb < 256; cb += 5 {
53 for cr := 0; cr < 256; cr += 3 {
54 x := YCbCr{uint8(y), uint8(cb), uint8(cr)}
55 r0, g0, b0, _ := x.RGBA()
56 r1, g1, b1 := uint8(r0>>8), uint8(g0>>8), uint8(b0>>8)
57 r2, g2, b2 := YCbCrToRGB(x.Y, x.Cb, x.Cr)
58 if r1 != r2 || g1 != g2 || b1 != b2 {
59 t.Fatalf("y, cb, cr = %d, %d, %d\nr1, g1, b1 = %d, %d, %d\nr2, g2, b2 = %d, %d, %d",
60 y, cb, cr, r1, g1, b1, r2, g2, b2)
61 }
62 }
63 }
64 }
65 }
66
67
68 func TestYCbCrGray(t *testing.T) {
69 for i := 0; i < 256; i++ {
70 c0 := YCbCr{uint8(i), 0x80, 0x80}
71 c1 := Gray{uint8(i)}
72 if err := eq(c0, c1); err != nil {
73 t.Errorf("i=0x%02x:\n%v", i, err)
74 }
75 }
76 }
77
78
79 func TestNYCbCrAAlpha(t *testing.T) {
80 for i := 0; i < 256; i++ {
81 c0 := NYCbCrA{YCbCr{0xff, 0x80, 0x80}, uint8(i)}
82 c1 := Alpha{uint8(i)}
83 if err := eq(c0, c1); err != nil {
84 t.Errorf("i=0x%02x:\n%v", i, err)
85 }
86 }
87 }
88
89
90 func TestNYCbCrAYCbCr(t *testing.T) {
91 for i := 0; i < 256; i++ {
92 c0 := NYCbCrA{YCbCr{uint8(i), 0x40, 0xc0}, 0xff}
93 c1 := YCbCr{uint8(i), 0x40, 0xc0}
94 if err := eq(c0, c1); err != nil {
95 t.Errorf("i=0x%02x:\n%v", i, err)
96 }
97 }
98 }
99
100
101
102 func TestCMYKRoundtrip(t *testing.T) {
103 for r := 0; r < 256; r += 7 {
104 for g := 0; g < 256; g += 5 {
105 for b := 0; b < 256; b += 3 {
106 r0, g0, b0 := uint8(r), uint8(g), uint8(b)
107 c, m, y, k := RGBToCMYK(r0, g0, b0)
108 r1, g1, b1 := CMYKToRGB(c, m, y, k)
109 if delta(r0, r1) > 1 || delta(g0, g1) > 1 || delta(b0, b1) > 1 {
110 t.Fatalf("\nr0, g0, b0 = %d, %d, %d\nc, m, y, k = %d, %d, %d, %d\nr1, g1, b1 = %d, %d, %d",
111 r0, g0, b0, c, m, y, k, r1, g1, b1)
112 }
113 }
114 }
115 }
116 }
117
118
119
120
121 func TestCMYKToRGBConsistency(t *testing.T) {
122 for c := 0; c < 256; c += 7 {
123 for m := 0; m < 256; m += 5 {
124 for y := 0; y < 256; y += 3 {
125 for k := 0; k < 256; k += 11 {
126 x := CMYK{uint8(c), uint8(m), uint8(y), uint8(k)}
127 r0, g0, b0, _ := x.RGBA()
128 r1, g1, b1 := uint8(r0>>8), uint8(g0>>8), uint8(b0>>8)
129 r2, g2, b2 := CMYKToRGB(x.C, x.M, x.Y, x.K)
130 if r1 != r2 || g1 != g2 || b1 != b2 {
131 t.Fatalf("c, m, y, k = %d, %d, %d, %d\nr1, g1, b1 = %d, %d, %d\nr2, g2, b2 = %d, %d, %d",
132 c, m, y, k, r1, g1, b1, r2, g2, b2)
133 }
134 }
135 }
136 }
137 }
138 }
139
140
141 func TestCMYKGray(t *testing.T) {
142 for i := 0; i < 256; i++ {
143 if err := eq(CMYK{0x00, 0x00, 0x00, uint8(255 - i)}, Gray{uint8(i)}); err != nil {
144 t.Errorf("i=0x%02x:\n%v", i, err)
145 }
146 }
147 }
148
149 func TestPalette(t *testing.T) {
150 p := Palette{
151 RGBA{0xff, 0xff, 0xff, 0xff},
152 RGBA{0x80, 0x00, 0x00, 0xff},
153 RGBA{0x7f, 0x00, 0x00, 0x7f},
154 RGBA{0x00, 0x00, 0x00, 0x7f},
155 RGBA{0x00, 0x00, 0x00, 0x00},
156 RGBA{0x40, 0x40, 0x40, 0x40},
157 }
158
159
160 for i, c := range p {
161 j := p.Index(c)
162 if i != j {
163 t.Errorf("Index(%v): got %d (color = %v), want %d", c, j, p[j], i)
164 }
165 }
166
167
168 got := p.Convert(RGBA{0x80, 0x00, 0x00, 0x80})
169 want := RGBA{0x7f, 0x00, 0x00, 0x7f}
170 if got != want {
171 t.Errorf("got %v, want %v", got, want)
172 }
173 }
174
175 var sink8 uint8
176 var sink32 uint32
177
178 func BenchmarkYCbCrToRGB(b *testing.B) {
179
180
181
182 b.Run("0", func(b *testing.B) {
183 for i := 0; i < b.N; i++ {
184 sink8, sink8, sink8 = YCbCrToRGB(0, 0, 0)
185 }
186 })
187 b.Run("128", func(b *testing.B) {
188 for i := 0; i < b.N; i++ {
189 sink8, sink8, sink8 = YCbCrToRGB(128, 128, 128)
190 }
191 })
192 b.Run("255", func(b *testing.B) {
193 for i := 0; i < b.N; i++ {
194 sink8, sink8, sink8 = YCbCrToRGB(255, 255, 255)
195 }
196 })
197 }
198
199 func BenchmarkRGBToYCbCr(b *testing.B) {
200
201
202
203 b.Run("0", func(b *testing.B) {
204 for i := 0; i < b.N; i++ {
205 sink8, sink8, sink8 = RGBToYCbCr(0, 0, 0)
206 }
207 })
208 b.Run("Cb", func(b *testing.B) {
209 for i := 0; i < b.N; i++ {
210 sink8, sink8, sink8 = RGBToYCbCr(0, 0, 255)
211 }
212 })
213 b.Run("Cr", func(b *testing.B) {
214 for i := 0; i < b.N; i++ {
215 sink8, sink8, sink8 = RGBToYCbCr(255, 0, 0)
216 }
217 })
218 }
219
220 func BenchmarkYCbCrToRGBA(b *testing.B) {
221
222
223
224 b.Run("0", func(b *testing.B) {
225 c := YCbCr{0, 0, 0}
226 for i := 0; i < b.N; i++ {
227 sink32, sink32, sink32, sink32 = c.RGBA()
228 }
229 })
230 b.Run("128", func(b *testing.B) {
231 c := YCbCr{128, 128, 128}
232 for i := 0; i < b.N; i++ {
233 sink32, sink32, sink32, sink32 = c.RGBA()
234 }
235 })
236 b.Run("255", func(b *testing.B) {
237 c := YCbCr{255, 255, 255}
238 for i := 0; i < b.N; i++ {
239 sink32, sink32, sink32, sink32 = c.RGBA()
240 }
241 })
242 }
243
244 func BenchmarkNYCbCrAToRGBA(b *testing.B) {
245
246
247
248 b.Run("0", func(b *testing.B) {
249 c := NYCbCrA{YCbCr{0, 0, 0}, 0xff}
250 for i := 0; i < b.N; i++ {
251 sink32, sink32, sink32, sink32 = c.RGBA()
252 }
253 })
254 b.Run("128", func(b *testing.B) {
255 c := NYCbCrA{YCbCr{128, 128, 128}, 0xff}
256 for i := 0; i < b.N; i++ {
257 sink32, sink32, sink32, sink32 = c.RGBA()
258 }
259 })
260 b.Run("255", func(b *testing.B) {
261 c := NYCbCrA{YCbCr{255, 255, 255}, 0xff}
262 for i := 0; i < b.N; i++ {
263 sink32, sink32, sink32, sink32 = c.RGBA()
264 }
265 })
266 }
267
View as plain text