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