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