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