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