Home | History | Annotate | Download | only in core
      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 "SkColorData.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 SkColorData.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 
     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 static 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 
    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 SK_API const uint16_t gDitherMatrix_4Bit_16[4];
    187     extern SK_API 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