| 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 "include/core/SkColorSpace.h" |
| 12 | #include "include/core/SkMath.h" |
| 13 | #include "include/core/SkRect.h" |
| 14 | #include "include/core/SkSize.h" |
| 15 | |
| 16 | #include "include/private/SkTFitsIn.h" |
| 17 | #include "include/private/SkTo.h" |
| 18 | |
| 19 | class SkReadBuffer; |
| 20 | class SkWriteBuffer; |
| 21 | |
| 22 | /** \enum SkImageInfo::SkAlphaType |
| 23 | Describes how to interpret the alpha component of a pixel. A pixel may |
| 24 | be opaque, or alpha, describing multiple levels of transparency. |
| 25 | |
| 26 | In simple blending, alpha weights the draw color and the destination |
| 27 | color to create a new color. If alpha describes a weight from zero to one: |
| 28 | |
| 29 | new color = draw color * alpha + destination color * (1 - alpha) |
| 30 | |
| 31 | In practice alpha is encoded in two or more bits, where 1.0 equals all bits set. |
| 32 | |
| 33 | RGB may have alpha included in each component value; the stored |
| 34 | value is the original RGB multiplied by alpha. Premultiplied color |
| 35 | components improve performance. |
| 36 | */ |
| 37 | enum SkAlphaType { |
| 38 | kUnknown_SkAlphaType, //!< uninitialized |
| 39 | kOpaque_SkAlphaType, //!< pixel is opaque |
| 40 | kPremul_SkAlphaType, //!< pixel components are premultiplied by alpha |
| 41 | kUnpremul_SkAlphaType, //!< pixel components are independent of alpha |
| 42 | kLastEnum_SkAlphaType = kUnpremul_SkAlphaType, //!< last valid value |
| 43 | }; |
| 44 | |
| 45 | /** Returns true if SkAlphaType equals kOpaque_SkAlphaType. |
| 46 | |
| 47 | kOpaque_SkAlphaType is a hint that the SkColorType is opaque, or that all |
| 48 | alpha values are set to their 1.0 equivalent. If SkAlphaType is |
| 49 | kOpaque_SkAlphaType, and SkColorType is not opaque, then the result of |
| 50 | drawing any pixel with a alpha value less than 1.0 is undefined. |
| 51 | */ |
| 52 | static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) { |
| 53 | return kOpaque_SkAlphaType == at; |
| 54 | } |
| 55 | |
| 56 | /////////////////////////////////////////////////////////////////////////////// |
| 57 | |
| 58 | /** Temporary macro that allows us to add new color types without breaking Chrome compile. */ |
| 59 | #define SK_EXTENDED_COLOR_TYPES |
| 60 | |
| 61 | /** \enum SkImageInfo::SkColorType |
| 62 | Describes how pixel bits encode color. A pixel may be an alpha mask, a |
| 63 | grayscale, RGB, or ARGB. |
| 64 | |
| 65 | kN32_SkColorType selects the native 32-bit ARGB format. On little endian |
| 66 | processors, pixels containing 8-bit ARGB components pack into 32-bit |
| 67 | kBGRA_8888_SkColorType. On big endian processors, pixels pack into 32-bit |
| 68 | kRGBA_8888_SkColorType. |
| 69 | */ |
| 70 | enum SkColorType { |
| 71 | kUnknown_SkColorType, //!< uninitialized |
| 72 | kAlpha_8_SkColorType, //!< pixel with alpha in 8-bit byte |
| 73 | kRGB_565_SkColorType, //!< pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word |
| 74 | kARGB_4444_SkColorType, //!< pixel with 4 bits for alpha, red, green, blue; in 16-bit word |
| 75 | kRGBA_8888_SkColorType, //!< pixel with 8 bits for red, green, blue, alpha; in 32-bit word |
| 76 | kRGB_888x_SkColorType, //!< pixel with 8 bits each for red, green, blue; in 32-bit word |
| 77 | kBGRA_8888_SkColorType, //!< pixel with 8 bits for blue, green, red, alpha; in 32-bit word |
| 78 | kRGBA_1010102_SkColorType, //!< 10 bits for red, green, blue; 2 bits for alpha; in 32-bit word |
| 79 | kBGRA_1010102_SkColorType, //!< 10 bits for blue, green, red; 2 bits for alpha; in 32-bit word |
| 80 | kRGB_101010x_SkColorType, //!< pixel with 10 bits each for red, green, blue; in 32-bit word |
| 81 | kBGR_101010x_SkColorType, //!< pixel with 10 bits each for blue, green, red; in 32-bit word |
| 82 | kGray_8_SkColorType, //!< pixel with grayscale level in 8-bit byte |
| 83 | kRGBA_F16Norm_SkColorType, //!< pixel with half floats in [0,1] for red, green, blue, alpha; in 64-bit word |
| 84 | kRGBA_F16_SkColorType, //!< pixel with half floats for red, green, blue, alpha; in 64-bit word |
| 85 | kRGBA_F32_SkColorType, //!< pixel using C float for red, green, blue, alpha; in 128-bit word |
| 86 | |
| 87 | // The following 6 colortypes are just for reading from - not for rendering to |
| 88 | kR8G8_unorm_SkColorType, //<! pixel with a uint8_t for red and green |
| 89 | |
| 90 | kA16_float_SkColorType, //<! pixel with a half float for alpha |
| 91 | kR16G16_float_SkColorType, //<! pixel with a half float for red and green |
| 92 | |
| 93 | kA16_unorm_SkColorType, //<! pixel with a little endian uint16_t for alpha |
| 94 | kR16G16_unorm_SkColorType, //<! pixel with a little endian uint16_t for red and green |
| 95 | kR16G16B16A16_unorm_SkColorType,//<! pixel with a little endian uint16_t for red, green, blue, and alpha |
| 96 | |
| 97 | kLastEnum_SkColorType = kR16G16B16A16_unorm_SkColorType, //!< last valid value |
| 98 | |
| 99 | #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A) |
| 100 | kN32_SkColorType = kBGRA_8888_SkColorType,//!< native ARGB 32-bit encoding |
| 101 | |
| 102 | #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A) |
| 103 | kN32_SkColorType = kRGBA_8888_SkColorType,//!< native ARGB 32-bit encoding |
| 104 | |
| 105 | #else |
| 106 | #error "SK_*32_SHIFT values must correspond to BGRA or RGBA byte order" |
| 107 | #endif |
| 108 | }; |
| 109 | |
| 110 | /** Returns the number of bytes required to store a pixel, including unused padding. |
| 111 | Returns zero if ct is kUnknown_SkColorType or invalid. |
| 112 | |
| 113 | @return bytes per pixel |
| 114 | */ |
| 115 | SK_API int SkColorTypeBytesPerPixel(SkColorType ct); |
| 116 | |
| 117 | /** Returns true if SkColorType always decodes alpha to 1.0, making the pixel |
| 118 | fully opaque. If true, SkColorType does not reserve bits to encode alpha. |
| 119 | |
| 120 | @return true if alpha is always set to 1.0 |
| 121 | */ |
| 122 | SK_API bool SkColorTypeIsAlwaysOpaque(SkColorType ct); |
| 123 | |
| 124 | /** Returns true if canonical can be set to a valid SkAlphaType for colorType. If |
| 125 | there is more than one valid canonical SkAlphaType, set to alphaType, if valid. |
| 126 | If true is returned and canonical is not nullptr, store valid SkAlphaType. |
| 127 | |
| 128 | Returns false only if alphaType is kUnknown_SkAlphaType, color type is not |
| 129 | kUnknown_SkColorType, and SkColorType is not always opaque. If false is returned, |
| 130 | canonical is ignored. |
| 131 | |
| 132 | @param canonical storage for SkAlphaType |
| 133 | @return true if valid SkAlphaType can be associated with colorType |
| 134 | */ |
| 135 | SK_API bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType, |
| 136 | SkAlphaType* canonical = nullptr); |
| 137 | |
| 138 | /** \enum SkImageInfo::SkYUVColorSpace |
| 139 | Describes color range of YUV pixels. The color mapping from YUV to RGB varies |
| 140 | depending on the source. YUV pixels may be generated by JPEG images, standard |
| 141 | video streams, or high definition video streams. Each has its own mapping from |
| 142 | YUV and RGB. |
| 143 | |
| 144 | JPEG YUV values encode the full range of 0 to 255 for all three components. |
| 145 | Video YUV values range from 16 to 235 for all three components. Details of |
| 146 | encoding and conversion to RGB are described in YCbCr color space. |
| 147 | |
| 148 | The identity colorspace exists to provide a utility mapping from Y to R, U to G and V to B. |
| 149 | It can be used to visualize the YUV planes or to explicitly post process the YUV channels. |
| 150 | */ |
| 151 | enum SkYUVColorSpace { |
| 152 | kJPEG_SkYUVColorSpace, //!< describes full range |
| 153 | kRec601_SkYUVColorSpace, //!< describes SDTV range |
| 154 | kRec709_SkYUVColorSpace, //!< describes HDTV range |
| 155 | kBT2020_SkYUVColorSpace, //!< describes UHDTV range, non-constant-luminance |
| 156 | kIdentity_SkYUVColorSpace, //!< maps Y->R, U->G, V->B |
| 157 | |
| 158 | kLastEnum_SkYUVColorSpace = kIdentity_SkYUVColorSpace, //!< last valid value |
| 159 | }; |
| 160 | |
| 161 | /** \struct SkColorInfo |
| 162 | Describes pixel and encoding. SkImageInfo can be created from SkColorInfo by |
| 163 | providing dimensions. |
| 164 | |
| 165 | It encodes how pixel bits describe alpha, transparency; color components red, blue, |
| 166 | and green; and SkColorSpace, the range and linearity of colors. |
| 167 | */ |
| 168 | class SK_API SkColorInfo { |
| 169 | public: |
| 170 | /** Creates an SkColorInfo with kUnknown_SkColorType, kUnknown_SkAlphaType, |
| 171 | and no SkColorSpace. |
| 172 | |
| 173 | @return empty SkImageInfo |
| 174 | */ |
| 175 | SkColorInfo() = default; |
| 176 | |
| 177 | /** Creates SkColorInfo from SkColorType ct, SkAlphaType at, and optionally SkColorSpace cs. |
| 178 | |
| 179 | If SkColorSpace cs is nullptr and SkColorInfo is part of drawing source: SkColorSpace |
| 180 | defaults to sRGB, mapping into SkSurface SkColorSpace. |
| 181 | |
| 182 | Parameters are not validated to see if their values are legal, or that the |
| 183 | combination is supported. |
| 184 | @return created SkColorInfo |
| 185 | */ |
| 186 | SkColorInfo(SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs) |
| 187 | : fColorSpace(std::move(cs)), fColorType(ct), fAlphaType(at) {} |
| 188 | |
| 189 | SkColorInfo(const SkColorInfo&) = default; |
| 190 | SkColorInfo(SkColorInfo&&) = default; |
| 191 | |
| 192 | SkColorInfo& operator=(const SkColorInfo&) = default; |
| 193 | SkColorInfo& operator=(SkColorInfo&&) = default; |
| 194 | |
| 195 | SkColorSpace* colorSpace() const { return fColorSpace.get(); } |
| 196 | sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; } |
| 197 | SkColorType colorType() const { return fColorType; } |
| 198 | SkAlphaType alphaType() const { return fAlphaType; } |
| 199 | |
| 200 | bool isOpaque() const { |
| 201 | return SkAlphaTypeIsOpaque(fAlphaType) |
| 202 | || SkColorTypeIsAlwaysOpaque(fColorType); |
| 203 | } |
| 204 | |
| 205 | bool gammaCloseToSRGB() const { return fColorSpace && fColorSpace->gammaCloseToSRGB(); } |
| 206 | |
| 207 | /** Does other represent the same color type, alpha type, and color space? */ |
| 208 | bool operator==(const SkColorInfo& other) const { |
| 209 | return fColorType == other.fColorType && fAlphaType == other.fAlphaType && |
| 210 | SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get()); |
| 211 | } |
| 212 | |
| 213 | /** Does other represent a different color type, alpha type, or color space? */ |
| 214 | bool operator!=(const SkColorInfo& other) const { return !(*this == other); } |
| 215 | |
| 216 | /** Creates SkColorInfo with same SkColorType, SkColorSpace, with SkAlphaType set |
| 217 | to newAlphaType. |
| 218 | |
| 219 | Created SkColorInfo contains newAlphaType even if it is incompatible with |
| 220 | SkColorType, in which case SkAlphaType in SkColorInfo is ignored. |
| 221 | */ |
| 222 | SkColorInfo makeAlphaType(SkAlphaType newAlphaType) const { |
| 223 | return SkColorInfo(this->colorType(), newAlphaType, this->refColorSpace()); |
| 224 | } |
| 225 | |
| 226 | /** Creates new SkColorInfo with same SkAlphaType, SkColorSpace, with SkColorType |
| 227 | set to newColorType. |
| 228 | */ |
| 229 | SkColorInfo makeColorType(SkColorType newColorType) const { |
| 230 | return SkColorInfo(newColorType, this->alphaType(), this->refColorSpace()); |
| 231 | } |
| 232 | |
| 233 | /** Creates SkColorInfo with same SkAlphaType, SkColorType, with SkColorSpace |
| 234 | set to cs. cs may be nullptr. |
| 235 | */ |
| 236 | SkColorInfo makeColorSpace(sk_sp<SkColorSpace> cs) const { |
| 237 | return SkColorInfo(this->colorType(), this->alphaType(), std::move(cs)); |
| 238 | } |
| 239 | |
| 240 | /** Returns number of bytes per pixel required by SkColorType. |
| 241 | Returns zero if colorType() is kUnknown_SkColorType. |
| 242 | |
| 243 | @return bytes in pixel |
| 244 | |
| 245 | example: https://fiddle.skia.org/c/@ImageInfo_bytesPerPixel |
| 246 | */ |
| 247 | int bytesPerPixel() const; |
| 248 | |
| 249 | /** Returns bit shift converting row bytes to row pixels. |
| 250 | Returns zero for kUnknown_SkColorType. |
| 251 | |
| 252 | @return one of: 0, 1, 2, 3, 4; left shift to convert pixels to bytes |
| 253 | |
| 254 | example: https://fiddle.skia.org/c/@ImageInfo_shiftPerPixel |
| 255 | */ |
| 256 | int shiftPerPixel() const; |
| 257 | |
| 258 | private: |
| 259 | sk_sp<SkColorSpace> fColorSpace; |
| 260 | SkColorType fColorType = kUnknown_SkColorType; |
| 261 | SkAlphaType fAlphaType = kUnknown_SkAlphaType; |
| 262 | }; |
| 263 | |
| 264 | /** \struct SkImageInfo |
| 265 | Describes pixel dimensions and encoding. SkBitmap, SkImage, PixMap, and SkSurface |
| 266 | can be created from SkImageInfo. SkImageInfo can be retrieved from SkBitmap and |
| 267 | SkPixmap, but not from SkImage and SkSurface. For example, SkImage and SkSurface |
| 268 | implementations may defer pixel depth, so may not completely specify SkImageInfo. |
| 269 | |
| 270 | SkImageInfo contains dimensions, the pixel integral width and height. It encodes |
| 271 | how pixel bits describe alpha, transparency; color components red, blue, |
| 272 | and green; and SkColorSpace, the range and linearity of colors. |
| 273 | */ |
| 274 | struct SK_API SkImageInfo { |
| 275 | public: |
| 276 | |
| 277 | /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType, |
| 278 | a width and height of zero, and no SkColorSpace. |
| 279 | |
| 280 | @return empty SkImageInfo |
| 281 | */ |
| 282 | SkImageInfo() = default; |
| 283 | |
| 284 | /** Creates SkImageInfo from integral dimensions width and height, SkColorType ct, |
| 285 | SkAlphaType at, and optionally SkColorSpace cs. |
| 286 | |
| 287 | If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace |
| 288 | defaults to sRGB, mapping into SkSurface SkColorSpace. |
| 289 | |
| 290 | Parameters are not validated to see if their values are legal, or that the |
| 291 | combination is supported. |
| 292 | |
| 293 | @param width pixel column count; must be zero or greater |
| 294 | @param height pixel row count; must be zero or greater |
| 295 | @param cs range of colors; may be nullptr |
| 296 | @return created SkImageInfo |
| 297 | */ |
| 298 | static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at, |
| 299 | sk_sp<SkColorSpace> cs = nullptr) { |
| 300 | return SkImageInfo({width, height}, {ct, at, std::move(cs)}); |
| 301 | } |
| 302 | static SkImageInfo Make(SkISize dimensions, SkColorType ct, SkAlphaType at, |
| 303 | sk_sp<SkColorSpace> cs = nullptr) { |
| 304 | return SkImageInfo(dimensions, {ct, at, std::move(cs)}); |
| 305 | } |
| 306 | |
| 307 | /** Creates SkImageInfo from integral dimensions and SkColorInfo colorInfo, |
| 308 | |
| 309 | Parameters are not validated to see if their values are legal, or that the |
| 310 | combination is supported. |
| 311 | |
| 312 | @param dimensions pixel column and row count; must be zeros or greater |
| 313 | @param SkColorInfo the pixel encoding consisting of SkColorType, SkAlphaType, and |
| 314 | SkColorSpace (which may be nullptr) |
| 315 | @return created SkImageInfo |
| 316 | */ |
| 317 | static SkImageInfo Make(SkISize dimensions, const SkColorInfo& colorInfo) { |
| 318 | return SkImageInfo(dimensions, colorInfo); |
| 319 | } |
| 320 | static SkImageInfo Make(SkISize dimensions, SkColorInfo&& colorInfo) { |
| 321 | return SkImageInfo(dimensions, std::move(colorInfo)); |
| 322 | } |
| 323 | |
| 324 | /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType, |
| 325 | SkAlphaType at, and optionally SkColorSpace cs. kN32_SkColorType will equal either |
| 326 | kBGRA_8888_SkColorType or kRGBA_8888_SkColorType, whichever is optimal. |
| 327 | |
| 328 | If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace |
| 329 | defaults to sRGB, mapping into SkSurface SkColorSpace. |
| 330 | |
| 331 | Parameters are not validated to see if their values are legal, or that the |
| 332 | combination is supported. |
| 333 | |
| 334 | @param width pixel column count; must be zero or greater |
| 335 | @param height pixel row count; must be zero or greater |
| 336 | @param cs range of colors; may be nullptr |
| 337 | @return created SkImageInfo |
| 338 | */ |
| 339 | static SkImageInfo MakeN32(int width, int height, SkAlphaType at, |
| 340 | sk_sp<SkColorSpace> cs = nullptr) { |
| 341 | return Make({width, height}, kN32_SkColorType, at, std::move(cs)); |
| 342 | } |
| 343 | |
| 344 | /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType, |
| 345 | SkAlphaType at, with sRGB SkColorSpace. |
| 346 | |
| 347 | Parameters are not validated to see if their values are legal, or that the |
| 348 | combination is supported. |
| 349 | |
| 350 | @param width pixel column count; must be zero or greater |
| 351 | @param height pixel row count; must be zero or greater |
| 352 | @return created SkImageInfo |
| 353 | |
| 354 | example: https://fiddle.skia.org/c/@ImageInfo_MakeS32 |
| 355 | */ |
| 356 | static SkImageInfo MakeS32(int width, int height, SkAlphaType at); |
| 357 | |
| 358 | /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType, |
| 359 | kPremul_SkAlphaType, with optional SkColorSpace. |
| 360 | |
| 361 | If SkColorSpace cs is nullptr and SkImageInfo is part of drawing source: SkColorSpace |
| 362 | defaults to sRGB, mapping into SkSurface SkColorSpace. |
| 363 | |
| 364 | Parameters are not validated to see if their values are legal, or that the |
| 365 | combination is supported. |
| 366 | |
| 367 | @param width pixel column count; must be zero or greater |
| 368 | @param height pixel row count; must be zero or greater |
| 369 | @param cs range of colors; may be nullptr |
| 370 | @return created SkImageInfo |
| 371 | */ |
| 372 | static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) { |
| 373 | return Make({width, height}, kN32_SkColorType, kPremul_SkAlphaType, std::move(cs)); |
| 374 | } |
| 375 | |
| 376 | /** Creates SkImageInfo from integral dimensions width and height, kN32_SkColorType, |
| 377 | kPremul_SkAlphaType, with SkColorSpace set to nullptr. |
| 378 | |
| 379 | If SkImageInfo is part of drawing source: SkColorSpace defaults to sRGB, mapping |
| 380 | into SkSurface SkColorSpace. |
| 381 | |
| 382 | Parameters are not validated to see if their values are legal, or that the |
| 383 | combination is supported. |
| 384 | |
| 385 | @param dimensions width and height, each must be zero or greater |
| 386 | @param cs range of colors; may be nullptr |
| 387 | @return created SkImageInfo |
| 388 | */ |
| 389 | static SkImageInfo MakeN32Premul(SkISize dimensions, sk_sp<SkColorSpace> cs = nullptr) { |
| 390 | return Make(dimensions, kN32_SkColorType, kPremul_SkAlphaType, std::move(cs)); |
| 391 | } |
| 392 | |
| 393 | /** Creates SkImageInfo from integral dimensions width and height, kAlpha_8_SkColorType, |
| 394 | kPremul_SkAlphaType, with SkColorSpace set to nullptr. |
| 395 | |
| 396 | @param width pixel column count; must be zero or greater |
| 397 | @param height pixel row count; must be zero or greater |
| 398 | @return created SkImageInfo |
| 399 | */ |
| 400 | static SkImageInfo MakeA8(int width, int height) { |
| 401 | return Make({width, height}, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr); |
| 402 | } |
| 403 | /** Creates SkImageInfo from integral dimensions, kAlpha_8_SkColorType, |
| 404 | kPremul_SkAlphaType, with SkColorSpace set to nullptr. |
| 405 | |
| 406 | @param dimensions pixel row and column count; must be zero or greater |
| 407 | @return created SkImageInfo |
| 408 | */ |
| 409 | static SkImageInfo MakeA8(SkISize dimensions) { |
| 410 | return Make(dimensions, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr); |
| 411 | } |
| 412 | |
| 413 | /** Creates SkImageInfo from integral dimensions width and height, kUnknown_SkColorType, |
| 414 | kUnknown_SkAlphaType, with SkColorSpace set to nullptr. |
| 415 | |
| 416 | Returned SkImageInfo as part of source does not draw, and as part of destination |
| 417 | can not be drawn to. |
| 418 | |
| 419 | @param width pixel column count; must be zero or greater |
| 420 | @param height pixel row count; must be zero or greater |
| 421 | @return created SkImageInfo |
| 422 | */ |
| 423 | static SkImageInfo MakeUnknown(int width, int height) { |
| 424 | return Make({width, height}, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr); |
| 425 | } |
| 426 | |
| 427 | /** Creates SkImageInfo from integral dimensions width and height set to zero, |
| 428 | kUnknown_SkColorType, kUnknown_SkAlphaType, with SkColorSpace set to nullptr. |
| 429 | |
| 430 | Returned SkImageInfo as part of source does not draw, and as part of destination |
| 431 | can not be drawn to. |
| 432 | |
| 433 | @return created SkImageInfo |
| 434 | */ |
| 435 | static SkImageInfo MakeUnknown() { |
| 436 | return MakeUnknown(0, 0); |
| 437 | } |
| 438 | |
| 439 | /** Returns pixel count in each row. |
| 440 | |
| 441 | @return pixel width |
| 442 | */ |
| 443 | int width() const { return fDimensions.width(); } |
| 444 | |
| 445 | /** Returns pixel row count. |
| 446 | |
| 447 | @return pixel height |
| 448 | */ |
| 449 | int height() const { return fDimensions.height(); } |
| 450 | |
| 451 | SkColorType colorType() const { return fColorInfo.colorType(); } |
| 452 | |
| 453 | SkAlphaType alphaType() const { return fColorInfo.alphaType(); } |
| 454 | |
| 455 | /** Returns SkColorSpace, the range of colors. The reference count of |
| 456 | SkColorSpace is unchanged. The returned SkColorSpace is immutable. |
| 457 | |
| 458 | @return SkColorSpace, or nullptr |
| 459 | */ |
| 460 | SkColorSpace* colorSpace() const { return fColorInfo.colorSpace(); } |
| 461 | |
| 462 | /** Returns smart pointer to SkColorSpace, the range of colors. The smart pointer |
| 463 | tracks the number of objects sharing this SkColorSpace reference so the memory |
| 464 | is released when the owners destruct. |
| 465 | |
| 466 | The returned SkColorSpace is immutable. |
| 467 | |
| 468 | @return SkColorSpace wrapped in a smart pointer |
| 469 | */ |
| 470 | sk_sp<SkColorSpace> refColorSpace() const { return fColorInfo.refColorSpace(); } |
| 471 | |
| 472 | /** Returns if SkImageInfo describes an empty area of pixels by checking if either |
| 473 | width or height is zero or smaller. |
| 474 | |
| 475 | @return true if either dimension is zero or smaller |
| 476 | */ |
| 477 | bool isEmpty() const { return fDimensions.isEmpty(); } |
| 478 | |
| 479 | /** Returns the dimensionless SkColorInfo that represents the same color type, |
| 480 | alpha type, and color space as this SkImageInfo. |
| 481 | */ |
| 482 | const SkColorInfo& colorInfo() const { return fColorInfo; } |
| 483 | |
| 484 | /** Returns true if SkAlphaType is set to hint that all pixels are opaque; their |
| 485 | alpha value is implicitly or explicitly 1.0. If true, and all pixels are |
| 486 | not opaque, Skia may draw incorrectly. |
| 487 | |
| 488 | Does not check if SkColorType allows alpha, or if any pixel value has |
| 489 | transparency. |
| 490 | |
| 491 | @return true if SkAlphaType is kOpaque_SkAlphaType |
| 492 | */ |
| 493 | bool isOpaque() const { return fColorInfo.isOpaque(); } |
| 494 | |
| 495 | /** Returns SkISize { width(), height() }. |
| 496 | |
| 497 | @return integral size of width() and height() |
| 498 | */ |
| 499 | SkISize dimensions() const { return fDimensions; } |
| 500 | |
| 501 | /** Returns SkIRect { 0, 0, width(), height() }. |
| 502 | |
| 503 | @return integral rectangle from origin to width() and height() |
| 504 | */ |
| 505 | SkIRect bounds() const { return SkIRect::MakeSize(fDimensions); } |
| 506 | |
| 507 | /** Returns true if associated SkColorSpace is not nullptr, and SkColorSpace gamma |
| 508 | is approximately the same as sRGB. |
| 509 | This includes the |
| 510 | |
| 511 | @return true if SkColorSpace gamma is approximately the same as sRGB |
| 512 | */ |
| 513 | bool gammaCloseToSRGB() const { return fColorInfo.gammaCloseToSRGB(); } |
| 514 | |
| 515 | /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType, |
| 516 | with dimensions set to width and height. |
| 517 | |
| 518 | @param newWidth pixel column count; must be zero or greater |
| 519 | @param newHeight pixel row count; must be zero or greater |
| 520 | @return created SkImageInfo |
| 521 | */ |
| 522 | SkImageInfo makeWH(int newWidth, int newHeight) const { |
| 523 | return Make({newWidth, newHeight}, fColorInfo); |
| 524 | } |
| 525 | |
| 526 | /** Creates SkImageInfo with the same SkColorType, SkColorSpace, and SkAlphaType, |
| 527 | with dimensions set to newDimensions. |
| 528 | |
| 529 | @param newSize pixel column and row count; must be zero or greater |
| 530 | @return created SkImageInfo |
| 531 | */ |
| 532 | SkImageInfo makeDimensions(SkISize newSize) const { |
| 533 | return Make(newSize, fColorInfo); |
| 534 | } |
| 535 | |
| 536 | /** Creates SkImageInfo with same SkColorType, SkColorSpace, width, and height, |
| 537 | with SkAlphaType set to newAlphaType. |
| 538 | |
| 539 | Created SkImageInfo contains newAlphaType even if it is incompatible with |
| 540 | SkColorType, in which case SkAlphaType in SkImageInfo is ignored. |
| 541 | |
| 542 | @return created SkImageInfo |
| 543 | */ |
| 544 | SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const { |
| 545 | return Make(fDimensions, fColorInfo.makeAlphaType(newAlphaType)); |
| 546 | } |
| 547 | |
| 548 | /** Creates SkImageInfo with same SkAlphaType, SkColorSpace, width, and height, |
| 549 | with SkColorType set to newColorType. |
| 550 | |
| 551 | @return created SkImageInfo |
| 552 | */ |
| 553 | SkImageInfo makeColorType(SkColorType newColorType) const { |
| 554 | return Make(fDimensions, fColorInfo.makeColorType(newColorType)); |
| 555 | } |
| 556 | |
| 557 | /** Creates SkImageInfo with same SkAlphaType, SkColorType, width, and height, |
| 558 | with SkColorSpace set to cs. |
| 559 | |
| 560 | @param cs range of colors; may be nullptr |
| 561 | @return created SkImageInfo |
| 562 | */ |
| 563 | SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const { |
| 564 | return Make(fDimensions, fColorInfo.makeColorSpace(std::move(cs))); |
| 565 | } |
| 566 | |
| 567 | /** Returns number of bytes per pixel required by SkColorType. |
| 568 | Returns zero if colorType( is kUnknown_SkColorType. |
| 569 | |
| 570 | @return bytes in pixel |
| 571 | */ |
| 572 | int bytesPerPixel() const { return fColorInfo.bytesPerPixel(); } |
| 573 | |
| 574 | /** Returns bit shift converting row bytes to row pixels. |
| 575 | Returns zero for kUnknown_SkColorType. |
| 576 | |
| 577 | @return one of: 0, 1, 2, 3; left shift to convert pixels to bytes |
| 578 | */ |
| 579 | int shiftPerPixel() const { return fColorInfo.shiftPerPixel(); } |
| 580 | |
| 581 | /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which |
| 582 | specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit |
| 583 | in 31 bits. |
| 584 | |
| 585 | @return width() times bytesPerPixel() as unsigned 64-bit integer |
| 586 | */ |
| 587 | uint64_t minRowBytes64() const { return sk_64_mul(this->width(), this->bytesPerPixel()); } |
| 588 | |
| 589 | /** Returns minimum bytes per row, computed from pixel width() and SkColorType, which |
| 590 | specifies bytesPerPixel(). SkBitmap maximum value for row bytes must fit |
| 591 | in 31 bits. |
| 592 | |
| 593 | @return width() times bytesPerPixel() as signed 32-bit integer |
| 594 | */ |
| 595 | size_t minRowBytes() const { |
| 596 | uint64_t minRowBytes = this->minRowBytes64(); |
| 597 | if (!SkTFitsIn<int32_t>(minRowBytes)) { |
| 598 | return 0; |
| 599 | } |
| 600 | return SkTo<int32_t>(minRowBytes); |
| 601 | } |
| 602 | |
| 603 | /** Returns byte offset of pixel from pixel base address. |
| 604 | |
| 605 | Asserts in debug build if x or y is outside of bounds. Does not assert if |
| 606 | rowBytes is smaller than minRowBytes(), even though result may be incorrect. |
| 607 | |
| 608 | @param x column index, zero or greater, and less than width() |
| 609 | @param y row index, zero or greater, and less than height() |
| 610 | @param rowBytes size of pixel row or larger |
| 611 | @return offset within pixel array |
| 612 | |
| 613 | example: https://fiddle.skia.org/c/@ImageInfo_computeOffset |
| 614 | */ |
| 615 | size_t computeOffset(int x, int y, size_t rowBytes) const; |
| 616 | |
| 617 | /** Compares SkImageInfo with other, and returns true if width, height, SkColorType, |
| 618 | SkAlphaType, and SkColorSpace are equivalent. |
| 619 | |
| 620 | @param other SkImageInfo to compare |
| 621 | @return true if SkImageInfo equals other |
| 622 | */ |
| 623 | bool operator==(const SkImageInfo& other) const { |
| 624 | return fDimensions == other.fDimensions && fColorInfo == other.fColorInfo; |
| 625 | } |
| 626 | |
| 627 | /** Compares SkImageInfo with other, and returns true if width, height, SkColorType, |
| 628 | SkAlphaType, and SkColorSpace are not equivalent. |
| 629 | |
| 630 | @param other SkImageInfo to compare |
| 631 | @return true if SkImageInfo is not equal to other |
| 632 | */ |
| 633 | bool operator!=(const SkImageInfo& other) const { |
| 634 | return !(*this == other); |
| 635 | } |
| 636 | |
| 637 | /** Returns storage required by pixel array, given SkImageInfo dimensions, SkColorType, |
| 638 | and rowBytes. rowBytes is assumed to be at least as large as minRowBytes(). |
| 639 | |
| 640 | Returns zero if height is zero. |
| 641 | Returns SIZE_MAX if answer exceeds the range of size_t. |
| 642 | |
| 643 | @param rowBytes size of pixel row or larger |
| 644 | @return memory required by pixel buffer |
| 645 | |
| 646 | example: https://fiddle.skia.org/c/@ImageInfo_computeByteSize |
| 647 | */ |
| 648 | size_t computeByteSize(size_t rowBytes) const; |
| 649 | |
| 650 | /** Returns storage required by pixel array, given SkImageInfo dimensions, and |
| 651 | SkColorType. Uses minRowBytes() to compute bytes for pixel row. |
| 652 | |
| 653 | Returns zero if height is zero. |
| 654 | Returns SIZE_MAX if answer exceeds the range of size_t. |
| 655 | |
| 656 | @return least memory required by pixel buffer |
| 657 | */ |
| 658 | size_t computeMinByteSize() const { |
| 659 | return this->computeByteSize(this->minRowBytes()); |
| 660 | } |
| 661 | |
| 662 | /** Returns true if byteSize equals SIZE_MAX. computeByteSize() and |
| 663 | computeMinByteSize() return SIZE_MAX if size_t can not hold buffer size. |
| 664 | |
| 665 | @param byteSize result of computeByteSize() or computeMinByteSize() |
| 666 | @return true if computeByteSize() or computeMinByteSize() result exceeds size_t |
| 667 | */ |
| 668 | static bool ByteSizeOverflowed(size_t byteSize) { |
| 669 | return SIZE_MAX == byteSize; |
| 670 | } |
| 671 | |
| 672 | /** Returns true if rowBytes is valid for this SkImageInfo. |
| 673 | |
| 674 | @param rowBytes size of pixel row including padding |
| 675 | @return true if rowBytes is large enough to contain pixel row and is properly |
| 676 | aligned |
| 677 | */ |
| 678 | bool validRowBytes(size_t rowBytes) const { |
| 679 | if (rowBytes < this->minRowBytes64()) { |
| 680 | return false; |
| 681 | } |
| 682 | int shift = this->shiftPerPixel(); |
| 683 | size_t alignedRowBytes = rowBytes >> shift << shift; |
| 684 | return alignedRowBytes == rowBytes; |
| 685 | } |
| 686 | |
| 687 | /** Creates an empty SkImageInfo with kUnknown_SkColorType, kUnknown_SkAlphaType, |
| 688 | a width and height of zero, and no SkColorSpace. |
| 689 | */ |
| 690 | void reset() { *this = {}; } |
| 691 | |
| 692 | /** Asserts if internal values are illegal or inconsistent. Only available if |
| 693 | SK_DEBUG is defined at compile time. |
| 694 | */ |
| 695 | SkDEBUGCODE(void validate() const;) |
| 696 | |
| 697 | private: |
| 698 | SkColorInfo fColorInfo; |
| 699 | SkISize fDimensions = {0, 0}; |
| 700 | |
| 701 | SkImageInfo(SkISize dimensions, const SkColorInfo& colorInfo) |
| 702 | : fColorInfo(colorInfo), fDimensions(dimensions) {} |
| 703 | |
| 704 | SkImageInfo(SkISize dimensions, SkColorInfo&& colorInfo) |
| 705 | : fColorInfo(std::move(colorInfo)), fDimensions(dimensions) {} |
| 706 | }; |
| 707 | |
| 708 | #endif |
| 709 | |