Home | History | Annotate | Download | only in images
      1 /*
      2  * Copyright 2007 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 #include "SkScaledBitmapSampler.h"
     10 #include "SkBitmap.h"
     11 #include "SkColorPriv.h"
     12 #include "SkDither.h"
     13 #include "SkTypes.h"
     14 
     15 // 8888
     16 
     17 static bool Sample_Gray_D8888(void* SK_RESTRICT dstRow,
     18                               const uint8_t* SK_RESTRICT src,
     19                               int width, int deltaSrc, int, const SkPMColor[]) {
     20     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
     21     for (int x = 0; x < width; x++) {
     22         dst[x] = SkPackARGB32(0xFF, src[0], src[0], src[0]);
     23         src += deltaSrc;
     24     }
     25     return false;
     26 }
     27 
     28 static bool Sample_RGBx_D8888(void* SK_RESTRICT dstRow,
     29                               const uint8_t* SK_RESTRICT src,
     30                               int width, int deltaSrc, int, const SkPMColor[]) {
     31     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
     32     for (int x = 0; x < width; x++) {
     33         dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]);
     34         src += deltaSrc;
     35     }
     36     return false;
     37 }
     38 
     39 static bool Sample_RGBA_D8888(void* SK_RESTRICT dstRow,
     40                               const uint8_t* SK_RESTRICT src,
     41                               int width, int deltaSrc, int, const SkPMColor[]) {
     42     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
     43     unsigned alphaMask = 0xFF;
     44     for (int x = 0; x < width; x++) {
     45         unsigned alpha = src[3];
     46         dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
     47         src += deltaSrc;
     48         alphaMask &= alpha;
     49     }
     50     return alphaMask != 0xFF;
     51 }
     52 
     53 // 565
     54 
     55 static bool Sample_Gray_D565(void* SK_RESTRICT dstRow,
     56                              const uint8_t* SK_RESTRICT src,
     57                              int width, int deltaSrc, int, const SkPMColor[]) {
     58     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
     59     for (int x = 0; x < width; x++) {
     60         dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]);
     61         src += deltaSrc;
     62     }
     63     return false;
     64 }
     65 
     66 static bool Sample_Gray_D565_D(void* SK_RESTRICT dstRow,
     67                                const uint8_t* SK_RESTRICT src,
     68                            int width, int deltaSrc, int y, const SkPMColor[]) {
     69     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
     70     DITHER_565_SCAN(y);
     71     for (int x = 0; x < width; x++) {
     72         dst[x] = SkDitherRGBTo565(src[0], src[0], src[0], DITHER_VALUE(x));
     73         src += deltaSrc;
     74     }
     75     return false;
     76 }
     77 
     78 static bool Sample_RGBx_D565(void* SK_RESTRICT dstRow,
     79                              const uint8_t* SK_RESTRICT src,
     80                              int width, int deltaSrc, int, const SkPMColor[]) {
     81     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
     82     for (int x = 0; x < width; x++) {
     83         dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]);
     84         src += deltaSrc;
     85     }
     86     return false;
     87 }
     88 
     89 static bool Sample_D565_D565(void* SK_RESTRICT dstRow,
     90                              const uint8_t* SK_RESTRICT src,
     91                              int width, int deltaSrc, int, const SkPMColor[]) {
     92     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
     93     uint16_t* SK_RESTRICT castedSrc = (uint16_t*) src;
     94     for (int x = 0; x < width; x++) {
     95         dst[x] = castedSrc[0];
     96         castedSrc += deltaSrc >> 1;
     97     }
     98     return false;
     99 }
    100 
    101 static bool Sample_RGBx_D565_D(void* SK_RESTRICT dstRow,
    102                                const uint8_t* SK_RESTRICT src,
    103                            int width, int deltaSrc, int y, const SkPMColor[]) {
    104     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
    105     DITHER_565_SCAN(y);
    106     for (int x = 0; x < width; x++) {
    107         dst[x] = SkDitherRGBTo565(src[0], src[1], src[2], DITHER_VALUE(x));
    108         src += deltaSrc;
    109     }
    110     return false;
    111 }
    112 
    113 // 4444
    114 
    115 static bool Sample_Gray_D4444(void* SK_RESTRICT dstRow,
    116                               const uint8_t* SK_RESTRICT src,
    117                               int width, int deltaSrc, int, const SkPMColor[]) {
    118     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    119     for (int x = 0; x < width; x++) {
    120         unsigned gray = src[0] >> 4;
    121         dst[x] = SkPackARGB4444(0xF, gray, gray, gray);
    122         src += deltaSrc;
    123     }
    124     return false;
    125 }
    126 
    127 static bool Sample_Gray_D4444_D(void* SK_RESTRICT dstRow,
    128                                 const uint8_t* SK_RESTRICT src,
    129                             int width, int deltaSrc, int y, const SkPMColor[]) {
    130     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    131     DITHER_4444_SCAN(y);
    132     for (int x = 0; x < width; x++) {
    133         dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[0], src[0],
    134                                       DITHER_VALUE(x));
    135         src += deltaSrc;
    136     }
    137     return false;
    138 }
    139 
    140 static bool Sample_RGBx_D4444(void* SK_RESTRICT dstRow,
    141                               const uint8_t* SK_RESTRICT src,
    142                               int width, int deltaSrc, int, const SkPMColor[]) {
    143     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    144     for (int x = 0; x < width; x++) {
    145         dst[x] = SkPackARGB4444(0xF, src[0] >> 4, src[1] >> 4, src[2] >> 4);
    146         src += deltaSrc;
    147     }
    148     return false;
    149 }
    150 
    151 static bool Sample_RGBx_D4444_D(void* SK_RESTRICT dstRow,
    152                                 const uint8_t* SK_RESTRICT src,
    153                             int width, int deltaSrc, int y, const SkPMColor[]) {
    154     SkPMColor16* dst = (SkPMColor16*)dstRow;
    155     DITHER_4444_SCAN(y);
    156 
    157     for (int x = 0; x < width; x++) {
    158         dst[x] = SkDitherARGB32To4444(0xFF, src[0], src[1], src[2],
    159                                       DITHER_VALUE(x));
    160         src += deltaSrc;
    161     }
    162     return false;
    163 }
    164 
    165 static bool Sample_RGBA_D4444(void* SK_RESTRICT dstRow,
    166                               const uint8_t* SK_RESTRICT src,
    167                               int width, int deltaSrc, int, const SkPMColor[]) {
    168     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    169     unsigned alphaMask = 0xFF;
    170 
    171     for (int x = 0; x < width; x++) {
    172         unsigned alpha = src[3];
    173         SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
    174         dst[x] = SkPixel32ToPixel4444(c);
    175         src += deltaSrc;
    176         alphaMask &= alpha;
    177     }
    178     return alphaMask != 0xFF;
    179 }
    180 
    181 static bool Sample_RGBA_D4444_D(void* SK_RESTRICT dstRow,
    182                                 const uint8_t* SK_RESTRICT src,
    183                             int width, int deltaSrc, int y, const SkPMColor[]) {
    184     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    185     unsigned alphaMask = 0xFF;
    186     DITHER_4444_SCAN(y);
    187 
    188     for (int x = 0; x < width; x++) {
    189         unsigned alpha = src[3];
    190         SkPMColor c = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]);
    191         dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
    192         src += deltaSrc;
    193         alphaMask &= alpha;
    194     }
    195     return alphaMask != 0xFF;
    196 }
    197 
    198 // Index
    199 
    200 #define A32_MASK_IN_PLACE   (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT)
    201 
    202 static bool Sample_Index_D8888(void* SK_RESTRICT dstRow,
    203                                const uint8_t* SK_RESTRICT src,
    204                        int width, int deltaSrc, int, const SkPMColor ctable[]) {
    205 
    206     SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow;
    207     SkPMColor cc = A32_MASK_IN_PLACE;
    208     for (int x = 0; x < width; x++) {
    209         SkPMColor c = ctable[*src];
    210         cc &= c;
    211         dst[x] = c;
    212         src += deltaSrc;
    213     }
    214     return cc != A32_MASK_IN_PLACE;
    215 }
    216 
    217 static bool Sample_Index_D565(void* SK_RESTRICT dstRow,
    218                                const uint8_t* SK_RESTRICT src,
    219                        int width, int deltaSrc, int, const SkPMColor ctable[]) {
    220 
    221     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
    222     for (int x = 0; x < width; x++) {
    223         dst[x] = SkPixel32ToPixel16(ctable[*src]);
    224         src += deltaSrc;
    225     }
    226     return false;
    227 }
    228 
    229 static bool Sample_Index_D565_D(void* SK_RESTRICT dstRow,
    230                                 const uint8_t* SK_RESTRICT src, int width,
    231                                 int deltaSrc, int y, const SkPMColor ctable[]) {
    232 
    233     uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow;
    234     DITHER_565_SCAN(y);
    235 
    236     for (int x = 0; x < width; x++) {
    237         SkPMColor c = ctable[*src];
    238         dst[x] = SkDitherRGBTo565(SkGetPackedR32(c), SkGetPackedG32(c),
    239                                   SkGetPackedB32(c), DITHER_VALUE(x));
    240         src += deltaSrc;
    241     }
    242     return false;
    243 }
    244 
    245 static bool Sample_Index_D4444(void* SK_RESTRICT dstRow,
    246                                const uint8_t* SK_RESTRICT src, int width,
    247                                int deltaSrc, int y, const SkPMColor ctable[]) {
    248 
    249     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    250     SkPMColor cc = A32_MASK_IN_PLACE;
    251     for (int x = 0; x < width; x++) {
    252         SkPMColor c = ctable[*src];
    253         cc &= c;
    254         dst[x] = SkPixel32ToPixel4444(c);
    255         src += deltaSrc;
    256     }
    257     return cc != A32_MASK_IN_PLACE;
    258 }
    259 
    260 static bool Sample_Index_D4444_D(void* SK_RESTRICT dstRow,
    261                                  const uint8_t* SK_RESTRICT src, int width,
    262                                 int deltaSrc, int y, const SkPMColor ctable[]) {
    263 
    264     SkPMColor16* SK_RESTRICT dst = (SkPMColor16*)dstRow;
    265     SkPMColor cc = A32_MASK_IN_PLACE;
    266     DITHER_4444_SCAN(y);
    267 
    268     for (int x = 0; x < width; x++) {
    269         SkPMColor c = ctable[*src];
    270         cc &= c;
    271         dst[x] = SkDitherARGB32To4444(c, DITHER_VALUE(x));
    272         src += deltaSrc;
    273     }
    274     return cc != A32_MASK_IN_PLACE;
    275 }
    276 
    277 static bool Sample_Index_DI(void* SK_RESTRICT dstRow,
    278                             const uint8_t* SK_RESTRICT src,
    279                             int width, int deltaSrc, int, const SkPMColor[]) {
    280     if (1 == deltaSrc) {
    281         memcpy(dstRow, src, width);
    282     } else {
    283         uint8_t* SK_RESTRICT dst = (uint8_t*)dstRow;
    284         for (int x = 0; x < width; x++) {
    285             dst[x] = src[0];
    286             src += deltaSrc;
    287         }
    288     }
    289     return false;
    290 }
    291 
    292 // A8
    293 static bool Sample_Gray_DA8(void* SK_RESTRICT dstRow,
    294                             const uint8_t* SK_RESTRICT src,
    295                             int width, int deltaSrc, int,
    296                             const SkPMColor[]) {
    297     memcpy(dstRow, src, width);
    298     return true;
    299 }
    300 
    301 // 8888 Unpremul
    302 
    303 static bool Sample_Gray_D8888_Unpremul(void* SK_RESTRICT dstRow,
    304                                        const uint8_t* SK_RESTRICT src,
    305                                        int width, int deltaSrc, int,
    306                                        const SkPMColor[]) {
    307     uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
    308     for (int x = 0; x < width; x++) {
    309         dst[x] = SkPackARGB32NoCheck(0xFF, src[0], src[0], src[0]);
    310         src += deltaSrc;
    311     }
    312     return false;
    313 }
    314 
    315 // Sample_RGBx_D8888_Unpremul is no different from Sample_RGBx_D8888, since alpha
    316 // is 0xFF
    317 
    318 static bool Sample_RGBA_D8888_Unpremul(void* SK_RESTRICT dstRow,
    319                                        const uint8_t* SK_RESTRICT src,
    320                                        int width, int deltaSrc, int,
    321                                        const SkPMColor[]) {
    322     uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow);
    323     unsigned alphaMask = 0xFF;
    324     for (int x = 0; x < width; x++) {
    325         unsigned alpha = src[3];
    326         dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]);
    327         src += deltaSrc;
    328         alphaMask &= alpha;
    329     }
    330     return alphaMask != 0xFF;
    331 }
    332 
    333 // Sample_Index_D8888_Unpremul is the same as Sample_Index_D8888, since the
    334 // color table has its colors inserted unpremultiplied.
    335 
    336 ///////////////////////////////////////////////////////////////////////////////
    337 
    338 #include "SkScaledBitmapSampler.h"
    339 
    340 SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
    341                                              int sampleSize) {
    342     fCTable = NULL;
    343     fDstRow = NULL;
    344     fRowProc = NULL;
    345 
    346     if (width <= 0 || height <= 0) {
    347         sk_throw();
    348     }
    349 
    350     if (sampleSize <= 1) {
    351         fScaledWidth = width;
    352         fScaledHeight = height;
    353         fX0 = fY0 = 0;
    354         fDX = fDY = 1;
    355         return;
    356     }
    357 
    358     int dx = SkMin32(sampleSize, width);
    359     int dy = SkMin32(sampleSize, height);
    360 
    361     fScaledWidth = width / dx;
    362     fScaledHeight = height / dy;
    363 
    364     SkASSERT(fScaledWidth > 0);
    365     SkASSERT(fScaledHeight > 0);
    366 
    367     fX0 = dx >> 1;
    368     fY0 = dy >> 1;
    369 
    370     SkASSERT(fX0 >= 0 && fX0 < width);
    371     SkASSERT(fY0 >= 0 && fY0 < height);
    372 
    373     fDX = dx;
    374     fDY = dy;
    375 
    376     SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
    377     SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
    378 }
    379 
    380 bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
    381                                   const SkPMColor ctable[],
    382                                   bool requireUnpremul) {
    383     static const RowProc gProcs[] = {
    384         // 8888 (no dither distinction)
    385         Sample_Gray_D8888,              Sample_Gray_D8888,
    386         Sample_RGBx_D8888,              Sample_RGBx_D8888,
    387         Sample_RGBA_D8888,              Sample_RGBA_D8888,
    388         Sample_Index_D8888,             Sample_Index_D8888,
    389         NULL,                           NULL,
    390         // 565 (no alpha distinction)
    391         Sample_Gray_D565,               Sample_Gray_D565_D,
    392         Sample_RGBx_D565,               Sample_RGBx_D565_D,
    393         Sample_RGBx_D565,               Sample_RGBx_D565_D,
    394         Sample_Index_D565,              Sample_Index_D565_D,
    395         Sample_D565_D565,               Sample_D565_D565,
    396         // 4444
    397         Sample_Gray_D4444,              Sample_Gray_D4444_D,
    398         Sample_RGBx_D4444,              Sample_RGBx_D4444_D,
    399         Sample_RGBA_D4444,              Sample_RGBA_D4444_D,
    400         Sample_Index_D4444,             Sample_Index_D4444_D,
    401         NULL,                           NULL,
    402         // Index8
    403         NULL,                           NULL,
    404         NULL,                           NULL,
    405         NULL,                           NULL,
    406         Sample_Index_DI,                Sample_Index_DI,
    407         NULL,                           NULL,
    408         // A8
    409         Sample_Gray_DA8,                Sample_Gray_DA8,
    410         NULL,                           NULL,
    411         NULL,                           NULL,
    412         NULL,                           NULL,
    413         NULL,                           NULL,
    414         // 8888 Unpremul (no dither distinction)
    415         Sample_Gray_D8888_Unpremul,     Sample_Gray_D8888_Unpremul,
    416         Sample_RGBx_D8888,              Sample_RGBx_D8888,
    417         Sample_RGBA_D8888_Unpremul,     Sample_RGBA_D8888_Unpremul,
    418         Sample_Index_D8888,             Sample_Index_D8888,
    419         NULL,                           NULL,
    420     };
    421     // The jump between dst configs in the table
    422     static const int gProcDstConfigSpan = 10;
    423     SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gProcs) == 6 * gProcDstConfigSpan,
    424                       gProcs_has_the_wrong_number_of_entries);
    425 
    426     fCTable = ctable;
    427 
    428     int index = 0;
    429     if (dither) {
    430         index += 1;
    431     }
    432     switch (sc) {
    433         case SkScaledBitmapSampler::kGray:
    434             fSrcPixelSize = 1;
    435             index += 0;
    436             break;
    437         case SkScaledBitmapSampler::kRGB:
    438             fSrcPixelSize = 3;
    439             index += 2;
    440             break;
    441         case SkScaledBitmapSampler::kRGBX:
    442             fSrcPixelSize = 4;
    443             index += 2;
    444             break;
    445         case SkScaledBitmapSampler::kRGBA:
    446             fSrcPixelSize = 4;
    447             index += 4;
    448             break;
    449         case SkScaledBitmapSampler::kIndex:
    450             fSrcPixelSize = 1;
    451             index += 6;
    452             break;
    453         case SkScaledBitmapSampler::kRGB_565:
    454             fSrcPixelSize = 2;
    455             index += 8;
    456             break;
    457         default:
    458             return false;
    459     }
    460 
    461     switch (dst->config()) {
    462         case SkBitmap::kARGB_8888_Config:
    463             index += 0 * gProcDstConfigSpan;
    464             break;
    465         case SkBitmap::kRGB_565_Config:
    466             index += 1 * gProcDstConfigSpan;
    467             break;
    468         case SkBitmap::kARGB_4444_Config:
    469             index += 2 * gProcDstConfigSpan;
    470             break;
    471         case SkBitmap::kIndex8_Config:
    472             index += 3 * gProcDstConfigSpan;
    473             break;
    474         case SkBitmap::kA8_Config:
    475             index += 4 * gProcDstConfigSpan;
    476             break;
    477         default:
    478             return false;
    479     }
    480 
    481     if (requireUnpremul) {
    482         if (dst->config() != SkBitmap::kARGB_8888_Config) {
    483             return false;
    484         }
    485         index += 5 * gProcDstConfigSpan;
    486     }
    487 
    488     fRowProc = gProcs[index];
    489     fDstRow = (char*)dst->getPixels();
    490     fDstRowBytes = dst->rowBytes();
    491     fCurrY = 0;
    492     return fRowProc != NULL;
    493 }
    494 
    495 bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
    496     SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
    497 
    498     bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
    499                              fDX * fSrcPixelSize, fCurrY, fCTable);
    500     fDstRow += fDstRowBytes;
    501     fCurrY += 1;
    502     return hadAlpha;
    503 }
    504