SkImageInfo.h revision 64ba5fa1ff428858f803523257cd862f8b33423b
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 "SkSize.h"
13
14class SkWriteBuffer;
15class SkReadBuffer;
16
17/**
18 *  Describes how to interpret the alpha compoent of a pixel.
19 */
20enum SkAlphaType {
21    /**
22     *  All pixels should be treated as opaque, regardless of the value stored
23     *  in their alpha field. Used for legacy images that wrote 0 or garbarge
24     *  in their alpha field, but intended the RGB to be treated as opaque.
25     */
26    kIgnore_SkAlphaType,
27
28    /**
29     *  All pixels are stored as opaque. This differs slightly from kIgnore in
30     *  that kOpaque has correct "opaque" values stored in the pixels, while
31     *  kIgnore may not, but in both cases the caller should treat the pixels
32     *  as opaque.
33     */
34    kOpaque_SkAlphaType,
35
36    /**
37     *  All pixels have their alpha premultiplied in their color components.
38     *  This is the natural format for the rendering target pixels.
39     */
40    kPremul_SkAlphaType,
41
42    /**
43     *  All pixels have their color components stored without any regard to the
44     *  alpha. e.g. this is the default configuration for PNG images.
45     *
46     *  This alpha-type is ONLY supported for input images. Rendering cannot
47     *  generate this on output.
48     */
49    kUnpremul_SkAlphaType,
50
51    kLastEnum_SkAlphaType = kUnpremul_SkAlphaType
52};
53
54static inline bool SkAlphaTypeIsOpaque(SkAlphaType at) {
55    SK_COMPILE_ASSERT(kIgnore_SkAlphaType < kOpaque_SkAlphaType, bad_alphatype_order);
56    SK_COMPILE_ASSERT(kPremul_SkAlphaType > kOpaque_SkAlphaType, bad_alphatype_order);
57    SK_COMPILE_ASSERT(kUnpremul_SkAlphaType > kOpaque_SkAlphaType, bad_alphatype_order);
58
59    return (unsigned)at <= kOpaque_SkAlphaType;
60}
61
62static inline bool SkAlphaTypeIsValid(unsigned value) {
63    return value <= kLastEnum_SkAlphaType;
64}
65
66///////////////////////////////////////////////////////////////////////////////
67
68/**
69 *  Describes how to interpret the components of a pixel.
70 *
71 *  kN32_SkColorType is an alias for whichever 32bit ARGB format is the "native"
72 *  form for skia's blitters. Use this if you don't have a swizzle preference
73 *  for 32bit pixels.
74 */
75enum SkColorType {
76    kUnknown_SkColorType,
77    kAlpha_8_SkColorType,
78    kRGB_565_SkColorType,
79    kARGB_4444_SkColorType,
80    kRGBA_8888_SkColorType,
81    kBGRA_8888_SkColorType,
82    kIndex_8_SkColorType,
83
84    kLastEnum_SkColorType = kIndex_8_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_SHFIT values must correspond to BGRA or RGBA byte order"
92#endif
93
94#ifdef SK_SUPPORT_LEGACY_N32_NAME
95    kPMColor_SkColorType = kN32_SkColorType
96#endif
97};
98
99static int SkColorTypeBytesPerPixel(SkColorType ct) {
100    static const uint8_t gSize[] = {
101        0,  // Unknown
102        1,  // Alpha_8
103        2,  // RGB_565
104        2,  // ARGB_4444
105        4,  // RGBA_8888
106        4,  // BGRA_8888
107        1,  // kIndex_8
108    };
109    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1),
110                      size_mismatch_with_SkColorType_enum);
111
112    SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize));
113    return gSize[ct];
114}
115
116static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
117    return width * SkColorTypeBytesPerPixel(ct);
118}
119
120static inline bool SkColorTypeIsValid(unsigned value) {
121    return value <= kLastEnum_SkColorType;
122}
123
124///////////////////////////////////////////////////////////////////////////////
125
126/**
127 *  Return true if alphaType is supported by colorType. If there is a canonical
128 *  alphaType for this colorType, return it in canonical.
129 */
130bool SkColorTypeValidateAlphaType(SkColorType colorType, SkAlphaType alphaType,
131                                  SkAlphaType* canonical = NULL);
132
133///////////////////////////////////////////////////////////////////////////////
134
135/**
136 *  Describe an image's dimensions and pixel type.
137 */
138struct SkImageInfo {
139    int         fWidth;
140    int         fHeight;
141    SkColorType fColorType;
142    SkAlphaType fAlphaType;
143
144    static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at) {
145        SkImageInfo info = {
146            width, height, ct, at
147        };
148        return info;
149    }
150
151    /**
152     *  Sets colortype to the native ARGB32 type.
153     */
154    static SkImageInfo MakeN32(int width, int height, SkAlphaType at) {
155        SkImageInfo info = {
156            width, height, kN32_SkColorType, at
157        };
158        return info;
159    }
160
161    /**
162     *  Sets colortype to the native ARGB32 type, and the alphatype to premul.
163     */
164    static SkImageInfo MakeN32Premul(int width, int height) {
165        SkImageInfo info = {
166            width, height, kN32_SkColorType, kPremul_SkAlphaType
167        };
168        return info;
169    }
170
171    /**
172     *  Sets colortype to the native ARGB32 type, and the alphatype to premul.
173     */
174    static SkImageInfo MakeN32Premul(const SkISize& size) {
175        return MakeN32Premul(size.width(), size.height());
176    }
177
178    static SkImageInfo MakeA8(int width, int height) {
179        SkImageInfo info = {
180            width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType
181        };
182        return info;
183    }
184
185    static SkImageInfo MakeUnknown(int width, int height) {
186        SkImageInfo info = {
187            width, height, kUnknown_SkColorType, kIgnore_SkAlphaType
188        };
189        return info;
190    }
191
192    static SkImageInfo MakeUnknown() {
193        SkImageInfo info = {
194            0, 0, kUnknown_SkColorType, kIgnore_SkAlphaType
195        };
196        return info;
197    }
198
199    int width() const { return fWidth; }
200    int height() const { return fHeight; }
201    SkColorType colorType() const { return fColorType; }
202    SkAlphaType alphaType() const { return fAlphaType; }
203
204    bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
205
206    bool isOpaque() const {
207        return SkAlphaTypeIsOpaque(fAlphaType);
208    }
209
210    SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
211
212    /**
213     *  Return a new ImageInfo with the same colortype and alphatype as this info,
214     *  but with the specified width and height.
215     */
216    SkImageInfo makeWH(int newWidth, int newHeight) const {
217        return SkImageInfo::Make(newWidth, newHeight, fColorType, fAlphaType);
218    }
219
220    int bytesPerPixel() const {
221        return SkColorTypeBytesPerPixel(fColorType);
222    }
223
224    uint64_t minRowBytes64() const {
225        return sk_64_mul(fWidth, this->bytesPerPixel());
226    }
227
228    size_t minRowBytes() const {
229        return (size_t)this->minRowBytes64();
230    }
231
232    bool operator==(const SkImageInfo& other) const {
233        return 0 == memcmp(this, &other, sizeof(other));
234    }
235    bool operator!=(const SkImageInfo& other) const {
236        return 0 != memcmp(this, &other, sizeof(other));
237    }
238
239    void unflatten(SkReadBuffer&);
240    void flatten(SkWriteBuffer&) const;
241
242    int64_t getSafeSize64(size_t rowBytes) const {
243        if (0 == fHeight) {
244            return 0;
245        }
246        return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel();
247    }
248
249    size_t getSafeSize(size_t rowBytes) const {
250        return (size_t)this->getSafeSize64(rowBytes);
251    }
252
253    bool validRowBytes(size_t rowBytes) const {
254        uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel());
255        return rowBytes >= rb;
256    }
257
258    SkDEBUGCODE(void validate() const;)
259};
260
261#endif
262