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 */
71enum SkColorType {
72    kUnknown_SkColorType,
73    kAlpha_8_SkColorType,
74    kRGB_565_SkColorType,
75    kARGB_4444_SkColorType,
76    kRGBA_8888_SkColorType,
77    kBGRA_8888_SkColorType,
78    kIndex_8_SkColorType,
79
80    kLastEnum_SkColorType = kIndex_8_SkColorType,
81
82#if SK_PMCOLOR_BYTE_ORDER(B,G,R,A)
83    kN32_SkColorType = kBGRA_8888_SkColorType,
84#elif SK_PMCOLOR_BYTE_ORDER(R,G,B,A)
85    kN32_SkColorType = kRGBA_8888_SkColorType,
86#else
87#error "SK_*32_SHFIT values must correspond to BGRA or RGBA byte order"
88#endif
89
90#ifdef SK_SUPPORT_LEGACY_N32_NAME
91    kPMColor_SkColorType = kN32_SkColorType
92#endif
93};
94
95static int SkColorTypeBytesPerPixel(SkColorType ct) {
96    static const uint8_t gSize[] = {
97        0,  // Unknown
98        1,  // Alpha_8
99        2,  // RGB_565
100        2,  // ARGB_4444
101        4,  // RGBA_8888
102        4,  // BGRA_8888
103        1,  // kIndex_8
104    };
105    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gSize) == (size_t)(kLastEnum_SkColorType + 1),
106                      size_mismatch_with_SkColorType_enum);
107
108    SkASSERT((size_t)ct < SK_ARRAY_COUNT(gSize));
109    return gSize[ct];
110}
111
112static inline size_t SkColorTypeMinRowBytes(SkColorType ct, int width) {
113    return width * SkColorTypeBytesPerPixel(ct);
114}
115
116static inline bool SkColorTypeIsValid(unsigned value) {
117    return value <= kLastEnum_SkColorType;
118}
119
120///////////////////////////////////////////////////////////////////////////////
121
122/**
123 *  Describe an image's dimensions and pixel type.
124 */
125struct SkImageInfo {
126    int         fWidth;
127    int         fHeight;
128    SkColorType fColorType;
129    SkAlphaType fAlphaType;
130
131    static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at) {
132        SkImageInfo info = {
133            width, height, ct, at
134        };
135        return info;
136    }
137
138    /**
139     *  Sets colortype to the native ARGB32 type.
140     */
141    static SkImageInfo MakeN32(int width, int height, SkAlphaType at) {
142        SkImageInfo info = {
143            width, height, kN32_SkColorType, at
144        };
145        return info;
146    }
147
148    /**
149     *  Sets colortype to the native ARGB32 type, and the alphatype to premul.
150     */
151    static SkImageInfo MakeN32Premul(int width, int height) {
152        SkImageInfo info = {
153            width, height, kN32_SkColorType, kPremul_SkAlphaType
154        };
155        return info;
156    }
157
158    /**
159     *  Sets colortype to the native ARGB32 type, and the alphatype to premul.
160     */
161    static SkImageInfo MakeN32Premul(const SkISize& size) {
162        return MakeN32Premul(size.width(), size.height());
163    }
164
165    static SkImageInfo MakeA8(int width, int height) {
166        SkImageInfo info = {
167            width, height, kAlpha_8_SkColorType, kPremul_SkAlphaType
168        };
169        return info;
170    }
171
172    static SkImageInfo MakeUnknown(int width, int height) {
173        SkImageInfo info = {
174            width, height, kUnknown_SkColorType, kIgnore_SkAlphaType
175        };
176        return info;
177    }
178
179    static SkImageInfo MakeUnknown() {
180        SkImageInfo info = {
181            0, 0, kUnknown_SkColorType, kIgnore_SkAlphaType
182        };
183        return info;
184    }
185
186    int width() const { return fWidth; }
187    int height() const { return fHeight; }
188    SkColorType colorType() const { return fColorType; }
189    SkAlphaType alphaType() const { return fAlphaType; }
190
191    bool isEmpty() const { return fWidth <= 0 || fHeight <= 0; }
192
193    bool isOpaque() const {
194        return SkAlphaTypeIsOpaque(fAlphaType);
195    }
196
197    SkISize dimensions() const { return SkISize::Make(fWidth, fHeight); }
198
199    /**
200     *  Return a new ImageInfo with the same colortype and alphatype as this info,
201     *  but with the specified width and height.
202     */
203    SkImageInfo makeWH(int newWidth, int newHeight) const {
204        return SkImageInfo::Make(newWidth, newHeight, fColorType, fAlphaType);
205    }
206
207    int bytesPerPixel() const {
208        return SkColorTypeBytesPerPixel(fColorType);
209    }
210
211    uint64_t minRowBytes64() const {
212        return sk_64_mul(fWidth, this->bytesPerPixel());
213    }
214
215    size_t minRowBytes() const {
216        return (size_t)this->minRowBytes64();
217    }
218
219    bool operator==(const SkImageInfo& other) const {
220        return 0 == memcmp(this, &other, sizeof(other));
221    }
222    bool operator!=(const SkImageInfo& other) const {
223        return 0 != memcmp(this, &other, sizeof(other));
224    }
225
226    void unflatten(SkReadBuffer&);
227    void flatten(SkWriteBuffer&) const;
228
229    int64_t getSafeSize64(size_t rowBytes) const {
230        if (0 == fHeight) {
231            return 0;
232        }
233        return sk_64_mul(fHeight - 1, rowBytes) + fWidth * this->bytesPerPixel();
234    }
235
236    size_t getSafeSize(size_t rowBytes) const {
237        return (size_t)this->getSafeSize64(rowBytes);
238    }
239
240    bool validRowBytes(size_t rowBytes) const {
241        uint64_t rb = sk_64_mul(fWidth, this->bytesPerPixel());
242        return rowBytes >= rb;
243    }
244
245    SkDEBUGCODE(void validate() const;)
246};
247
248#endif
249