1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2008 The Android Open Source Project
48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkDither_DEFINED
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDither_DEFINED
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_DitherValueMax4444   15
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_DitherValueMax565    7
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*  need to use macros for bit-counts for each component, and then
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    move these into SkColorPriv.h
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_R32_FOR_565_MACRO(r, d)    (r + d - (r >> 5))
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_G32_FOR_565_MACRO(g, d)    (g + (d >> 1) - (g >> 6))
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_B32_FOR_565_MACRO(b, d)    (b + d - (b >> 5))
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_A32_FOR_4444_MACRO(a, d)    (a + 15 - (a >> 4))
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_R32_FOR_4444_MACRO(r, d)    (r + d - (r >> 4))
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_G32_FOR_4444_MACRO(g, d)    (g + d - (g >> 4))
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_B32_FOR_4444_MACRO(b, d)    (b + d - (b >> 4))
308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inline unsigned SkDITHER_R32_FOR_565(unsigned r, unsigned d)
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(d <= SK_DitherValueMax565);
358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkA32Assert(r);
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        r = SkDITHER_R32_FOR_565_MACRO(r, d);
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkA32Assert(r);
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return r;
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inline unsigned SkDITHER_G32_FOR_565(unsigned g, unsigned d)
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(d <= SK_DitherValueMax565);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkG32Assert(g);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        g = SkDITHER_G32_FOR_565_MACRO(g, d);
458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkG32Assert(g);
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return g;
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    inline unsigned SkDITHER_B32_FOR_565(unsigned b, unsigned d)
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    {
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(d <= SK_DitherValueMax565);
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkB32Assert(b);
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        b = SkDITHER_B32_FOR_565_MACRO(b, d);
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkB32Assert(b);
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return b;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkDITHER_R32_FOR_565(r, d)  SkDITHER_R32_FOR_565_MACRO(r, d)
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkDITHER_G32_FOR_565(g, d)  SkDITHER_G32_FOR_565_MACRO(g, d)
598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define SkDITHER_B32_FOR_565(b, d)  SkDITHER_B32_FOR_565_MACRO(b, d)
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_R32To565(r, d)  SkR32ToR16(SkDITHER_R32_FOR_565(r, d))
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_G32To565(g, d)  SkG32ToG16(SkDITHER_G32_FOR_565(g, d))
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_B32To565(b, d)  SkB32ToB16(SkDITHER_B32_FOR_565(b, d))
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_A32To4444(a, d)  SkA32To4444(SkDITHER_A32_FOR_4444_MACRO(a, d))
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_R32To4444(r, d)  SkR32To4444(SkDITHER_R32_FOR_4444_MACRO(r, d))
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_G32To4444(g, d)  SkG32To4444(SkDITHER_G32_FOR_4444_MACRO(g, d))
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkDITHER_B32To4444(b, d)  SkB32To4444(SkDITHER_B32_FOR_4444_MACRO(b, d))
708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor SkDitherARGB32For565(SkPMColor c, unsigned dither)
728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(dither <= SK_DitherValueMax565);
74fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sa = SkGetPackedA32(c);
768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dither = SkAlphaMul(dither, SkAlpha255To256(sa));
778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(c);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(c);
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(c);
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = SkDITHER_R32_FOR_565(sr, dither);
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = SkDITHER_G32_FOR_565(sg, dither);
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = SkDITHER_B32_FOR_565(sb, dither);
84fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB32(sa, sr, sg, sb);
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor SkDitherRGB32For565(SkPMColor c, unsigned dither)
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(dither <= SK_DitherValueMax565);
91fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(c);
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(c);
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(c);
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = SkDITHER_R32_FOR_565(sr, dither);
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = SkDITHER_G32_FOR_565(sg, dither);
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = SkDITHER_B32_FOR_565(sb, dither);
98fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB32(0xFF, sr, sg, sb);
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t SkDitherRGBTo565(U8CPU r, U8CPU g, U8CPU b,
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                              unsigned dither)
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(dither <= SK_DitherValueMax565);
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = SkDITHER_R32To565(r, dither);
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = SkDITHER_G32To565(g, dither);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = SkDITHER_B32To565(b, dither);
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(r, g, b);
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t SkDitherRGB32To565(SkPMColor c, unsigned dither)
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(dither <= SK_DitherValueMax565);
115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(c);
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(c);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(c);
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = SkDITHER_R32To565(sr, dither);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = SkDITHER_G32To565(sg, dither);
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = SkDITHER_B32To565(sb, dither);
122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(sr, sg, sb);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t SkDitherARGB32To565(U8CPU sa, SkPMColor c, unsigned dither)
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
128fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    SkASSERT(dither <= SK_DitherValueMax565);
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dither = SkAlphaMul(dither, SkAlpha255To256(sa));
130fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sr = SkGetPackedR32(c);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sg = SkGetPackedG32(c);
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned sb = SkGetPackedB32(c);
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sr = SkDITHER_R32To565(sr, dither);
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sg = SkDITHER_G32To565(sg, dither);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    sb = SkDITHER_B32To565(sb, dither);
137fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackRGB16(sr, sg, sb);
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com///////////////////////// 4444
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkDitherARGB32To4444(U8CPU a, U8CPU r, U8CPU g,
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                                               U8CPU b, unsigned dither)
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dither = SkAlphaMul(dither, SkAlpha255To256(a));
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a = SkDITHER_A32To4444(a, dither);
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = SkDITHER_R32To4444(r, dither);
1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = SkDITHER_G32To4444(g, dither);
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = SkDITHER_B32To4444(b, dither);
152fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB4444(a, r, g, b);
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPMColor16 SkDitherARGB32To4444(SkPMColor c, unsigned dither)
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned a = SkGetPackedA32(c);
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned r = SkGetPackedR32(c);
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned g = SkGetPackedG32(c);
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    unsigned b = SkGetPackedB32(c);
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    dither = SkAlphaMul(dither, SkAlpha255To256(a));
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    a = SkDITHER_A32To4444(a, dither);
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r = SkDITHER_R32To4444(r, dither);
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    g = SkDITHER_G32To4444(g, dither);
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    b = SkDITHER_B32To4444(b, dither);
169fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return SkPackARGB4444(a, r, g, b);
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// TODO: need dither routines for 565 -> 4444
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this toggles between a 4x4 and a 1x4 array
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define ENABLE_DITHER_MATRIX_4X4
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef ENABLE_DITHER_MATRIX_4X4
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    extern const uint8_t gDitherMatrix_4Bit_4X4[4][4];
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    extern const uint8_t gDitherMatrix_3Bit_4X4[4][4];
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define DITHER_4444_SCAN(y) const uint8_t* dither_scan = gDitherMatrix_4Bit_4X4[(y) & 3]
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define DITHER_565_SCAN(y)  const uint8_t* dither_scan = gDitherMatrix_3Bit_4X4[(y) & 3]
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define DITHER_VALUE(x) dither_scan[(x) & 3]
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    extern const uint16_t gDitherMatrix_4Bit_16[4];
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    extern const uint16_t gDitherMatrix_3Bit_16[4];
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define DITHER_4444_SCAN(y) const uint16_t dither_scan = gDitherMatrix_4Bit_16[(y) & 3]
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define DITHER_565_SCAN(y)  const uint16_t dither_scan = gDitherMatrix_3Bit_16[(y) & 3]
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    #define DITHER_VALUE(x) ((dither_scan >> (((x) & 3) << 2)) & 0xF)
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define DITHER_INC_X(x) ++(x)
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
199