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