blob: a539824afb956fd5bbb2af1cb79595c4e9bb54c5 [file] [log] [blame]
msarettc30c4182016-04-20 11:53:35 -07001/*
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
Leon Scroggins III36f7e322018-08-27 11:55:46 -040011#include "SkData.h"
msarettc30c4182016-04-20 11:53:35 -070012#include "SkImageInfo.h"
Leon Scroggins III36f7e322018-08-27 11:55:46 -040013#include "../../third_party/skcms/skcms.h"
msarettc30c4182016-04-20 11:53:35 -070014
15struct SkEncodedInfo {
16public:
Leon Scroggins III36f7e322018-08-27 11:55:46 -040017 class ICCProfile {
18 public:
19 static std::unique_ptr<ICCProfile> Make(sk_sp<SkData>);
Leon Scroggins III36f7e322018-08-27 11:55:46 -040020 static std::unique_ptr<ICCProfile> Make(const skcms_ICCProfile&);
21
22 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 };
msarettc30c4182016-04-20 11:53:35 -070029
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,
msarettc30c4182016-04-20 11:53:35 -070037 };
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
Leon Scroggins III36f7e322018-08-27 11:55:46 -040054 // 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
msarettc30c4182016-04-20 11:53:35 -070068 // 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,
msarettc30c4182016-04-20 11:53:35 -070094 };
95
Leon Scroggins III36f7e322018-08-27 11:55:46 -040096 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
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400101 static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha,
102 int bitsPerComponent, std::unique_ptr<ICCProfile> profile) {
msarettc30c4182016-04-20 11:53:35 -0700103 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(kOpaque_Alpha != alpha);
133 SkASSERT(bitsPerComponent >= 8);
134 break;
135 case kBGRA_Color:
136 case kYUVA_Color:
137 SkASSERT(kOpaque_Alpha != alpha);
138 SkASSERT(8 == bitsPerComponent);
139 break;
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400140 case kXAlpha_Color:
141 SkASSERT(kUnpremul_Alpha == alpha);
142 SkASSERT(8 == bitsPerComponent);
143 break;
144 case k565_Color:
145 SkASSERT(kOpaque_Alpha == alpha);
146 SkASSERT(8 == bitsPerComponent);
147 break;
msarettc30c4182016-04-20 11:53:35 -0700148 default:
149 SkASSERT(false);
150 break;
151 }
152
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400153 return SkEncodedInfo(width, height, color, alpha, bitsPerComponent, std::move(profile));
msarettc30c4182016-04-20 11:53:35 -0700154 }
155
156 /*
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400157 * Returns a recommended SkImageInfo.
158 *
159 * TODO: Leave this up to the client.
msarettc30c4182016-04-20 11:53:35 -0700160 */
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400161 SkImageInfo makeImageInfo() const {
162 auto ct = kGray_Color == fColor ? kGray_8_SkColorType :
163 kXAlpha_Color == fColor ? kAlpha_8_SkColorType :
164 k565_Color == fColor ? kRGB_565_SkColorType :
165 kN32_SkColorType ;
Leon Scroggins IIIc8037dc2017-12-05 13:55:24 -0500166 auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType
167 : kUnpremul_SkAlphaType;
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400168 sk_sp<SkColorSpace> cs = fProfile ? SkColorSpace::Make(*fProfile->profile())
169 : nullptr;
170 if (!cs) {
171 cs = SkColorSpace::MakeSRGB();
172 }
173 return SkImageInfo::Make(fWidth, fHeight, ct, alpha, std::move(cs));
msarettc30c4182016-04-20 11:53:35 -0700174 }
175
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400176 int width() const { return fWidth; }
177 int height() const { return fHeight; }
178 Color color() const { return fColor; }
179 Alpha alpha() const { return fAlpha; }
Leon Scroggins III07418182017-08-15 12:24:02 -0400180 bool opaque() const { return fAlpha == kOpaque_Alpha; }
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400181 const skcms_ICCProfile* profile() const {
182 if (!fProfile) return nullptr;
183 return fProfile->profile();
184 }
Leon Scroggins III07418182017-08-15 12:24:02 -0400185
msaretta45a6682016-04-22 13:18:37 -0700186 uint8_t bitsPerComponent() const { return fBitsPerComponent; }
187
188 uint8_t bitsPerPixel() const {
189 switch (fColor) {
190 case kGray_Color:
191 return fBitsPerComponent;
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400192 case kXAlpha_Color:
msaretta45a6682016-04-22 13:18:37 -0700193 case kGrayAlpha_Color:
194 return 2 * fBitsPerComponent;
195 case kPalette_Color:
196 return fBitsPerComponent;
197 case kRGB_Color:
198 case kBGR_Color:
199 case kYUV_Color:
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400200 case k565_Color:
msaretta45a6682016-04-22 13:18:37 -0700201 return 3 * fBitsPerComponent;
202 case kRGBA_Color:
203 case kBGRA_Color:
204 case kBGRX_Color:
205 case kYUVA_Color:
206 case kInvertedCMYK_Color:
207 case kYCCK_Color:
208 return 4 * fBitsPerComponent;
209 default:
210 SkASSERT(false);
211 return 0;
212 }
213 }
214
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400215 SkEncodedInfo(const SkEncodedInfo& orig) = delete;
216 SkEncodedInfo& operator=(const SkEncodedInfo&) = delete;
Leon Scroggins83988ed2018-08-24 21:41:24 +0000217
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400218 SkEncodedInfo(SkEncodedInfo&& orig) = default;
219 SkEncodedInfo& operator=(SkEncodedInfo&&) = default;
220
221 // Explicit copy method, to avoid accidental copying.
222 SkEncodedInfo copy() const {
223 auto copy = SkEncodedInfo::Make(fWidth, fHeight, fColor, fAlpha, fBitsPerComponent);
224 if (fProfile) {
225 copy.fProfile.reset(new ICCProfile(*fProfile.get()));
226 }
227 return copy;
228 }
229
230private:
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)
msarettc30c4182016-04-20 11:53:35 -0700236 , fAlpha(alpha)
237 , fBitsPerComponent(bitsPerComponent)
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400238 , fProfile(std::move(profile))
msarettc30c4182016-04-20 11:53:35 -0700239 {}
240
Leon Scroggins III36f7e322018-08-27 11:55:46 -0400241 int fWidth;
242 int fHeight;
243 Color fColor;
244 Alpha fAlpha;
245 uint8_t fBitsPerComponent;
246 std::unique_ptr<ICCProfile> fProfile;
msarettc30c4182016-04-20 11:53:35 -0700247};
248
249#endif