xref: /aosp_15_r20/external/skia/include/private/SkEncodedInfo.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 
profileSkEncodedInfo32         const skcms_ICCProfile* profile() const { return &fProfile; }
dataSkEncodedInfo33         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 
MakeSkEncodedInfo107     static SkEncodedInfo Make(int width, int height, Color color, Alpha alpha,
108             int bitsPerComponent) {
109         return Make(width, height, color, alpha, bitsPerComponent, nullptr);
110     }
111 
MakeSkEncodedInfo112     static SkEncodedInfo Make(int width, int height, Color color,
113             Alpha alpha, int bitsPerComponent, std::unique_ptr<ICCProfile> profile) {
114         return Make(width, height, color, alpha, /*bitsPerComponent*/ bitsPerComponent,
115                 std::move(profile), /*colorDepth*/ bitsPerComponent);
116     }
117 
MakeSkEncodedInfo118     static SkEncodedInfo Make(int width, int height, Color color,
119             Alpha alpha, int bitsPerComponent, std::unique_ptr<ICCProfile> profile,
120             int colorDepth) {
121         SkASSERT(1 == bitsPerComponent ||
122                  2 == bitsPerComponent ||
123                  4 == bitsPerComponent ||
124                  8 == bitsPerComponent ||
125                  16 == bitsPerComponent);
126 
127         switch (color) {
128             case kGray_Color:
129                 SkASSERT(kOpaque_Alpha == alpha);
130                 break;
131             case kGrayAlpha_Color:
132                 SkASSERT(kOpaque_Alpha != alpha);
133                 break;
134             case kPalette_Color:
135                 SkASSERT(16 != bitsPerComponent);
136                 break;
137             case kRGB_Color:
138             case kBGR_Color:
139             case kBGRX_Color:
140                 SkASSERT(kOpaque_Alpha == alpha);
141                 SkASSERT(bitsPerComponent >= 8);
142                 break;
143             case kYUV_Color:
144             case kInvertedCMYK_Color:
145             case kYCCK_Color:
146                 SkASSERT(kOpaque_Alpha == alpha);
147                 SkASSERT(8 == bitsPerComponent);
148                 break;
149             case kRGBA_Color:
150                 SkASSERT(bitsPerComponent >= 8);
151                 break;
152             case kBGRA_Color:
153             case kYUVA_Color:
154                 SkASSERT(8 == bitsPerComponent);
155                 break;
156             case kXAlpha_Color:
157                 SkASSERT(kUnpremul_Alpha == alpha);
158                 SkASSERT(8 == bitsPerComponent);
159                 break;
160             case k565_Color:
161                 SkASSERT(kOpaque_Alpha == alpha);
162                 SkASSERT(8 == bitsPerComponent);
163                 break;
164             default:
165                 SkASSERT(false);
166                 break;
167         }
168 
169         return SkEncodedInfo(width,
170                              height,
171                              color,
172                              alpha,
173                              SkToU8(bitsPerComponent),
174                              SkToU8(colorDepth),
175                              std::move(profile));
176     }
177 
178     /*
179      * Returns a recommended SkImageInfo.
180      *
181      * TODO: Leave this up to the client.
182      */
makeImageInfoSkEncodedInfo183     SkImageInfo makeImageInfo() const {
184         auto ct =  kGray_Color == fColor ? kGray_8_SkColorType   :
185                  kXAlpha_Color == fColor ? kAlpha_8_SkColorType  :
186                     k565_Color == fColor ? kRGB_565_SkColorType  :
187                                            kN32_SkColorType      ;
188         auto alpha = kOpaque_Alpha == fAlpha ? kOpaque_SkAlphaType
189                                              : kUnpremul_SkAlphaType;
190         sk_sp<SkColorSpace> cs = fProfile ? SkColorSpace::Make(*fProfile->profile())
191                                           : nullptr;
192         if (!cs) {
193             cs = SkColorSpace::MakeSRGB();
194         }
195         return SkImageInfo::Make(fWidth, fHeight, ct, alpha, std::move(cs));
196     }
197 
widthSkEncodedInfo198     int   width() const { return fWidth;  }
heightSkEncodedInfo199     int  height() const { return fHeight; }
colorSkEncodedInfo200     Color color() const { return fColor;  }
alphaSkEncodedInfo201     Alpha alpha() const { return fAlpha;  }
opaqueSkEncodedInfo202     bool opaque() const { return fAlpha == kOpaque_Alpha; }
profileSkEncodedInfo203     const skcms_ICCProfile* profile() const {
204         if (!fProfile) return nullptr;
205         return fProfile->profile();
206     }
profileDataSkEncodedInfo207     sk_sp<SkData> profileData() const {
208         if (!fProfile) return nullptr;
209         return fProfile->data();
210     }
211 
bitsPerComponentSkEncodedInfo212     uint8_t bitsPerComponent() const { return fBitsPerComponent; }
213 
bitsPerPixelSkEncodedInfo214     uint8_t bitsPerPixel() const {
215         switch (fColor) {
216             case kGray_Color:
217                 return fBitsPerComponent;
218             case kXAlpha_Color:
219             case kGrayAlpha_Color:
220                 return 2 * fBitsPerComponent;
221             case kPalette_Color:
222                 return fBitsPerComponent;
223             case kRGB_Color:
224             case kBGR_Color:
225             case kYUV_Color:
226             case k565_Color:
227                 return 3 * fBitsPerComponent;
228             case kRGBA_Color:
229             case kBGRA_Color:
230             case kBGRX_Color:
231             case kYUVA_Color:
232             case kInvertedCMYK_Color:
233             case kYCCK_Color:
234                 return 4 * fBitsPerComponent;
235             default:
236                 SkASSERT(false);
237                 return 0;
238         }
239     }
240 
241     SkEncodedInfo(const SkEncodedInfo& orig) = delete;
242     SkEncodedInfo& operator=(const SkEncodedInfo&) = delete;
243 
244     SkEncodedInfo(SkEncodedInfo&& orig) = default;
245     SkEncodedInfo& operator=(SkEncodedInfo&&) = default;
246 
247     // Explicit copy method, to avoid accidental copying.
copySkEncodedInfo248     SkEncodedInfo copy() const {
249         auto copy = SkEncodedInfo::Make(
250                 fWidth, fHeight, fColor, fAlpha, fBitsPerComponent, nullptr, fColorDepth);
251         if (fProfile) {
252             copy.fProfile = std::make_unique<ICCProfile>(*fProfile);
253         }
254         return copy;
255     }
256 
257     // Return number of bits of R/G/B channel
getColorDepthSkEncodedInfo258     uint8_t getColorDepth() const {
259         return fColorDepth;
260     }
261 
262 private:
SkEncodedInfoSkEncodedInfo263     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     {}
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
284