1/*
2 * Copyright 2016 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 SkEncodedInfo_DEFINED
9#define SkEncodedInfo_DEFINED
10
11#include "SkImageInfo.h"
12
13class SkColorSpace;
14
15struct SkEncodedInfo {
16public:
17
18    enum Alpha {
19        kOpaque_Alpha,
20        kUnpremul_Alpha,
21
22        // Each pixel is either fully opaque or fully transparent.
23        // There is no difference between requesting kPremul or kUnpremul.
24        kBinary_Alpha,
25    };
26
27    /*
28     * We strive to make the number of components per pixel obvious through
29     * our naming conventions.
30     * Ex: kRGB has 3 components.  kRGBA has 4 components.
31     *
32     * This sometimes results in redundant Alpha and Color information.
33     * Ex: kRGB images must also be kOpaque.
34     */
35    enum Color {
36        // PNG, WBMP
37        kGray_Color,
38
39        // PNG
40        kGrayAlpha_Color,
41
42        // PNG, GIF, BMP
43        kPalette_Color,
44
45        // PNG, RAW
46        kRGB_Color,
47        kRGBA_Color,
48
49        // BMP
50        kBGR_Color,
51        kBGRX_Color,
52        kBGRA_Color,
53
54        // JPEG, WEBP
55        kYUV_Color,
56
57        // WEBP
58        kYUVA_Color,
59
60        // JPEG
61        // Photoshop actually writes inverted CMYK data into JPEGs, where zero
62        // represents 100% ink coverage.  For this reason, we treat CMYK JPEGs
63        // as having inverted CMYK.  libjpeg-turbo warns that this may break
64        // other applications, but the CMYK JPEGs we see on the web expect to
65        // be treated as inverted CMYK.
66        kInvertedCMYK_Color,
67        kYCCK_Color,
68    };
69
70    static SkEncodedInfo Make(Color color, Alpha alpha, int bitsPerComponent) {
71        SkASSERT(1 == bitsPerComponent ||
72                 2 == bitsPerComponent ||
73                 4 == bitsPerComponent ||
74                 8 == bitsPerComponent ||
75                 16 == bitsPerComponent);
76
77        switch (color) {
78            case kGray_Color:
79                SkASSERT(kOpaque_Alpha == alpha);
80                break;
81            case kGrayAlpha_Color:
82                SkASSERT(kOpaque_Alpha != alpha);
83                break;
84            case kPalette_Color:
85                SkASSERT(16 != bitsPerComponent);
86                break;
87            case kRGB_Color:
88            case kBGR_Color:
89            case kBGRX_Color:
90                SkASSERT(kOpaque_Alpha == alpha);
91                SkASSERT(bitsPerComponent >= 8);
92                break;
93            case kYUV_Color:
94            case kInvertedCMYK_Color:
95            case kYCCK_Color:
96                SkASSERT(kOpaque_Alpha == alpha);
97                SkASSERT(8 == bitsPerComponent);
98                break;
99            case kRGBA_Color:
100                SkASSERT(kOpaque_Alpha != alpha);
101                SkASSERT(bitsPerComponent >= 8);
102                break;
103            case kBGRA_Color:
104            case kYUVA_Color:
105                SkASSERT(kOpaque_Alpha != alpha);
106                SkASSERT(8 == bitsPerComponent);
107                break;
108            default:
109                SkASSERT(false);
110                break;
111        }
112
113        return SkEncodedInfo(color, alpha, bitsPerComponent);
114    }
115
116    /*
117     * Returns an SkImageInfo with Skia color and alpha types that are the
118     * closest possible match to the encoded info.
119     */
120    SkImageInfo makeImageInfo(int width, int height, sk_sp<SkColorSpace> colorSpace) const {
121        auto ct = kGray_Color == fColor ? kGray_8_SkColorType   :
122                                          kN32_SkColorType      ;
123        auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType
124                                             : kUnpremul_SkAlphaType;
125        return SkImageInfo::Make(width, height, ct, alpha, std::move(colorSpace));
126    }
127
128    Color color() const { return fColor; }
129    Alpha alpha() const { return fAlpha; }
130    bool opaque() const { return fAlpha == kOpaque_Alpha; }
131
132    uint8_t bitsPerComponent() const { return fBitsPerComponent; }
133
134    uint8_t bitsPerPixel() const {
135        switch (fColor) {
136            case kGray_Color:
137                return fBitsPerComponent;
138            case kGrayAlpha_Color:
139                return 2 * fBitsPerComponent;
140            case kPalette_Color:
141                return fBitsPerComponent;
142            case kRGB_Color:
143            case kBGR_Color:
144            case kYUV_Color:
145                return 3 * fBitsPerComponent;
146            case kRGBA_Color:
147            case kBGRA_Color:
148            case kBGRX_Color:
149            case kYUVA_Color:
150            case kInvertedCMYK_Color:
151            case kYCCK_Color:
152                return 4 * fBitsPerComponent;
153            default:
154                SkASSERT(false);
155                return 0;
156        }
157    }
158
159private:
160
161    SkEncodedInfo(Color color, Alpha alpha, uint8_t bitsPerComponent)
162        : fColor(color)
163        , fAlpha(alpha)
164        , fBitsPerComponent(bitsPerComponent)
165    {}
166
167    Color   fColor;
168    Alpha   fAlpha;
169    uint8_t fBitsPerComponent;
170};
171
172#endif
173