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 "SkMath.h"
12#include "SkRect.h"
13#include "SkSize.h"
14
15class SkReadBuffer;
16class SkWriteBuffer;
17
18/**
19 *  Describes how to interpret the alpha compoent of a pixel.
20 */
21enum SkAlphaType {
22    kUnknown_SkAlphaType,
23
24    /**
25     *  All pixels are stored as opaque. This differs slightly from kIgnore in
26     *  that kOpaque has correct "opaque" values stored in the pixels, while
27     *  kIgnore may not, but in both cases the caller should treat the pixels
28     *  as opaque.
29     */
30    kOpaque_SkAlphaType,
31
32    /**
33     *  All pixels have their alpha premultiplied in their color components.
34     *  This is the natural format for the rendering target pixels.
35     */
36    kPremul_SkAlphaType,
37
38    /**
39     *  All pixels have their color components stored without any regard to the
40     *  alpha. e.g. this is the default configuration for PNG images.
41     *
42     *  This alpha-type is ONLY supported for input images. Rendering cannot
43     *  generate this on output.
44     */
45    kUnpremul_SkAlphaType,
46
47    kLastEnum_SkAlphaType = kUnpremul_SkAlphaType
48};
49
50static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
51    return kOpaque_SkAlphaType == at;
52}
53
54static inline bool SkAlphaTypeIsValid(unsigned value) {
55    return value <= kLastEnum_SkAlphaType;
56}
57
58///////////////////////////////////////////////////////////////////////////////
59
60/**
61 *  Describes how to interpret the components of a pixel.
62 *
63 *  kN32_SkColorType is an alias for whichever 32bit ARGB format is the "native"
64 *  form for skia's blitters. Use this if you don't have a swizzle preference
65 *  for 32bit pixels.
66 */
67enum SkColorType {
68    kUnknown_SkColorType,
69    kAlpha_8_SkColorType,
70    kRGB_565_SkColorType,
71    kARGB_4444_SkColorType,
72    kRGBA_8888_SkColorType,
73    kBGRA_8888_SkColorType,
74    kIndex_8_SkColorType,
75    kGray_8_SkColorType,
76
77    kLastEnum_SkColorType = kGray_8_SkColorType,
78
79#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
80    kN32_SkColorType = kBGRA_8888_SkColorType,
81#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
82    kN32_SkColorType = kRGBA_8888_SkColorType,
83#else
84    #error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order"
85#endif
86};
87
88static int SkColorTypeBytesPerPixel(SkColorType ct) {
89    static const uint8_t gSize[] = {
90        0,  // Unknown
91        1,  // Alpha_8
92        2,  // RGB_565
93        2,  // ARGB_4444
94        4,  // RGBA_8888
95        4,  // BGRA_8888
96        1,  // kIndex_8
97        1,  // kGray_8
98    };
99    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1),
100                      size_mismatch_with_SkColorType_enum);
101
102    SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize));
103    return gSize[ct];
104}
105
106static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
107    return width * SkColorTypeBytesPerPixel(ct);
108}
109
110static inline bool SkColorTypeIsValid(unsigned value) {
111    return value <= kLastEnum_SkColorType;
112}
113
114///////////////////////////////////////////////////////////////////////////////
115
116/**
117 *  Return true if alphaType is supported by colorType. If there is a canonical
118 *  alphaType for this colorType, return it in canonical.
119 */
120bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
121                                  SkAlphaType* canonical = NULL);
122
123///////////////////////////////////////////////////////////////////////////////
124
125/**
126 *  Describes the color space a YUV pixel.
127 */
128enum SkYUVColorSpace {
129    /** Standard JPEG color space. */
130    kJPEG_SkYUVColorSpace,
131    /** SDTV standard Rec. 601 color space. Uses "studio swing" [16, 235] color
132       range. See http://en.wikipedia.org/wiki/Rec._601 for details. */
133    kRec601_SkYUVColorSpace,
134
135    kLastEnum_SkYUVColorSpace = kRec601_SkYUVColorSpace
136};
137
138///////////////////////////////////////////////////////////////////////////////
139
140enum SkColorProfileType {
141    kLinear_SkColorProfileType,
142    kSRGB_SkColorProfileType,
143
144    kLastEnum_SkColorProfileType = kSRGB_SkColorProfileType
145};
146
147/**
148 *  Describe an image's dimensions and pixel type.
149 *  Used for both src images and render-targets (surfaces).
150 */
151struct SK_API SkImageInfo {
152public:
153    SkImageInfo()
154        : fWidth(0)
155        , fHeight(0)
156        , fColorType(kUnknown_SkColorType)
157        , fAlphaType(kUnknown_SkAlphaType)
158        , fProfileType(kLinear_SkColorProfileType)
159    {}
160
161    static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at,
162                            SkColorProfileType pt = kLinear_SkColorProfileType) {
163        return SkImageInfo(width, height, ct, at, pt);
164    }
165
166    /**
167     *  Sets colortype to the native ARGB32 type.
168     */
169    static SkImageInfo MakeN32(int width, int height, SkAlphaType at,
170                               SkColorProfileType pt = kLinear_SkColorProfileType) {
171        return SkImageInfo(width, height, kN32_SkColorType, at, pt);
172    }
173
174    /**
175     *  Sets colortype to the native ARGB32 type, and the alphatype to premul.
176     */
177    static SkImageInfo MakeN32Premul(int width, int height,
178                                     SkColorProfileType pt = kLinear_SkColorProfileType) {
179        return SkImageInfo(width, height, kN32_SkColorType, kPremul_SkAlphaType, pt);
180    }
181
182    /**
183     *  Sets colortype to the native ARGB32 type, and the alphatype to premul.
184     */
185    static SkImageInfo MakeN32Premul(const SkISize& size,
186                                     SkColorProfileType pt = kLinear_SkColorProfileType) {
187        return MakeN32Premul(size.width(), size.height(), pt);
188    }
189
190    static SkImageInfo MakeA8(int width, int height) {
191        return SkImageInfo(width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType,
192                           kLinear_SkColorProfileType);
193    }
194
195    static SkImageInfo MakeUnknown(int width, int height) {
196        return SkImageInfo(width, height, kUnknown_SkColorType, kUnknown_SkAlphaType,
197                           kLinear_SkColorProfileType);
198    }
199
200    static SkImageInfo MakeUnknown() {
201        return SkImageInfo();
202    }
203
204    int width() const { return fWidth; }
205    int height() const { return fHeight; }
206    SkColorType colorType() const { return fColorType; }
207    SkAlphaType alphaType() const { return fAlphaType; }
208    SkColorProfileType profileType() const { return fProfileType; }
209
210    bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
211
212    bool isOpaque() const {
213        return SkAlphaTypeIsOpaque(fAlphaType);
214    }
215
216    bool isLinear() const { return kLinear_SkColorProfileType == fProfileType; }
217    bool isSRGB() const { return kSRGB_SkColorProfileType == fProfileType; }
218
219    SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
220    SkIRect bounds() const { return SkIRect::MakeWH(fWidth, fHeight); }
221
222    /**
223     *  Return a new ImageInfo with the same colortype and alphatype as this info,
224     *  but with the specified width and height.
225     */
226    SkImageInfo makeWH(int newWidth, int newHeight) const {
227        return SkImageInfo::Make(newWidth, newHeight, fColorType, fAlphaType, fProfileType);
228    }
229
230    SkImageInfo makeAlphaType(SkAlphaType newAlphaType) const {
231        return SkImageInfo::Make(fWidth, fHeight, fColorType, newAlphaType, fProfileType);
232    }
233
234    SkImageInfo makeColorType(SkColorType newColorType) const {
235        return SkImageInfo::Make(fWidth, fHeight, newColorType, fAlphaType, fProfileType);
236    }
237
238    int bytesPerPixel() const {
239        return SkColorTypeBytesPerPixel(fColorType);
240    }
241
242    uint64_t minRowBytes64() const {
243        return sk_64_mul(fWidth, this->bytesPerPixel());
244    }
245
246    size_t minRowBytes() const {
247        return (size_t)this->minRowBytes64();
248    }
249
250    bool operator==(const SkImageInfo& other) const {
251        return 0 == memcmp(this, &other, sizeof(other));
252    }
253    bool operator!=(const SkImageInfo& other) const {
254        return 0 != memcmp(this, &other, sizeof(other));
255    }
256
257    void unflatten(SkReadBuffer&);
258    void flatten(SkWriteBuffer&) const;
259
260    int64_t getSafeSize64(size_t rowBytes) const {
261        if (0 == fHeight) {
262            return 0;
263        }
264        return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel();
265    }
266
267    size_t getSafeSize(size_t rowBytes) const {
268        return (size_t)this->getSafeSize64(rowBytes);
269    }
270
271    bool validRowBytes(size_t rowBytes) const {
272        uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel());
273        return rowBytes >= rb;
274    }
275
276    SkDEBUGCODE(void validate() const;)
277
278#ifdef SK_SUPPORT_LEGACY_PUBLIC_IMAGEINFO_FIELDS
279public:
280#else
281private:
282#endif
283    int                 fWidth;
284    int                 fHeight;
285    SkColorType         fColorType;
286    SkAlphaType         fAlphaType;
287
288private:
289    SkImageInfo(int width, int height, SkColorType ct, SkAlphaType at, SkColorProfileType pt)
290        : fWidth(width)
291        , fHeight(height)
292        , fColorType(ct)
293        , fAlphaType(at)
294        , fProfileType(pt)
295    {}
296
297    SkColorProfileType  fProfileType;
298};
299
300#endif
301