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