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