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
32 0 : inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
33 : {
34 0 : SkASSERT(d <= SK_DitherValueMax565);
35 0 : SkA32Assert(r);
36 0 : r = SkDITHER_R32_FOR_565_MACRO(r, d);
37 0 : SkA32Assert(r);
38 0 : return r;
39 : }
40 0 : inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
41 : {
42 0 : SkASSERT(d <= SK_DitherValueMax565);
43 0 : SkG32Assert(g);
44 0 : g = SkDITHER_G32_FOR_565_MACRO(g, d);
45 0 : SkG32Assert(g);
46 0 : return g;
47 : }
48 0 : inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
49 : {
50 0 : SkASSERT(d <= SK_DitherValueMax565);
51 0 : SkB32Assert(b);
52 0 : b = SkDITHER_B32_FOR_565_MACRO(b, d);
53 0 : SkB32Assert(b);
54 0 : 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 :
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 :
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 :
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 :
112 0 : static inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
113 : {
114 0 : SkASSERT(dither <= SK_DitherValueMax565);
115 :
116 0 : unsigned sr = SkGetPackedR32(c);
117 0 : unsigned sg = SkGetPackedG32(c);
118 0 : unsigned sb = SkGetPackedB32(c);
119 0 : sr = SkDITHER_R32To565(sr, dither);
120 0 : sg = SkDITHER_G32To565(sg, dither);
121 0 : sb = SkDITHER_B32To565(sb, dither);
122 :
123 0 : return SkPackRGB16(sr, sg, sb);
124 : }
125 :
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 :
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 :
156 0 : static inline SkPMColor16 SkDitherARGB32To4444(SkPMColor c, unsigned dither)
157 : {
158 0 : unsigned a = SkGetPackedA32(c);
159 0 : unsigned r = SkGetPackedR32(c);
160 0 : unsigned g = SkGetPackedG32(c);
161 0 : unsigned b = SkGetPackedB32(c);
162 :
163 0 : dither = SkAlphaMul(dither, SkAlpha255To256(a));
164 :
165 0 : a = SkDITHER_A32To4444(a, dither);
166 0 : r = SkDITHER_R32To4444(r, dither);
167 0 : g = SkDITHER_G32To4444(g, dither);
168 0 : b = SkDITHER_B32To4444(b, dither);
169 :
170 0 : 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
|