Home | History | Annotate | Download | only in images
      1 
      2 /*
      3  * Copyright 2007 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 #include "SkScaledBitmapSampler.h"
     11 #include "SkBitmap.h"
     12 #include "SkColorPriv.h"
     13 #include "SkDither.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 ///////////////////////////////////////////////////////////////////////////////
    293 
    294 #include "SkScaledBitmapSampler.h"
    295 
    296 SkScaledBitmapSampler::SkScaledBitmapSampler(int width, int height,
    297                                              int sampleSize) {
    298     if (width <= 0 || height <= 0) {
    299         sk_throw();
    300     }
    301 
    302     if (sampleSize <= 1) {
    303         fScaledWidth = width;
    304         fScaledHeight = height;
    305         fX0 = fY0 = 0;
    306         fDX = fDY = 1;
    307         return;
    308     }
    309 
    310     int dx = SkMin32(sampleSize, width);
    311     int dy = SkMin32(sampleSize, height);
    312 
    313     fScaledWidth = width / dx;
    314     fScaledHeight = height / dy;
    315 
    316     SkASSERT(fScaledWidth > 0);
    317     SkASSERT(fScaledHeight > 0);
    318 
    319     fX0 = dx >> 1;
    320     fY0 = dy >> 1;
    321 
    322     SkASSERT(fX0 >= 0 && fX0 < width);
    323     SkASSERT(fY0 >= 0 && fY0 < height);
    324 
    325     fDX = dx;
    326     fDY = dy;
    327 
    328     SkASSERT(fDX > 0 && (fX0 + fDX * (fScaledWidth - 1)) < width);
    329     SkASSERT(fDY > 0 && (fY0 + fDY * (fScaledHeight - 1)) < height);
    330 
    331     fRowProc = NULL;
    332     fCTable = NULL;
    333 }
    334 
    335 bool SkScaledBitmapSampler::begin(SkBitmap* dst, SrcConfig sc, bool dither,
    336                                   const SkPMColor ctable[]) {
    337     static const RowProc gProcs[] = {
    338         // 8888 (no dither distinction)
    339         Sample_Gray_D8888,  Sample_Gray_D8888,
    340         Sample_RGBx_D8888,  Sample_RGBx_D8888,
    341         Sample_RGBA_D8888,  Sample_RGBA_D8888,
    342         Sample_Index_D8888, Sample_Index_D8888,
    343         NULL,               NULL,
    344         // 565 (no alpha distinction)
    345         Sample_Gray_D565,   Sample_Gray_D565_D,
    346         Sample_RGBx_D565,   Sample_RGBx_D565_D,
    347         Sample_RGBx_D565,   Sample_RGBx_D565_D,
    348         Sample_Index_D565,  Sample_Index_D565_D,
    349         Sample_D565_D565,   Sample_D565_D565,
    350         // 4444
    351         Sample_Gray_D4444,  Sample_Gray_D4444_D,
    352         Sample_RGBx_D4444,  Sample_RGBx_D4444_D,
    353         Sample_RGBA_D4444,  Sample_RGBA_D4444_D,
    354         Sample_Index_D4444, Sample_Index_D4444_D,
    355         NULL,               NULL,
    356         // Index8
    357         NULL,               NULL,
    358         NULL,               NULL,
    359         NULL,               NULL,
    360         Sample_Index_DI,    Sample_Index_DI,
    361         NULL,               NULL,
    362     };
    363 
    364     fCTable = ctable;
    365 
    366     int index = 0;
    367     if (dither) {
    368         index += 1;
    369     }
    370     switch (sc) {
    371         case SkScaledBitmapSampler::kGray:
    372             fSrcPixelSize = 1;
    373             index += 0;
    374             break;
    375         case SkScaledBitmapSampler::kRGB:
    376             fSrcPixelSize = 3;
    377             index += 2;
    378             break;
    379         case SkScaledBitmapSampler::kRGBX:
    380             fSrcPixelSize = 4;
    381             index += 2;
    382             break;
    383         case SkScaledBitmapSampler::kRGBA:
    384             fSrcPixelSize = 4;
    385             index += 4;
    386             break;
    387         case SkScaledBitmapSampler::kIndex:
    388             fSrcPixelSize = 1;
    389             index += 6;
    390             break;
    391         case SkScaledBitmapSampler::kRGB_565:
    392             fSrcPixelSize = 2;
    393             index += 8;
    394             break;
    395         default:
    396             return false;
    397     }
    398 
    399     switch (dst->config()) {
    400         case SkBitmap::kARGB_8888_Config:
    401             index += 0;
    402             break;
    403         case SkBitmap::kRGB_565_Config:
    404             index += 10;
    405             break;
    406         case SkBitmap::kARGB_4444_Config:
    407             index += 20;
    408             break;
    409         case SkBitmap::kIndex8_Config:
    410             index += 30;
    411             break;
    412         default:
    413             return false;
    414     }
    415 
    416     fRowProc = gProcs[index];
    417     fDstRow = (char*)dst->getPixels();
    418     fDstRowBytes = dst->rowBytes();
    419     fCurrY = 0;
    420     return fRowProc != NULL;
    421 }
    422 
    423 bool SkScaledBitmapSampler::next(const uint8_t* SK_RESTRICT src) {
    424     SkASSERT((unsigned)fCurrY < (unsigned)fScaledHeight);
    425 
    426     bool hadAlpha = fRowProc(fDstRow, src + fX0 * fSrcPixelSize, fScaledWidth,
    427                              fDX * fSrcPixelSize, fCurrY, fCTable);
    428     fDstRow += fDstRowBytes;
    429     fCurrY += 1;
    430     return hadAlpha;
    431 }
    432