Home | History | Annotate | Download | only in codec
      1 /*
      2  * Copyright 2015 Google Inc.
      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 #include "SkCodecPriv.h"
      9 #include "SkColorPriv.h"
     10 #include "SkMaskSwizzler.h"
     11 
     12 static void swizzle_mask16_to_n32_opaque(
     13         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
     14         uint32_t startX, uint32_t sampleX) {
     15 
     16     // Use the masks to decode to the destination
     17     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     18     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     19     for (int i = 0; i < width; i++) {
     20         uint16_t p = srcPtr[0];
     21         uint8_t red = masks->getRed(p);
     22         uint8_t green = masks->getGreen(p);
     23         uint8_t blue = masks->getBlue(p);
     24         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
     25         srcPtr += sampleX;
     26     }
     27 }
     28 
     29 static void swizzle_mask16_to_n32_unpremul(
     30         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
     31         uint32_t startX, uint32_t sampleX) {
     32 
     33     // Use the masks to decode to the destination
     34     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     35     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     36     for (int i = 0; i < width; i++) {
     37         uint16_t p = srcPtr[0];
     38         uint8_t red = masks->getRed(p);
     39         uint8_t green = masks->getGreen(p);
     40         uint8_t blue = masks->getBlue(p);
     41         uint8_t alpha = masks->getAlpha(p);
     42         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
     43         srcPtr += sampleX;
     44     }
     45 }
     46 
     47 static void swizzle_mask16_to_n32_premul(
     48         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
     49         uint32_t startX, uint32_t sampleX) {
     50 
     51     // Use the masks to decode to the destination
     52     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     53     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     54     for (int i = 0; i < width; i++) {
     55         uint16_t p = srcPtr[0];
     56         uint8_t red = masks->getRed(p);
     57         uint8_t green = masks->getGreen(p);
     58         uint8_t blue = masks->getBlue(p);
     59         uint8_t alpha = masks->getAlpha(p);
     60         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
     61         srcPtr += sampleX;
     62     }
     63 }
     64 
     65 // TODO (msarett): We have promoted a two byte per pixel image to 8888, only to
     66 // convert it back to 565. Instead, we should swizzle to 565 directly.
     67 static void swizzle_mask16_to_565(
     68         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
     69         uint32_t startX, uint32_t sampleX) {
     70 
     71     // Use the masks to decode to the destination
     72     uint16_t* srcPtr = ((uint16_t*) srcRow) + startX;
     73     uint16_t* dstPtr = (uint16_t*) dstRow;
     74     for (int i = 0; i < width; i++) {
     75         uint16_t p = srcPtr[0];
     76         uint8_t red = masks->getRed(p);
     77         uint8_t green = masks->getGreen(p);
     78         uint8_t blue = masks->getBlue(p);
     79         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
     80         srcPtr += sampleX;
     81     }
     82 }
     83 
     84 static void swizzle_mask24_to_n32_opaque(
     85         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
     86         uint32_t startX, uint32_t sampleX) {
     87 
     88     // Use the masks to decode to the destination
     89     srcRow += 3 * startX;
     90     SkPMColor* dstPtr = (SkPMColor*) dstRow;
     91     for (int i = 0; i < width; i++) {
     92         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
     93         uint8_t red = masks->getRed(p);
     94         uint8_t green = masks->getGreen(p);
     95         uint8_t blue = masks->getBlue(p);
     96         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
     97         srcRow += 3 * sampleX;
     98     }
     99 }
    100 
    101 static void swizzle_mask24_to_n32_unpremul(
    102         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    103         uint32_t startX, uint32_t sampleX) {
    104 
    105     // Use the masks to decode to the destination
    106     srcRow += 3 * startX;
    107     SkPMColor* dstPtr = (SkPMColor*) dstRow;
    108     for (int i = 0; i < width; i++) {
    109         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
    110         uint8_t red = masks->getRed(p);
    111         uint8_t green = masks->getGreen(p);
    112         uint8_t blue = masks->getBlue(p);
    113         uint8_t alpha = masks->getAlpha(p);
    114         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
    115         srcRow += 3 * sampleX;
    116     }
    117 }
    118 
    119 static void swizzle_mask24_to_n32_premul(
    120         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    121         uint32_t startX, uint32_t sampleX) {
    122 
    123     // Use the masks to decode to the destination
    124     srcRow += 3 * startX;
    125     SkPMColor* dstPtr = (SkPMColor*) dstRow;
    126     for (int i = 0; i < width; i++) {
    127         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
    128         uint8_t red = masks->getRed(p);
    129         uint8_t green = masks->getGreen(p);
    130         uint8_t blue = masks->getBlue(p);
    131         uint8_t alpha = masks->getAlpha(p);
    132         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
    133         srcRow += 3 * sampleX;
    134     }
    135 }
    136 
    137 static void swizzle_mask24_to_565(
    138         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    139         uint32_t startX, uint32_t sampleX) {
    140 
    141     // Use the masks to decode to the destination
    142     srcRow += 3 * startX;
    143     uint16_t* dstPtr = (uint16_t*) dstRow;
    144     for (int i = 0; i < width; i++) {
    145         uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16;
    146         uint8_t red = masks->getRed(p);
    147         uint8_t green = masks->getGreen(p);
    148         uint8_t blue = masks->getBlue(p);
    149         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
    150         srcRow += 3 * sampleX;
    151     }
    152 }
    153 
    154 static void swizzle_mask32_to_n32_opaque(
    155         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    156         uint32_t startX, uint32_t sampleX) {
    157 
    158     // Use the masks to decode to the destination
    159     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
    160     SkPMColor* dstPtr = (SkPMColor*) dstRow;
    161     for (int i = 0; i < width; i++) {
    162         uint32_t p = srcPtr[0];
    163         uint8_t red = masks->getRed(p);
    164         uint8_t green = masks->getGreen(p);
    165         uint8_t blue = masks->getBlue(p);
    166         dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue);
    167         srcPtr += sampleX;
    168     }
    169 }
    170 
    171 static void swizzle_mask32_to_n32_unpremul(
    172         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    173         uint32_t startX, uint32_t sampleX) {
    174 
    175     // Use the masks to decode to the destination
    176     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
    177     SkPMColor* dstPtr = (SkPMColor*) dstRow;
    178     for (int i = 0; i < width; i++) {
    179         uint32_t p = srcPtr[0];
    180         uint8_t red = masks->getRed(p);
    181         uint8_t green = masks->getGreen(p);
    182         uint8_t blue = masks->getBlue(p);
    183         uint8_t alpha = masks->getAlpha(p);
    184         dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
    185         srcPtr += sampleX;
    186     }
    187 }
    188 
    189 static void swizzle_mask32_to_n32_premul(
    190         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    191         uint32_t startX, uint32_t sampleX) {
    192 
    193     // Use the masks to decode to the destination
    194     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
    195     SkPMColor* dstPtr = (SkPMColor*) dstRow;
    196     for (int i = 0; i < width; i++) {
    197         uint32_t p = srcPtr[0];
    198         uint8_t red = masks->getRed(p);
    199         uint8_t green = masks->getGreen(p);
    200         uint8_t blue = masks->getBlue(p);
    201         uint8_t alpha = masks->getAlpha(p);
    202         dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue);
    203         srcPtr += sampleX;
    204     }
    205 }
    206 
    207 static void swizzle_mask32_to_565(
    208         void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks,
    209         uint32_t startX, uint32_t sampleX) {
    210     // Use the masks to decode to the destination
    211     uint32_t* srcPtr = ((uint32_t*) srcRow) + startX;
    212     uint16_t* dstPtr = (uint16_t*) dstRow;
    213     for (int i = 0; i < width; i++) {
    214         uint32_t p = srcPtr[0];
    215         uint8_t red = masks->getRed(p);
    216         uint8_t green = masks->getGreen(p);
    217         uint8_t blue = masks->getBlue(p);
    218         dstPtr[i] = SkPack888ToRGB16(red, green, blue);
    219         srcPtr += sampleX;
    220     }
    221 }
    222 
    223 /*
    224  *
    225  * Create a new mask swizzler
    226  *
    227  */
    228 SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler(const SkImageInfo& dstInfo,
    229         const SkImageInfo& srcInfo, SkMasks* masks, uint32_t bitsPerPixel,
    230         const SkCodec::Options& options) {
    231 
    232     // Choose the appropriate row procedure
    233     RowProc proc = nullptr;
    234     switch (bitsPerPixel) {
    235         case 16:
    236             switch (dstInfo.colorType()) {
    237                 case kN32_SkColorType:
    238                     if (kOpaque_SkAlphaType == srcInfo.alphaType()) {
    239                         proc = &swizzle_mask16_to_n32_opaque;
    240                     } else {
    241                         switch (dstInfo.alphaType()) {
    242                             case kUnpremul_SkAlphaType:
    243                                 proc = &swizzle_mask16_to_n32_unpremul;
    244                                 break;
    245                             case kPremul_SkAlphaType:
    246                                 proc = &swizzle_mask16_to_n32_premul;
    247                                 break;
    248                             default:
    249                                 break;
    250                         }
    251                     }
    252                     break;
    253                 case kRGB_565_SkColorType:
    254                     proc = &swizzle_mask16_to_565;
    255                     break;
    256                 default:
    257                     break;
    258             }
    259             break;
    260         case 24:
    261             switch (dstInfo.colorType()) {
    262                 case kN32_SkColorType:
    263                     if (kOpaque_SkAlphaType == srcInfo.alphaType()) {
    264                         proc = &swizzle_mask24_to_n32_opaque;
    265                     } else {
    266                         switch (dstInfo.alphaType()) {
    267                             case kUnpremul_SkAlphaType:
    268                                 proc = &swizzle_mask24_to_n32_unpremul;
    269                                 break;
    270                             case kPremul_SkAlphaType:
    271                                 proc = &swizzle_mask24_to_n32_premul;
    272                                 break;
    273                             default:
    274                                 break;
    275                         }
    276                     }
    277                     break;
    278                 case kRGB_565_SkColorType:
    279                     proc = &swizzle_mask24_to_565;
    280                     break;
    281                 default:
    282                     break;
    283             }
    284             break;
    285         case 32:
    286             switch (dstInfo.colorType()) {
    287                 case kN32_SkColorType:
    288                     if (kOpaque_SkAlphaType == srcInfo.alphaType()) {
    289                         proc = &swizzle_mask32_to_n32_opaque;
    290                     } else {
    291                         switch (dstInfo.alphaType()) {
    292                             case kUnpremul_SkAlphaType:
    293                                 proc = &swizzle_mask32_to_n32_unpremul;
    294                                 break;
    295                             case kPremul_SkAlphaType:
    296                                 proc = &swizzle_mask32_to_n32_premul;
    297                                 break;
    298                             default:
    299                                 break;
    300                         }
    301                     }
    302                     break;
    303                 case kRGB_565_SkColorType:
    304                     proc = &swizzle_mask32_to_565;
    305                     break;
    306                 default:
    307                     break;
    308             }
    309             break;
    310         default:
    311             SkASSERT(false);
    312             return nullptr;
    313     }
    314 
    315     int srcOffset = 0;
    316     int srcWidth = dstInfo.width();
    317     if (options.fSubset) {
    318         srcOffset = options.fSubset->left();
    319         srcWidth = options.fSubset->width();
    320     }
    321 
    322     return new SkMaskSwizzler(masks, proc, srcOffset, srcWidth);
    323 }
    324 
    325 /*
    326  *
    327  * Constructor for mask swizzler
    328  *
    329  */
    330 SkMaskSwizzler::SkMaskSwizzler(SkMasks* masks, RowProc proc, int srcOffset, int subsetWidth)
    331     : fMasks(masks)
    332     , fRowProc(proc)
    333     , fSubsetWidth(subsetWidth)
    334     , fDstWidth(subsetWidth)
    335     , fSampleX(1)
    336     , fSrcOffset(srcOffset)
    337     , fX0(srcOffset)
    338 {}
    339 
    340 int SkMaskSwizzler::onSetSampleX(int sampleX) {
    341     // FIXME: Share this function with SkSwizzler?
    342     SkASSERT(sampleX > 0); // Surely there is an upper limit? Should there be
    343                            // way to report failure?
    344     fSampleX = sampleX;
    345     fX0 = get_start_coord(sampleX) + fSrcOffset;
    346     fDstWidth = get_scaled_dimension(fSubsetWidth, sampleX);
    347 
    348     // check that fX0 is valid
    349     SkASSERT(fX0 >= 0);
    350     return fDstWidth;
    351 }
    352 
    353 /*
    354  *
    355  * Swizzle the specified row
    356  *
    357  */
    358 void SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) {
    359     SkASSERT(nullptr != dst && nullptr != src);
    360     fRowProc(dst, src, fDstWidth, fMasks, fX0, fSampleX);
    361 }
    362