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