Home | History | Annotate | Download | only in core
      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 
     71 static 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 
     88 static 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 
    102 static 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 
    112 static 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 
    126 static 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 
    143 static 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 
    156 static 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