Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2010 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 "SkImageInfoPriv.h"
      9 #include "SkSafeMath.h"
     10 #include "SkReadBuffer.h"
     11 #include "SkWriteBuffer.h"
     12 
     13 int SkColorTypeBytesPerPixel(SkColorType ct) {
     14     switch (ct) {
     15         case kUnknown_SkColorType:      return 0;
     16         case kAlpha_8_SkColorType:      return 1;
     17         case kRGB_565_SkColorType:      return 2;
     18         case kARGB_4444_SkColorType:    return 2;
     19         case kRGBA_8888_SkColorType:    return 4;
     20         case kBGRA_8888_SkColorType:    return 4;
     21         case kRGB_888x_SkColorType:     return 4;
     22         case kRGBA_1010102_SkColorType: return 4;
     23         case kRGB_101010x_SkColorType:  return 4;
     24         case kGray_8_SkColorType:       return 1;
     25         case kRGBA_F16_SkColorType:     return 8;
     26     }
     27     return 0;
     28 }
     29 
     30 // These values must be constant over revisions, though they can be renamed to reflect if/when
     31 // they are deprecated.
     32 enum Stored_SkColorType {
     33     kUnknown_Stored_SkColorType             = 0,
     34     kAlpha_8_Stored_SkColorType             = 1,
     35     kRGB_565_Stored_SkColorType             = 2,
     36     kARGB_4444_Stored_SkColorType           = 3,
     37     kRGBA_8888_Stored_SkColorType           = 4,
     38     kBGRA_8888_Stored_SkColorType           = 5,
     39     kIndex_8_Stored_SkColorType_DEPRECATED  = 6,
     40     kGray_8_Stored_SkColorType              = 7,
     41     kRGBA_F16_Stored_SkColorType            = 8,
     42     kRGB_888x_Stored_SkColorType            = 9,
     43     kRGBA_1010102_Stored_SkColorType        = 10,
     44     kRGB_101010x_Stored_SkColorType         = 11,
     45 };
     46 
     47 static uint8_t live_to_stored(unsigned ct) {
     48     switch (ct) {
     49         case kUnknown_SkColorType:      return kUnknown_Stored_SkColorType;
     50         case kAlpha_8_SkColorType:      return kAlpha_8_Stored_SkColorType;
     51         case kRGB_565_SkColorType:      return kRGB_565_Stored_SkColorType;
     52         case kARGB_4444_SkColorType:    return kARGB_4444_Stored_SkColorType;
     53         case kRGBA_8888_SkColorType:    return kRGBA_8888_Stored_SkColorType;
     54         case kRGB_888x_SkColorType:     return kRGB_888x_Stored_SkColorType;
     55         case kBGRA_8888_SkColorType:    return kBGRA_8888_Stored_SkColorType;
     56         case kRGBA_1010102_SkColorType: return kRGBA_1010102_Stored_SkColorType;
     57         case kRGB_101010x_SkColorType:  return kRGB_101010x_Stored_SkColorType;
     58         case kGray_8_SkColorType:       return kGray_8_Stored_SkColorType;
     59         case kRGBA_F16_SkColorType:     return kRGBA_F16_Stored_SkColorType;
     60     }
     61     return kUnknown_Stored_SkColorType;
     62 }
     63 
     64 static SkColorType stored_to_live(unsigned stored) {
     65     switch (stored) {
     66         case kUnknown_Stored_SkColorType:            return kUnknown_SkColorType;
     67         case kAlpha_8_Stored_SkColorType:            return kAlpha_8_SkColorType;
     68         case kRGB_565_Stored_SkColorType:            return kRGB_565_SkColorType;
     69         case kARGB_4444_Stored_SkColorType:          return kARGB_4444_SkColorType;
     70         case kRGBA_8888_Stored_SkColorType:          return kRGBA_8888_SkColorType;
     71         case kRGB_888x_Stored_SkColorType:           return kRGB_888x_SkColorType;
     72         case kBGRA_8888_Stored_SkColorType:          return kBGRA_8888_SkColorType;
     73         case kRGBA_1010102_Stored_SkColorType:       return kRGBA_1010102_SkColorType;
     74         case kRGB_101010x_Stored_SkColorType:        return kRGB_101010x_SkColorType;
     75         case kIndex_8_Stored_SkColorType_DEPRECATED: return kUnknown_SkColorType;
     76         case kGray_8_Stored_SkColorType:             return kGray_8_SkColorType;
     77         case kRGBA_F16_Stored_SkColorType:           return kRGBA_F16_SkColorType;
     78     }
     79     return kUnknown_SkColorType;
     80 }
     81 
     82 bool SkColorTypeIsAlwaysOpaque(SkColorType ct) {
     83     switch (ct) {
     84         case kRGB_565_SkColorType:
     85         case kRGB_888x_SkColorType:
     86         case kRGB_101010x_SkColorType:
     87         case kGray_8_SkColorType:
     88             return true;
     89         default:
     90             break;
     91     }
     92     return false;
     93 }
     94 
     95 ///////////////////////////////////////////////////////////////////////////////////////////////////
     96 
     97 int SkImageInfo::bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
     98 
     99 int SkImageInfo::shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
    100 
    101 size_t SkImageInfo::computeOffset(int x, int y, size_t rowBytes) const {
    102     SkASSERT((unsigned)x < (unsigned)fWidth);
    103     SkASSERT((unsigned)y < (unsigned)fHeight);
    104     return SkColorTypeComputeOffset(fColorType, x, y, rowBytes);
    105 }
    106 
    107 size_t SkImageInfo::computeByteSize(size_t rowBytes) const {
    108     if (0 == fHeight) {
    109         return 0;
    110     }
    111     SkSafeMath safe;
    112     size_t bytes = safe.add(safe.mul(fHeight - 1, rowBytes),
    113                             safe.mul(fWidth, this->bytesPerPixel()));
    114     return safe ? bytes : SK_MaxSizeT;
    115 }
    116 
    117 static bool alpha_type_is_valid(SkAlphaType alphaType) {
    118     return (alphaType >= kUnknown_SkAlphaType) && (alphaType <= kLastEnum_SkAlphaType);
    119 }
    120 
    121 static bool color_type_is_valid(SkColorType colorType) {
    122     return (colorType >= kUnknown_SkColorType) && (colorType <= kLastEnum_SkColorType);
    123 }
    124 
    125 SkImageInfo SkImageInfo::MakeS32(int width, int height, SkAlphaType at) {
    126     return SkImageInfo(width, height, kN32_SkColorType, at,
    127                        SkColorSpace::MakeSRGB());
    128 }
    129 
    130 static const int kColorTypeMask = 0x0F;
    131 static const int kAlphaTypeMask = 0x03;
    132 
    133 void SkImageInfo::unflatten(SkReadBuffer& buffer) {
    134     fWidth = buffer.read32();
    135     fHeight = buffer.read32();
    136 
    137     uint32_t packed = buffer.read32();
    138     fColorType = stored_to_live((packed >> 0) & kColorTypeMask);
    139     fAlphaType = (SkAlphaType)((packed >> 8) & kAlphaTypeMask);
    140     buffer.validate(alpha_type_is_valid(fAlphaType) && color_type_is_valid(fColorType));
    141 
    142     sk_sp<SkData> data = buffer.readByteArrayAsData();
    143     fColorSpace = SkColorSpace::Deserialize(data->data(), data->size());
    144 }
    145 
    146 void SkImageInfo::flatten(SkWriteBuffer& buffer) const {
    147     buffer.write32(fWidth);
    148     buffer.write32(fHeight);
    149 
    150     SkASSERT(0 == (fAlphaType & ~kAlphaTypeMask));
    151     SkASSERT(0 == (fColorType & ~kColorTypeMask));
    152     uint32_t packed = (fAlphaType << 8) | live_to_stored(fColorType);
    153     buffer.write32(packed);
    154 
    155     if (fColorSpace) {
    156         sk_sp<SkData> data = fColorSpace->serialize();
    157         if (data) {
    158             buffer.writeDataAsByteArray(data.get());
    159         } else {
    160             buffer.writeByteArray(nullptr, 0);
    161         }
    162     } else {
    163         sk_sp<SkData> data = SkData::MakeEmpty();
    164         buffer.writeDataAsByteArray(data.get());
    165     }
    166 }
    167 
    168 bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
    169                                   SkAlphaType* canonical) {
    170     switch (colorType) {
    171         case kUnknown_SkColorType:
    172             alphaType = kUnknown_SkAlphaType;
    173             break;
    174         case kAlpha_8_SkColorType:
    175             if (kUnpremul_SkAlphaType == alphaType) {
    176                 alphaType = kPremul_SkAlphaType;
    177             }
    178             // fall-through
    179         case kARGB_4444_SkColorType:
    180         case kRGBA_8888_SkColorType:
    181         case kBGRA_8888_SkColorType:
    182         case kRGBA_1010102_SkColorType:
    183         case kRGBA_F16_SkColorType:
    184             if (kUnknown_SkAlphaType == alphaType) {
    185                 return false;
    186             }
    187             break;
    188         case kGray_8_SkColorType:
    189         case kRGB_565_SkColorType:
    190         case kRGB_888x_SkColorType:
    191         case kRGB_101010x_SkColorType:
    192             alphaType = kOpaque_SkAlphaType;
    193             break;
    194         default:
    195             return false;
    196     }
    197     if (canonical) {
    198         *canonical = alphaType;
    199     }
    200     return true;
    201 }
    202 
    203 ///////////////////////////////////////////////////////////////////////////////////////////////////
    204 
    205 #include "SkReadPixelsRec.h"
    206 
    207 bool SkReadPixelsRec::trim(int srcWidth, int srcHeight) {
    208     if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
    209         return false;
    210     }
    211     if (0 >= fInfo.width() || 0 >= fInfo.height()) {
    212         return false;
    213     }
    214 
    215     int x = fX;
    216     int y = fY;
    217     SkIRect srcR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
    218     if (!srcR.intersect(0, 0, srcWidth, srcHeight)) {
    219         return false;
    220     }
    221 
    222     // if x or y are negative, then we have to adjust pixels
    223     if (x > 0) {
    224         x = 0;
    225     }
    226     if (y > 0) {
    227         y = 0;
    228     }
    229     // here x,y are either 0 or negative
    230     fPixels = ((char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
    231     // the intersect may have shrunk info's logical size
    232     fInfo = fInfo.makeWH(srcR.width(), srcR.height());
    233     fX = srcR.x();
    234     fY = srcR.y();
    235 
    236     return true;
    237 }
    238 
    239 ///////////////////////////////////////////////////////////////////////////////////////////////////
    240 
    241 #include "SkWritePixelsRec.h"
    242 
    243 bool SkWritePixelsRec::trim(int dstWidth, int dstHeight) {
    244     if (nullptr == fPixels || fRowBytes < fInfo.minRowBytes()) {
    245         return false;
    246     }
    247     if (0 >= fInfo.width() || 0 >= fInfo.height()) {
    248         return false;
    249     }
    250 
    251     int x = fX;
    252     int y = fY;
    253     SkIRect dstR = SkIRect::MakeXYWH(x, y, fInfo.width(), fInfo.height());
    254     if (!dstR.intersect(0, 0, dstWidth, dstHeight)) {
    255         return false;
    256     }
    257 
    258     // if x or y are negative, then we have to adjust pixels
    259     if (x > 0) {
    260         x = 0;
    261     }
    262     if (y > 0) {
    263         y = 0;
    264     }
    265     // here x,y are either 0 or negative
    266     fPixels = ((const char*)fPixels - y * fRowBytes - x * fInfo.bytesPerPixel());
    267     // the intersect may have shrunk info's logical size
    268     fInfo = fInfo.makeWH(dstR.width(), dstR.height());
    269     fX = dstR.x();
    270     fY = dstR.y();
    271 
    272     return true;
    273 }
    274