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