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