Line data Source code
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
31 0 : inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
32 : {
33 0 : SkASSERT(d <= SK_DitherValueMax565);
34 0 : SkA32Assert(r);
35 0 : r = SkDITHER_R32_FOR_565_MACRO(r, d);
36 0 : SkA32Assert(r);
37 0 : return r;
38 : }
39 0 : inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
40 : {
41 0 : SkASSERT(d <= SK_DitherValueMax565);
42 0 : SkG32Assert(g);
43 0 : g = SkDITHER_G32_FOR_565_MACRO(g, d);
44 0 : SkG32Assert(g);
45 0 : return g;
46 : }
47 0 : inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
48 : {
49 0 : SkASSERT(d <= SK_DitherValueMax565);
50 0 : SkB32Assert(b);
51 0 : b = SkDITHER_B32_FOR_565_MACRO(b, d);
52 0 : SkB32Assert(b);
53 0 : 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 :
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 :
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 :
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 :
111 0 : static inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
112 : {
113 0 : SkASSERT(dither <= SK_DitherValueMax565);
114 :
115 0 : unsigned sr = SkGetPackedR32(c);
116 0 : unsigned sg = SkGetPackedG32(c);
117 0 : unsigned sb = SkGetPackedB32(c);
118 0 : sr = SkDITHER_R32To565(sr, dither);
119 0 : sg = SkDITHER_G32To565(sg, dither);
120 0 : sb = SkDITHER_B32To565(sb, dither);
121 :
122 0 : return SkPackRGB16(sr, sg, sb);
123 : }
124 :
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 :
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 :
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
|