1
2 /*
3 * Copyright 2008 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #ifndef SkDither_DEFINED
11 #define SkDither_DEFINED
12
13 #include "SkColorPriv.h"
14
15 #define SK_DitherValueMax4444 15
16 #define SK_DitherValueMax565 7
17
18 /* need to use macros for bit-counts for each component, and then
19 move these into SkColorPriv.h
20 */
21
22 #define SkDITHER_R32_FOR_565_MACRO(r, d) (r + d - (r >> 5))
23 #define SkDITHER_G32_FOR_565_MACRO(g, d) (g + (d >> 1) - (g >> 6))
24 #define SkDITHER_B32_FOR_565_MACRO(b, d) (b + d - (b >> 5))
25
26 #define SkDITHER_A32_FOR_4444_MACRO(a, d) (a + 15 - (a >> 4))
27 #define SkDITHER_R32_FOR_4444_MACRO(r, d) (r + d - (r >> 4))
28 #define SkDITHER_G32_FOR_4444_MACRO(g, d) (g + d - (g >> 4))
29 #define SkDITHER_B32_FOR_4444_MACRO(b, d) (b + d - (b >> 4))
30
31 #ifdef SK_DEBUG
SkDITHER_R32_FOR_565(unsigned r,unsigned d)32 inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
33 {
34 SkASSERT(d <= SK_DitherValueMax565);
35 SkA32Assert(r);
36 r = SkDITHER_R32_FOR_565_MACRO(r, d);
37 SkA32Assert(r);
38 return r;
39 }
SkDITHER_G32_FOR_565(unsigned g,unsigned d)40 inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
41 {
42 SkASSERT(d <= SK_DitherValueMax565);
43 SkG32Assert(g);
44 g = SkDITHER_G32_FOR_565_MACRO(g, d);
45 SkG32Assert(g);
46 return g;
47 }
SkDITHER_B32_FOR_565(unsigned b,unsigned d)48 inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
49 {
50 SkASSERT(d <= SK_DitherValueMax565);
51 SkB32Assert(b);
52 b = SkDITHER_B32_FOR_565_MACRO(b, d);
53 SkB32Assert(b);
54 return b;
55 }
56 #else
57 #define SkDITHER_R32_FOR_565(r, d) SkDITHER_R32_FOR_565_MACRO(r, d)
58 #define SkDITHER_G32_FOR_565(g, d) SkDITHER_G32_FOR_565_MACRO(g, d)
59 #define SkDITHER_B32_FOR_565(b, d) SkDITHER_B32_FOR_565_MACRO(b, d)
60 #endif
61
62 #define SkDITHER_R32To565(r, d) SkR32ToR16(SkDITHER_R32_FOR_565(r, d))
63 #define SkDITHER_G32To565(g, d) SkG32ToG16(SkDITHER_G32_FOR_565(g, d))
64 #define SkDITHER_B32To565(b, d) SkB32ToB16(SkDITHER_B32_FOR_565(b, d))
65
66 #define SkDITHER_A32To4444(a, d) SkA32To4444(SkDITHER_A32_FOR_4444_MACRO(a, d))
67 #define SkDITHER_R32To4444(r, d) SkR32To4444(SkDITHER_R32_FOR_4444_MACRO(r, d))
68 #define SkDITHER_G32To4444(g, d) SkG32To4444(SkDITHER_G32_FOR_4444_MACRO(g, d))
69 #define SkDITHER_B32To4444(b, d) SkB32To4444(SkDITHER_B32_FOR_4444_MACRO(b, d))
70
SkDitherARGB32For565(SkPMColor c,unsigned dither)71 static inline SkPMColor SkDitherARGB32For565(SkPMColor c, unsigned dither)
72 {
73 SkASSERT(dither <= SK_DitherValueMax565);
74
75 unsigned sa = SkGetPackedA32(c);
76 dither = SkAlphaMul(dither, SkAlpha255To256(sa));
77
78 unsigned sr = SkGetPackedR32(c);
79 unsigned sg = SkGetPackedG32(c);
80 unsigned sb = SkGetPackedB32(c);
81 sr = SkDITHER_R32_FOR_565(sr, dither);
82 sg = SkDITHER_G32_FOR_565(sg, dither);
83 sb = SkDITHER_B32_FOR_565(sb, dither);
84
85 return SkPackARGB32(sa, sr, sg, sb);
86 }
87
SkDitherRGB32For565(SkPMColor c,unsigned dither)88 static inline SkPMColor SkDitherRGB32For565(SkPMColor c, unsigned dither)
89 {
90 SkASSERT(dither <= SK_DitherValueMax565);
91
92 unsigned sr = SkGetPackedR32(c);
93 unsigned sg = SkGetPackedG32(c);
94 unsigned sb = SkGetPackedB32(c);
95 sr = SkDITHER_R32_FOR_565(sr, dither);
96 sg = SkDITHER_G32_FOR_565(sg, dither);
97 sb = SkDITHER_B32_FOR_565(sb, dither);
98
99 return SkPackARGB32(0xFF, sr, sg, sb);
100 }
101
SkDitherRGBTo565(U8CPU r,U8CPU g,U8CPU b,unsigned dither)102 static inline uint16_t SkDitherRGBTo565(U8CPU r, U8CPU g, U8CPU b,
103 unsigned dither)
104 {
105 SkASSERT(dither <= SK_DitherValueMax565);
106 r = SkDITHER_R32To565(r, dither);
107 g = SkDITHER_G32To565(g, dither);
108 b = SkDITHER_B32To565(b, dither);
109 return SkPackRGB16(r, g, b);
110 }
111
SkDitherRGB32To565(SkPMColor c,unsigned dither)112 static inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
113 {
114 SkASSERT(dither <= SK_DitherValueMax565);
115
116 unsigned sr = SkGetPackedR32(c);
117 unsigned sg = SkGetPackedG32(c);
118 unsigned sb = SkGetPackedB32(c);
119 sr = SkDITHER_R32To565(sr, dither);
120 sg = SkDITHER_G32To565(sg, dither);
121 sb = SkDITHER_B32To565(sb, dither);
122
123 return SkPackRGB16(sr, sg, sb);
124 }
125
SkDitherARGB32To565(U8CPU sa,SkPMColor c,unsigned dither)126 static inline uint16_t SkDitherARGB32To565(U8CPU sa, SkPMColor c, unsigned dither)
127 {
128 SkASSERT(dither <= SK_DitherValueMax565);
129 dither = SkAlphaMul(dither, SkAlpha255To256(sa));
130
131 unsigned sr = SkGetPackedR32(c);
132 unsigned sg = SkGetPackedG32(c);
133 unsigned sb = SkGetPackedB32(c);
134 sr = SkDITHER_R32To565(sr, dither);
135 sg = SkDITHER_G32To565(sg, dither);
136 sb = SkDITHER_B32To565(sb, dither);
137
138 return SkPackRGB16(sr, sg, sb);
139 }
140
141 ///////////////////////// 4444
142
SkDitherARGB32To4444(U8CPU a,U8CPU r,U8CPU g,U8CPU b,unsigned dither)143 static inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, U8CPU g,
144 U8CPU b, unsigned dither)
145 {
146 dither = SkAlphaMul(dither, SkAlpha255To256(a));
147
148 a = SkDITHER_A32To4444(a, dither);
149 r = SkDITHER_R32To4444(r, dither);
150 g = SkDITHER_G32To4444(g, dither);
151 b = SkDITHER_B32To4444(b, dither);
152
153 return SkPackARGB4444(a, r, g, b);
154 }
155
SkDitherARGB32To4444(SkPMColor c,unsigned dither)156 static inline SkPMColor16 SkDitherARGB32To4444(SkPMColor c, unsigned dither)
157 {
158 unsigned a = SkGetPackedA32(c);
159 unsigned r = SkGetPackedR32(c);
160 unsigned g = SkGetPackedG32(c);
161 unsigned b = SkGetPackedB32(c);
162
163 dither = SkAlphaMul(dither, SkAlpha255To256(a));
164
165 a = SkDITHER_A32To4444(a, dither);
166 r = SkDITHER_R32To4444(r, dither);
167 g = SkDITHER_G32To4444(g, dither);
168 b = SkDITHER_B32To4444(b, dither);
169
170 return SkPackARGB4444(a, r, g, b);
171 }
172
173 // TODO: need dither routines for 565 -> 4444
174
175 // this toggles between a 4x4 and a 1x4 array
176 //#define ENABLE_DITHER_MATRIX_4X4
177
178 #ifdef ENABLE_DITHER_MATRIX_4X4
179 extern const uint8_t gDitherMatrix_4Bit_4X4[4][4];
180 extern const uint8_t gDitherMatrix_3Bit_4X4[4][4];
181
182 #define DITHER_4444_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_4Bit_4X4[(y) & 3]
183 #define DITHER_565_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3]
184
185 #define DITHER_VALUE(x) dither_scan[(x) & 3]
186 #else
187 extern const uint16_t gDitherMatrix_4Bit_16[4];
188 extern const uint16_t gDitherMatrix_3Bit_16[4];
189
190 #define DITHER_4444_SCAN(y) const uint16_t dither_scan = gDitherMatrix_4Bit_16[(y) & 3]
191 #define DITHER_565_SCAN(y) const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3]
192
193 #define DITHER_VALUE(x) ((dither_scan >> (((x) & 3) << 2)) & 0xF)
194 #endif
195
196 #define DITHER_INC_X(x) ++(x)
197
198 #endif
199