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
16 class SkReadBuffer;
17 class SkWriteBuffer;
18
19 /**
20 * Describes how to interpret the alpha component of a pixel.
21 */
22 enum 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
SkAlphaTypeIsOpaque(SkAlphaType at)51 static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
52 return kOpaque_SkAlphaType == at;
53 }
54
SkAlphaTypeIsValid(unsigned value)55 static inline bool SkAlphaTypeIsValid(unsigned value) {
56 return value <= kLastEnum_SkAlphaType;
57 }
58
59 ///////////////////////////////////////////////////////////////////////////////
60
61 /**
62 * Describes how to interpret the components of a pixel.
63 *
64 * kN32_SkColorType is an alias for whichever 32bit ARGB format is the "native"
65 * form for skia's blitters. Use this if you don't have a swizzle preference
66 * for 32bit pixels.
67 */
68 enum SkColorType {
69 kUnknown_SkColorType,
70 kAlpha_8_SkColorType,
71 kRGB_565_SkColorType,
72 kARGB_4444_SkColorType,
73 kRGBA_8888_SkColorType,
74 kBGRA_8888_SkColorType,
75 kGray_8_SkColorType,
76 kRGBA_F16_SkColorType,
77
78 kLastEnum_SkColorType = kRGBA_F16_SkColorType,
79
80 #if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
81 kN32_SkColorType = kBGRA_8888_SkColorType,
82 #elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
83 kN32_SkColorType = kRGBA_8888_SkColorType,
84 #else
85 #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order"
86 #endif
87 };
88
SkColorTypeBytesPerPixel(SkColorType ct)89 static int SkColorTypeBytesPerPixel(SkColorType ct) {
90 static const uint8_t gSize[] = {
91 0, // Unknown
92 1, // Alpha_8
93 2, // RGB_565
94 2, // ARGB_4444
95 4, // RGBA_8888
96 4, // BGRA_8888
97 1, // kGray_8
98 8, // kRGBA_F16
99 };
100 static_assert(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1),
101 "size_mismatch_with_SkColorType_enum");
102
103 SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize));
104 return gSize[ct];
105 }
106
SkColorTypeShiftPerPixel(SkColorType ct)107 static int SkColorTypeShiftPerPixel(SkColorType ct) {
108 static const uint8_t gShift[] = {
109 0, // Unknown
110 0, // Alpha_8
111 1, // RGB_565
112 1, // ARGB_4444
113 2, // RGBA_8888
114 2, // BGRA_8888
115 0, // kGray_8
116 3, // kRGBA_F16
117 };
118 static_assert(SK_ARRAY_COUNT(gShift) == (size_t)(kLastEnum_SkColorType + 1),
119 "size_mismatch_with_SkColorType_enum");
120
121 SkASSERT((size_t)ct < SK_ARRAY_COUNT(gShift));
122 return gShift[ct];
123 }
124
SkColorTypeMinRowBytes(SkColorType ct,int width)125 static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
126 return width * SkColorTypeBytesPerPixel(ct);
127 }
128
SkColorTypeIsValid(unsigned value)129 static inline bool SkColorTypeIsValid(unsigned value) {
130 return value <= kLastEnum_SkColorType;
131 }
132
SkColorTypeComputeOffset(SkColorType ct,int x,int y,size_t rowBytes)133 static inline size_t SkColorTypeComputeOffset(SkColorType ct, int x, int y, size_t rowBytes) {
134 if (kUnknown_SkColorType == ct) {
135 return 0;
136 }
137 return y * rowBytes + (x << SkColorTypeShiftPerPixel(ct));
138 }
139
140 ///////////////////////////////////////////////////////////////////////////////
141
142 /**
143 * Return true if alphaType is supported by colorType. If there is a canonical
144 * alphaType for this colorType, return it in canonical.
145 */
146 bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
147 SkAlphaType* canonical = NULL);
148
149 ///////////////////////////////////////////////////////////////////////////////
150
151 /**
152 * Describes the color space a YUV pixel.
153 */
154 enum SkYUVColorSpace {
155 /** Standard JPEG color space. */
156 kJPEG_SkYUVColorSpace,
157 /** SDTV standard Rec. 601 color space. Uses "studio swing" [16, 235] color
158 range. See http://en.wikipedia.org/wiki/Rec._601 for details. */
159 kRec601_SkYUVColorSpace,
160 /** HDTV standard Rec. 709 color space. Uses "studio swing" [16, 235] color
161 range. See http://en.wikipedia.org/wiki/Rec._709 for details. */
162 kRec709_SkYUVColorSpace,
163
164 kLastEnum_SkYUVColorSpace = kRec709_SkYUVColorSpace
165 };
166
167 ///////////////////////////////////////////////////////////////////////////////
168
169 enum class SkDestinationSurfaceColorMode {
170 kLegacy,
171 kGammaAndColorSpaceAware,
172 };
173
174 /**
175 * Describe an image's dimensions and pixel type.
176 * Used for both src images and render-targets (surfaces).
177 */
178 struct SK_API SkImageInfo {
179 public:
SkImageInfoSkImageInfo180 SkImageInfo()
181 : fColorSpace(nullptr)
182 , fWidth(0)
183 , fHeight(0)
184 , fColorType(kUnknown_SkColorType)
185 , fAlphaType(kUnknown_SkAlphaType)
186 {}
187
188 static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,
189 sk_sp<SkColorSpace> cs = nullptr) {
190 return SkImageInfo(width, height, ct, at, std::move(cs));
191 }
192
193 /**
194 * Sets colortype to the native ARGB32 type.
195 */
196 static SkImageInfo MakeN32(int width, int height, SkAlphaType at,
197 sk_sp<SkColorSpace> cs = nullptr) {
198 return Make(width, height, kN32_SkColorType, at, cs);
199 }
200
201 /**
202 * Create an ImageInfo marked as SRGB with N32 swizzle.
203 */
204 static SkImageInfo MakeS32(int width, int height, SkAlphaType at);
205
206 /**
207 * Sets colortype to the native ARGB32 type, and the alphatype to premul.
208 */
209 static SkImageInfo MakeN32Premul(int width, int height, sk_sp<SkColorSpace> cs = nullptr) {
210 return Make(width, height, kN32_SkColorType, kPremul_SkAlphaType, cs);
211 }
212
MakeN32PremulSkImageInfo213 static SkImageInfo MakeN32Premul(const SkISize& size) {
214 return MakeN32Premul(size.width(), size.height());
215 }
216
MakeA8SkImageInfo217 static SkImageInfo MakeA8(int width, int height) {
218 return Make(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr);
219 }
220
MakeUnknownSkImageInfo221 static SkImageInfo MakeUnknown(int width, int height) {
222 return Make(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType, nullptr);
223 }
224
MakeUnknownSkImageInfo225 static SkImageInfo MakeUnknown() {
226 return MakeUnknown(0, 0);
227 }
228
widthSkImageInfo229 int width() const { return fWidth; }
heightSkImageInfo230 int height() const { return fHeight; }
colorTypeSkImageInfo231 SkColorType colorType() const { return fColorType; }
alphaTypeSkImageInfo232 SkAlphaType alphaType() const { return fAlphaType; }
colorSpaceSkImageInfo233 SkColorSpace* colorSpace() const { return fColorSpace.get(); }
refColorSpaceSkImageInfo234 sk_sp<SkColorSpace> refColorSpace() const { return fColorSpace; }
235
isEmptySkImageInfo236 bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
237
isOpaqueSkImageInfo238 bool isOpaque() const {
239 return SkAlphaTypeIsOpaque(fAlphaType);
240 }
241
dimensionsSkImageInfo242 SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
boundsSkImageInfo243 SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }
244
gammaCloseToSRGBSkImageInfo245 bool gammaCloseToSRGB() const {
246 return fColorSpace && fColorSpace->gammaCloseToSRGB();
247 }
248
249 /**
250 * Return a new ImageInfo with the same colortype and alphatype as this info,
251 * but with the specified width and height.
252 */
makeWHSkImageInfo253 SkImageInfo makeWH(int newWidth, int newHeight) const {
254 return Make(newWidth, newHeight, fColorType, fAlphaType, fColorSpace);
255 }
256
makeAlphaTypeSkImageInfo257 SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {
258 return Make(fWidth, fHeight, fColorType, newAlphaType, fColorSpace);
259 }
260
makeColorTypeSkImageInfo261 SkImageInfo makeColorType(SkColorType newColorType) const {
262 return Make(fWidth, fHeight, newColorType, fAlphaType, fColorSpace);
263 }
264
makeColorSpaceSkImageInfo265 SkImageInfo makeColorSpace(sk_sp<SkColorSpace> cs) const {
266 return Make(fWidth, fHeight, fColorType, fAlphaType, std::move(cs));
267 }
268
bytesPerPixelSkImageInfo269 int bytesPerPixel() const { return SkColorTypeBytesPerPixel(fColorType); }
270
shiftPerPixelSkImageInfo271 int shiftPerPixel() const { return SkColorTypeShiftPerPixel(fColorType); }
272
minRowBytes64SkImageInfo273 uint64_t minRowBytes64() const {
274 return sk_64_mul(fWidth, this->bytesPerPixel());
275 }
276
minRowBytesSkImageInfo277 size_t minRowBytes() const {
278 uint64_t minRowBytes = this->minRowBytes64();
279 if (!sk_64_isS32(minRowBytes)) {
280 return 0;
281 }
282 return sk_64_asS32(minRowBytes);
283 }
284
computeOffsetSkImageInfo285 size_t computeOffset(int x, int y, size_t rowBytes) const {
286 SkASSERT((unsigned)x < (unsigned)fWidth);
287 SkASSERT((unsigned)y < (unsigned)fHeight);
288 return SkColorTypeComputeOffset(fColorType, x, y, rowBytes);
289 }
290
291 bool operator==(const SkImageInfo& other) const {
292 return fWidth == other.fWidth && fHeight == other.fHeight &&
293 fColorType == other.fColorType && fAlphaType == other.fAlphaType &&
294 SkColorSpace::Equals(fColorSpace.get(), other.fColorSpace.get());
295 }
296 bool operator!=(const SkImageInfo& other) const {
297 return !(*this == other);
298 }
299
300 void unflatten(SkReadBuffer&);
301 void flatten(SkWriteBuffer&) const;
302
getSafeSize64SkImageInfo303 int64_t getSafeSize64(size_t rowBytes) const {
304 if (0 == fHeight) {
305 return 0;
306 }
307 return sk_64_mul(fHeight - 1, rowBytes) + sk_64_mul(fWidth, this->bytesPerPixel());
308 }
309
getSafeSizeSkImageInfo310 size_t getSafeSize(size_t rowBytes) const {
311 int64_t size = this->getSafeSize64(rowBytes);
312 if (!sk_64_isS32(size)) {
313 return 0;
314 }
315 return sk_64_asS32(size);
316 }
317
validRowBytesSkImageInfo318 bool validRowBytes(size_t rowBytes) const {
319 uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel());
320 return rowBytes >= rb;
321 }
322
resetSkImageInfo323 void reset() {
324 fColorSpace = nullptr;
325 fWidth = 0;
326 fHeight = 0;
327 fColorType = kUnknown_SkColorType;
328 fAlphaType = kUnknown_SkAlphaType;
329 }
330
331 SkDEBUGCODE(void validate() const;)
332
333 private:
334 sk_sp<SkColorSpace> fColorSpace;
335 int fWidth;
336 int fHeight;
337 SkColorType fColorType;
338 SkAlphaType fAlphaType;
339
SkImageInfoSkImageInfo340 SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, sk_sp<SkColorSpace> cs)
341 : fColorSpace(std::move(cs))
342 , fWidth(width)
343 , fHeight(height)
344 , fColorType(ct)
345 , fAlphaType(at)
346 {}
347 };
348
349 #endif
350