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    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    }
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    }
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
71static 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
88static 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
102static 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
112static 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
126static 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
143static 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
156static 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