Home | History | Annotate | Download | only in images
      1 
      2 /*
      3  * Copyright 2012 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  * Functions to transform scanlines between packed-pixel formats.
     11  */
     12 
     13 #include "SkBitmap.h"
     14 #include "SkColor.h"
     15 #include "SkColorPriv.h"
     16 #include "SkPreConfig.h"
     17 #include "SkUnPreMultiply.h"
     18 
     19 /**
     20  * Function template for transforming scanlines.
     21  * Transform 'width' pixels from 'src' buffer into 'dst' buffer,
     22  * repacking color channel data as appropriate for the given transformation.
     23  */
     24 typedef void (*transform_scanline_proc)(const char* SK_RESTRICT src,
     25                                         int width, char* SK_RESTRICT dst);
     26 
     27 /**
     28  * Identity transformation: just copy bytes from src to dst.
     29  */
     30 static void transform_scanline_memcpy(const char* SK_RESTRICT src, int width,
     31                                       char* SK_RESTRICT dst) {
     32     memcpy(dst, src, width);
     33 }
     34 
     35 /**
     36  * Transform from kRGB_565_Config to 3-bytes-per-pixel RGB.
     37  * Alpha channel data is not present in kRGB_565_Config format, so there is no
     38  * alpha channel data to preserve.
     39  */
     40 static void transform_scanline_565(const char* SK_RESTRICT src, int width,
     41                                    char* SK_RESTRICT dst) {
     42     const uint16_t* SK_RESTRICT srcP = (const uint16_t*)src;
     43     for (int i = 0; i < width; i++) {
     44         unsigned c = *srcP++;
     45         *dst++ = SkPacked16ToR32(c);
     46         *dst++ = SkPacked16ToG32(c);
     47         *dst++ = SkPacked16ToB32(c);
     48     }
     49 }
     50 
     51 /**
     52  * Transform from kARGB_8888_Config to 3-bytes-per-pixel RGB.
     53  * Alpha channel data, if any, is abandoned.
     54  */
     55 static void transform_scanline_888(const char* SK_RESTRICT src, int width,
     56                                    char* SK_RESTRICT dst) {
     57     const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src;
     58     for (int i = 0; i < width; i++) {
     59         SkPMColor c = *srcP++;
     60         *dst++ = SkGetPackedR32(c);
     61         *dst++ = SkGetPackedG32(c);
     62         *dst++ = SkGetPackedB32(c);
     63     }
     64 }
     65 
     66 /**
     67  * Transform from kARGB_4444_Config to 3-bytes-per-pixel RGB.
     68  * Alpha channel data, if any, is abandoned.
     69  */
     70 static void transform_scanline_444(const char* SK_RESTRICT src, int width,
     71                                    char* SK_RESTRICT dst) {
     72     const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src;
     73     for (int i = 0; i < width; i++) {
     74         SkPMColor16 c = *srcP++;
     75         *dst++ = SkPacked4444ToR32(c);
     76         *dst++ = SkPacked4444ToG32(c);
     77         *dst++ = SkPacked4444ToB32(c);
     78     }
     79 }
     80 
     81 /**
     82  * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA.
     83  * (This would be the identity transformation, except for byte-order and
     84  * scaling of RGB based on alpha channel).
     85  */
     86 static void transform_scanline_8888(const char* SK_RESTRICT src, int width,
     87                                     char* SK_RESTRICT dst) {
     88     const SkPMColor* SK_RESTRICT srcP = (const SkPMColor*)src;
     89     const SkUnPreMultiply::Scale* SK_RESTRICT table =
     90                                               SkUnPreMultiply::GetScaleTable();
     91 
     92     for (int i = 0; i < width; i++) {
     93         SkPMColor c = *srcP++;
     94         unsigned a = SkGetPackedA32(c);
     95         unsigned r = SkGetPackedR32(c);
     96         unsigned g = SkGetPackedG32(c);
     97         unsigned b = SkGetPackedB32(c);
     98 
     99         if (0 != a && 255 != a) {
    100             SkUnPreMultiply::Scale scale = table[a];
    101             r = SkUnPreMultiply::ApplyScale(scale, r);
    102             g = SkUnPreMultiply::ApplyScale(scale, g);
    103             b = SkUnPreMultiply::ApplyScale(scale, b);
    104         }
    105         *dst++ = r;
    106         *dst++ = g;
    107         *dst++ = b;
    108         *dst++ = a;
    109     }
    110 }
    111 
    112 /**
    113  * Transform from kARGB_8888_Config to 4-bytes-per-pixel RGBA,
    114  * with scaling of RGB based on alpha channel.
    115  */
    116 static void transform_scanline_4444(const char* SK_RESTRICT src, int width,
    117                                     char* SK_RESTRICT dst) {
    118     const SkPMColor16* SK_RESTRICT srcP = (const SkPMColor16*)src;
    119     const SkUnPreMultiply::Scale* SK_RESTRICT table =
    120                                               SkUnPreMultiply::GetScaleTable();
    121 
    122     for (int i = 0; i < width; i++) {
    123         SkPMColor16 c = *srcP++;
    124         unsigned a = SkPacked4444ToA32(c);
    125         unsigned r = SkPacked4444ToR32(c);
    126         unsigned g = SkPacked4444ToG32(c);
    127         unsigned b = SkPacked4444ToB32(c);
    128 
    129         if (0 != a && 255 != a) {
    130             SkUnPreMultiply::Scale scale = table[a];
    131             r = SkUnPreMultiply::ApplyScale(scale, r);
    132             g = SkUnPreMultiply::ApplyScale(scale, g);
    133             b = SkUnPreMultiply::ApplyScale(scale, b);
    134         }
    135         *dst++ = r;
    136         *dst++ = g;
    137         *dst++ = b;
    138         *dst++ = a;
    139     }
    140 }
    141