Coverage Report

Created: 2024-05-20 07:14

/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