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