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