1/* 2 * Copyright 2013 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#ifndef SkImageInfo_DEFINED 9#define SkImageInfo_DEFINED 10 11#include "SkColorSpace.h" 12#include "SkMath.h" 13#include "SkRect.h" 14#include "SkSize.h" 15 16class SkReadBuffer; 17class SkWriteBuffer; 18 19/** 20 * Describes how to interpret the alpha component of a pixel. 21 */ 22enum SkAlphaType { 23 kUnknown_SkAlphaType, 24 25 /** 26 * All pixels are stored as opaque. This differs slightly from kIgnore in 27 * that kOpaque has correct "opaque" values stored in the pixels, while 28 * kIgnore may not, but in both cases the caller should treat the pixels 29 * as opaque. 30 */ 31 kOpaque_SkAlphaType, 32 33 /** 34 * All pixels have their alpha premultiplied in their color components. 35 * This is the natural format for the rendering target pixels. 36 */ 37 kPremul_SkAlphaType, 38 39 /** 40 * All pixels have their color components stored without any regard to the 41 * alpha. e.g. this is the default configuration for PNG images. 42 * 43 * This alpha-type is ONLY supported for input images. Rendering cannot 44 * generate this on output. 45 */ 46 kUnpremul_SkAlphaType, 47 48 kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, 49}; 50 51static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) { 52 return kOpaque_SkAlphaType == at; 53} 54 55static inline bool SkAlphaTypeIsValid(unsigned value) { 56 return value <= kLastEnum_SkAlphaType; 57} 58 59/////////////////////////////////////////////////////////////////////////////// 60 61/** Temporary macro that allows us to add new color types without breaking Chrome compile. */ 62#define SK_EXTENDED_COLOR_TYPES 63 64/** 65 * Describes how to interpret the components of a pixel. 66 * 67 * kN32_SkColorType is an alias for whichever 32bit ARGB format is the "native" 68 * form for skia's blitters. Use this if you don't have a swizzle preference 69 * for 32bit pixels. 70 */ 71enum SkColorType { 72 kUnknown_SkColorType, 73 kAlpha_8_SkColorType, 74 kRGB_565_SkColorType, 75 kARGB_4444_SkColorType, 76 kRGBA_8888_SkColorType, 77 kRGB_888x_SkColorType, 78 kBGRA_8888_SkColorType, 79 kRGBA_1010102_SkColorType, 80 kRGB_101010x_SkColorType, 81 kGray_8_SkColorType, 82 kRGBA_F16_SkColorType, 83 84 kLastEnum_SkColorType = kRGBA_F16_SkColorType, 85 86#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) 87 kN32_SkColorType = kBGRA_8888_SkColorType, 88#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) 89 kN32_SkColorType = kRGBA_8888_SkColorType, 90#else 91 #error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order" 92#endif 93}; 94 95static int SkColorTypeBytesPerPixel(SkColorType ct) { 96 switch (ct) { 97 case kUnknown_SkColorType: return 0; 98 case kAlpha_8_SkColorType: return 1; 99 case kRGB_565_SkColorType: return 2; 100 case kARGB_4444_SkColorType: return 2; 101 case kRGBA_8888_SkColorType: return 4; 102 case kBGRA_8888_SkColorType: return 4; 103 case kRGB_888x_SkColorType: return 4; 104 case kRGBA_1010102_SkColorType: return 4; 105 case kRGB_101010x_SkColorType: return 4; 106 case kGray_8_SkColorType: return 1; 107 case kRGBA_F16_SkColorType: return 8; 108 } 109 return 0; 110} 111 112static int SkColorTypeShiftPerPixel(SkColorType ct) { 113 switch (ct) { 114 case kUnknown_SkColorType: return 0; 115 case kAlpha_8_SkColorType: return 0; 116 case kRGB_565_SkColorType: return 1; 117 case kARGB_4444_SkColorType: return 1; 118 case kRGBA_8888_SkColorType: return 2; 119 case kRGB_888x_SkColorType: return 2; 120 case kBGRA_8888_SkColorType: return 2; 121 case kRGBA_1010102_SkColorType: return 2; 122 case kRGB_101010x_SkColorType: return 2; 123 case kGray_8_SkColorType: return 0; 124 case kRGBA_F16_SkColorType: return 3; 125 } 126 return 0; 127} 128 129static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) { 130 return width * SkColorTypeBytesPerPixel(ct); 131} 132 133static inline bool SkColorTypeIsValid(unsigned value) { 134 return value <= kLastEnum_SkColorType; 135} 136 137static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) { 138 if (kUnknown_SkColorType == ct) { 139 return 0; 140 } 141 return y * rowBytes + (x << SkColorTypeShiftPerPixel(ct)); 142} 143 144/////////////////////////////////////////////////////////////////////////////// 145 146/** 147 * Return true if alphaType is supported by colorType. If there is a canonical 148 * alphaType for this colorType, return it in canonical. 149 */ 150bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType, 151 SkAlphaType* canonical = nullptr); 152 153/////////////////////////////////////////////////////////////////////////////// 154 155/** 156 * Describes the color space a YUV pixel. 157 */ 158enum SkYUVColorSpace { 159 /** Standard JPEG color space. */ 160 kJPEG_SkYUVColorSpace, 161 /** SDTV standard Rec. 601 color space. Uses "studio swing" [16, 235] color 162 range. See http://en.wikipedia.org/wiki/Rec._601 for details. */ 163 kRec601_SkYUVColorSpace, 164 /** HDTV standard Rec. 709 color space. Uses "studio swing" [16, 235] color 165 range. See http://en.wikipedia.org/wiki/Rec._709 for details. */ 166 kRec709_SkYUVColorSpace, 167 168 kLastEnum_SkYUVColorSpace = kRec709_SkYUVColorSpace, 169}; 170 171/////////////////////////////////////////////////////////////////////////////// 172 173enum class SkDestinationSurfaceColorMode { 174 kLegacy, 175 kGammaAndColorSpaceAware, 176}; 177 178/** 179 * Describe an image's dimensions and pixel type. 180 * Used for both src images and render-targets (surfaces). 181 */ 182struct SK_API SkImageInfo { 183public: 184 SkImageInfo() 185 : fColorSpace(nullptr) 186 , fWidth(0) 187 , fHeight(0) 188 , fColorType(kUnknown_SkColorType) 189 , fAlphaType(kUnknown_SkAlphaType) 190 {} 191 192 static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at, 193 sk_sp<SkColorSpace> cs = nullptr) { 194 return SkImageInfo(width, height, ct, at, std::move(cs)); 195 } 196 197 /** 198 * Sets colortype to the native ARGB32 type. 199 */ 200 static SkImageInfo MakeN32(int width, int height, SkAlphaType at, 201 sk_sp<SkColorSpace> cs = nullptr) { 202 return Make(width, height, kN32_SkColorType, at, cs); 203 } 204 205 /** 206 * Create an ImageInfo marked as SRGB with N32 swizzle. 207 */ 208 static SkImageInfo MakeS32(int width, int height, SkAlphaType at); 209 210 /** 211 * Sets colortype to the native ARGB32 type, and the alphatype to premul. 212 */ 213 static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) { 214 return Make(width, height, kN32_SkColorType, kPremul_SkAlphaType, cs); 215 } 216 217 static SkImageInfo MakeN32Premul(const SkISize& size) { 218 return MakeN32Premul(size.width(), size.height()); 219 } 220 221 static SkImageInfo MakeA8(int width, int height) { 222 return Make(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr); 223 } 224 225 static SkImageInfo MakeUnknown(int width, int height) { 226 return Make(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr); 227 } 228 229 static SkImageInfo MakeUnknown() { 230 return MakeUnknown(0, 0); 231 } 232 233 int width() const { return fWidth; } 234 int height() const { return fHeight; } 235 SkColorType colorType() const { return fColorType; } 236 SkAlphaType alphaType() const { return fAlphaType; } 237 SkColorSpace* colorSpace() const { return fColorSpace.get(); } 238 sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; } 239 240 bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; } 241 242 bool isOpaque() const { 243 return SkAlphaTypeIsOpaque(fAlphaType); 244 } 245 246 SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); } 247 SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); } 248 249 bool gammaCloseToSRGB() const { 250 return fColorSpace && fColorSpace->gammaCloseToSRGB(); 251 } 252 253 /** 254 * Return a new ImageInfo with the same colortype and alphatype as this info, 255 * but with the specified width and height. 256 */ 257 SkImageInfo makeWH(int newWidth, int newHeight) const { 258 return Make(newWidth, newHeight, fColorType, fAlphaType, fColorSpace); 259 } 260 261 SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const { 262 return Make(fWidth, fHeight, fColorType, newAlphaType, fColorSpace); 263 } 264 265 SkImageInfo makeColorType(SkColorType newColorType) const { 266 return Make(fWidth, fHeight, newColorType, fAlphaType, fColorSpace); 267 } 268 269 SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const { 270 return Make(fWidth, fHeight, fColorType, fAlphaType, std::move(cs)); 271 } 272 273 int bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); } 274 275 int shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); } 276 277 uint64_t minRowBytes64() const { 278 return sk_64_mul(fWidth, this->bytesPerPixel()); 279 } 280 281 size_t minRowBytes() const { 282 uint64_t minRowBytes = this->minRowBytes64(); 283 if (!sk_64_isS32(minRowBytes)) { 284 return 0; 285 } 286 return sk_64_asS32(minRowBytes); 287 } 288 289 size_t computeOffset(int x, int y, size_t rowBytes) const { 290 SkASSERT((unsigned)x < (unsigned)fWidth); 291 SkASSERT((unsigned)y < (unsigned)fHeight); 292 return SkColorTypeComputeOffset(fColorType, x, y, rowBytes); 293 } 294 295 bool operator==(const SkImageInfo& other) const { 296 return fWidth == other.fWidth && fHeight == other.fHeight && 297 fColorType == other.fColorType && fAlphaType == other.fAlphaType && 298 SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get()); 299 } 300 bool operator!=(const SkImageInfo& other) const { 301 return !(*this == other); 302 } 303 304 void unflatten(SkReadBuffer& buffer); 305 void flatten(SkWriteBuffer& buffer) const; 306 307 /** 308 * Returns the size (in bytes) of the image buffer that this info needs, given the specified 309 * rowBytes. The rowBytes must be >= this->minRowBytes(). 310 * 311 * if (height == 0) { 312 * return 0; 313 * } else { 314 * return (height - 1) * rowBytes + width * bytes_per_pixel; 315 * } 316 * 317 * If the calculation overflows this returns SK_MaxSizeT 318 */ 319 size_t computeByteSize(size_t rowBytes) const; 320 321 /** 322 * Returns the minimum size (in bytes) of the image buffer that this info needs. 323 * If the calculation overflows, or if the height is 0, this returns 0. 324 */ 325 size_t computeMinByteSize() const { 326 return this->computeByteSize(this->minRowBytes()); 327 } 328 329 // Returns true if the result of computeByteSize (or computeMinByteSize) overflowed 330 static bool ByteSizeOverflowed(size_t byteSize) { 331 return SK_MaxSizeT == byteSize; 332 } 333 334 bool validRowBytes(size_t rowBytes) const { 335 uint64_t minRB = sk_64_mul(fWidth, this->bytesPerPixel()); 336 return rowBytes >= minRB; 337 } 338 339 void reset() { 340 fColorSpace = nullptr; 341 fWidth = 0; 342 fHeight = 0; 343 fColorType = kUnknown_SkColorType; 344 fAlphaType = kUnknown_SkAlphaType; 345 } 346 347 SkDEBUGCODE(void validate() const;) 348 349private: 350 sk_sp<SkColorSpace> fColorSpace; 351 int fWidth; 352 int fHeight; 353 SkColorType fColorType; 354 SkAlphaType fAlphaType; 355 356 SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs) 357 : fColorSpace(std::move(cs)) 358 , fWidth(width) 359 , fHeight(height) 360 , fColorType(ct) 361 , fAlphaType(at) 362 {} 363}; 364 365#endif 366