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