• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "include/core/SkAlphaType.h"
12 #include "include/core/SkColorSpace.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkData.h"
15 #include "include/core/SkImageInfo.h"
16 #include "include/core/SkRefCnt.h"
17 #include "include/core/SkTypes.h"
18 #include "modules/skcms/skcms.h"
19 
20 #include <cstdint>
21 #include <memory>
22 #include <utility>
23 
24 struct SkEncodedInfo {
25 public:
26     class ICCProfile {
27     public:
28         static std::unique_ptr<ICCProfile> Make(sk_sp<SkData>);
29         static std::unique_ptr<ICCProfile> Make(const skcms_ICCProfile&);
30 
profileSkEncodedInfo31         const skcms_ICCProfile* profile() const { return &fProfile; }
32     private:
33         ICCProfile(const skcms_ICCProfile&, sk_sp<SkData> = nullptr);
34 
35         skcms_ICCProfile fProfile;
36         sk_sp<SkData>    fData;
37     };
38 
39     enum Alpha {
40         kOpaque_Alpha,
41         kUnpremul_Alpha,
42 
43         // Each pixel is either fully opaque or fully transparent.
44         // There is no difference between requesting kPremul or kUnpremul.
45         kBinary_Alpha,
46     };
47 
48     /*
49      * We strive to make the number of components per pixel obvious through
50      * our naming conventions.
51      * Ex: kRGB has 3 components.  kRGBA has 4 components.
52      *
53      * This sometimes results in redundant Alpha and Color information.
54      * Ex: kRGB images must also be kOpaque.
55      */
56     enum Color {
57         // PNG, WBMP
58         kGray_Color,
59 
60         // PNG
61         kGrayAlpha_Color,
62 
63         // PNG with Skia-specific sBIT
64         // Like kGrayAlpha, except this expects to be treated as
65         // kAlpha_8_SkColorType, which ignores the gray component. If
66         // decoded to full color (e.g. kN32), the gray component is respected
67         // (so it can share code with kGrayAlpha).
68         kXAlpha_Color,
69 
70         // PNG
71         // 565 images may be encoded to PNG by specifying the number of
72         // significant bits for each channel.  This is a strange 565
73         // representation because the image is still encoded with 8 bits per
74         // component.
75         k565_Color,
76 
77         // PNG, GIF, BMP
78         kPalette_Color,
79 
80         // PNG, RAW
81         kRGB_Color,
82         kRGBA_Color,
83 
84         // BMP
85         kBGR_Color,
86         kBGRX_Color,
87         kBGRA_Color,
88 
89         // JPEG, WEBP
90         kYUV_Color,
91 
92         // WEBP
93         kYUVA_Color,
94 
95         // JPEG
96         // Photoshop actually writes inverted CMYK data into JPEGs, where zero
97         // represents 100% ink coverage.  For this reason, we treat CMYK JPEGs
98         // as having inverted CMYK.  libjpeg-turbo warns that this may break
99         // other applications, but the CMYK JPEGs we see on the web expect to
100         // be treated as inverted CMYK.
101         kInvertedCMYK_Color,
102         kYCCK_Color,
103     };
104 
MakeSkEncodedInfo105     static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha,
106             int bitsPerComponent) {
107         return Make(width, height, color, alpha, bitsPerComponent, nullptr);
108     }
109 
MakeSkEncodedInfo110     static SkEncodedInfo Make(int width, int height, Color color,
111             Alpha alpha, int bitsPerComponent, std::unique_ptr<ICCProfile> profile) {
112         return Make(width, height, color, alpha, /*bitsPerComponent*/ bitsPerComponent,
113                 std::move(profile), /*colorDepth*/ bitsPerComponent);
114     }
115 
MakeSkEncodedInfo116     static SkEncodedInfo Make(int width, int height, Color color,
117             Alpha alpha, int bitsPerComponent, std::unique_ptr<ICCProfile> profile,
118             int colorDepth) {
119         SkASSERT(1 == bitsPerComponent ||
120                  2 == bitsPerComponent ||
121                  4 == bitsPerComponent ||
122                  8 == bitsPerComponent ||
123                  16 == bitsPerComponent);
124 
125         switch (color) {
126             case kGray_Color:
127                 SkASSERT(kOpaque_Alpha == alpha);
128                 break;
129             case kGrayAlpha_Color:
130                 SkASSERT(kOpaque_Alpha != alpha);
131                 break;
132             case kPalette_Color:
133                 SkASSERT(16 != bitsPerComponent);
134                 break;
135             case kRGB_Color:
136             case kBGR_Color:
137             case kBGRX_Color:
138                 SkASSERT(kOpaque_Alpha == alpha);
139                 SkASSERT(bitsPerComponent >= 8);
140                 break;
141             case kYUV_Color:
142             case kInvertedCMYK_Color:
143             case kYCCK_Color:
144                 SkASSERT(kOpaque_Alpha == alpha);
145                 SkASSERT(8 == bitsPerComponent);
146                 break;
147             case kRGBA_Color:
148                 SkASSERT(bitsPerComponent >= 8);
149                 break;
150             case kBGRA_Color:
151             case kYUVA_Color:
152                 SkASSERT(8 == bitsPerComponent);
153                 break;
154             case kXAlpha_Color:
155                 SkASSERT(kUnpremul_Alpha == alpha);
156                 SkASSERT(8 == bitsPerComponent);
157                 break;
158             case k565_Color:
159                 SkASSERT(kOpaque_Alpha == alpha);
160                 SkASSERT(8 == bitsPerComponent);
161                 break;
162             default:
163                 SkASSERT(false);
164                 break;
165         }
166 
167         return SkEncodedInfo(width, height, color, alpha,
168                 bitsPerComponent, colorDepth, std::move(profile));
169     }
170 
171     /*
172      * Returns a recommended SkImageInfo.
173      *
174      * TODO: Leave this up to the client.
175      */
makeImageInfoSkEncodedInfo176     SkImageInfo makeImageInfo() const {
177         auto ct =  kGray_Color == fColor ? kGray_8_SkColorType   :
178                  kXAlpha_Color == fColor ? kAlpha_8_SkColorType  :
179                     k565_Color == fColor ? kRGB_565_SkColorType  :
180                                            kN32_SkColorType      ;
181         auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType
182                                              : kUnpremul_SkAlphaType;
183         sk_sp<SkColorSpace> cs = fProfile ? SkColorSpace::Make(*fProfile->profile())
184                                           : nullptr;
185         if (!cs) {
186             cs = SkColorSpace::MakeSRGB();
187         }
188         return SkImageInfo::Make(fWidth, fHeight, ct, alpha, std::move(cs));
189     }
190 
widthSkEncodedInfo191     int   width() const { return fWidth;  }
heightSkEncodedInfo192     int  height() const { return fHeight; }
colorSkEncodedInfo193     Color color() const { return fColor;  }
alphaSkEncodedInfo194     Alpha alpha() const { return fAlpha;  }
opaqueSkEncodedInfo195     bool opaque() const { return fAlpha == kOpaque_Alpha; }
profileSkEncodedInfo196     const skcms_ICCProfile* profile() const {
197         if (!fProfile) return nullptr;
198         return fProfile->profile();
199     }
200 
bitsPerComponentSkEncodedInfo201     uint8_t bitsPerComponent() const { return fBitsPerComponent; }
202 
bitsPerPixelSkEncodedInfo203     uint8_t bitsPerPixel() const {
204         switch (fColor) {
205             case kGray_Color:
206                 return fBitsPerComponent;
207             case kXAlpha_Color:
208             case kGrayAlpha_Color:
209                 return 2 * fBitsPerComponent;
210             case kPalette_Color:
211                 return fBitsPerComponent;
212             case kRGB_Color:
213             case kBGR_Color:
214             case kYUV_Color:
215             case k565_Color:
216                 return 3 * fBitsPerComponent;
217             case kRGBA_Color:
218             case kBGRA_Color:
219             case kBGRX_Color:
220             case kYUVA_Color:
221             case kInvertedCMYK_Color:
222             case kYCCK_Color:
223                 return 4 * fBitsPerComponent;
224             default:
225                 SkASSERT(false);
226                 return 0;
227         }
228     }
229 
230     SkEncodedInfo(const SkEncodedInfo& orig) = delete;
231     SkEncodedInfo& operator=(const SkEncodedInfo&) = delete;
232 
233     SkEncodedInfo(SkEncodedInfo&& orig) = default;
234     SkEncodedInfo& operator=(SkEncodedInfo&&) = default;
235 
236     // Explicit copy method, to avoid accidental copying.
copySkEncodedInfo237     SkEncodedInfo copy() const {
238         auto copy = SkEncodedInfo::Make(
239                 fWidth, fHeight, fColor, fAlpha, fBitsPerComponent, nullptr, fColorDepth);
240         if (fProfile) {
241             copy.fProfile = std::make_unique<ICCProfile>(*fProfile);
242         }
243         return copy;
244     }
245 
246     // Return number of bits of R/G/B channel
getColorDepthSkEncodedInfo247     uint8_t getColorDepth() const {
248         return fColorDepth;
249     }
250 
251 private:
SkEncodedInfoSkEncodedInfo252     SkEncodedInfo(int width, int height, Color color, Alpha alpha,
253             uint8_t bitsPerComponent, uint8_t colorDepth, std::unique_ptr<ICCProfile> profile)
254         : fWidth(width)
255         , fHeight(height)
256         , fColor(color)
257         , fAlpha(alpha)
258         , fBitsPerComponent(bitsPerComponent)
259         , fColorDepth(colorDepth)
260         , fProfile(std::move(profile))
261     {}
262 
263     int                         fWidth;
264     int                         fHeight;
265     Color                       fColor;
266     Alpha                       fAlpha;
267     uint8_t                     fBitsPerComponent;
268     uint8_t                     fColorDepth;
269     std::unique_ptr<ICCProfile> fProfile;
270 };
271 
272 #endif
273