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 
13 class SkColorSpace;
14 
15 struct SkEncodedInfo {
16 public:
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 
MakeSkEncodedInfo70     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      */
makeImageInfoSkEncodedInfo120     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 
colorSkEncodedInfo128     Color color() const { return fColor; }
alphaSkEncodedInfo129     Alpha alpha() const { return fAlpha; }
opaqueSkEncodedInfo130     bool opaque() const { return fAlpha == kOpaque_Alpha; }
131 
bitsPerComponentSkEncodedInfo132     uint8_t bitsPerComponent() const { return fBitsPerComponent; }
133 
bitsPerPixelSkEncodedInfo134     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 
159 private:
160 
SkEncodedInfoSkEncodedInfo161     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