1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkAndroidCodec.h"
9*c8dee2aaSAndroid Build Coastguard Worker
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkEncodedImageFormat.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkStream.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skcms/skcms.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkAndroidCodecAdapter.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkCodecPriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkSampledCodec.h"
21*c8dee2aaSAndroid Build Coastguard Worker
22*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
23*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
24*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
25*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Worker class SkPngChunkReader;
28*c8dee2aaSAndroid Build Coastguard Worker
is_valid_sample_size(int sampleSize)29*c8dee2aaSAndroid Build Coastguard Worker static bool is_valid_sample_size(int sampleSize) {
30*c8dee2aaSAndroid Build Coastguard Worker // FIXME: As Leon has mentioned elsewhere, surely there is also a maximum sampleSize?
31*c8dee2aaSAndroid Build Coastguard Worker return sampleSize > 0;
32*c8dee2aaSAndroid Build Coastguard Worker }
33*c8dee2aaSAndroid Build Coastguard Worker
cicp_get_primaries(uint8_t primaries,skcms_Matrix3x3 * sk_primaries)34*c8dee2aaSAndroid Build Coastguard Worker static bool cicp_get_primaries(uint8_t primaries, skcms_Matrix3x3* sk_primaries) {
35*c8dee2aaSAndroid Build Coastguard Worker // Rec. ITU-T H.273, Table 2.
36*c8dee2aaSAndroid Build Coastguard Worker switch (primaries) {
37*c8dee2aaSAndroid Build Coastguard Worker case 0:
38*c8dee2aaSAndroid Build Coastguard Worker // Reserved.
39*c8dee2aaSAndroid Build Coastguard Worker break;
40*c8dee2aaSAndroid Build Coastguard Worker case 1:
41*c8dee2aaSAndroid Build Coastguard Worker *sk_primaries = SkNamedGamut::kSRGB;
42*c8dee2aaSAndroid Build Coastguard Worker return true;
43*c8dee2aaSAndroid Build Coastguard Worker case 2:
44*c8dee2aaSAndroid Build Coastguard Worker // Unspecified.
45*c8dee2aaSAndroid Build Coastguard Worker break;
46*c8dee2aaSAndroid Build Coastguard Worker case 3:
47*c8dee2aaSAndroid Build Coastguard Worker // Reserved.
48*c8dee2aaSAndroid Build Coastguard Worker break;
49*c8dee2aaSAndroid Build Coastguard Worker case 4:
50*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
51*c8dee2aaSAndroid Build Coastguard Worker 0.67f, 0.33f, 0.21f, 0.71f, 0.14f, 0.08f, 0.31f, 0.316f, sk_primaries);
52*c8dee2aaSAndroid Build Coastguard Worker case 5:
53*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
54*c8dee2aaSAndroid Build Coastguard Worker 0.64f, 0.33f, 0.29f, 0.60f, 0.15f, 0.06f, 0.3127f, 0.3290f, sk_primaries);
55*c8dee2aaSAndroid Build Coastguard Worker case 6:
56*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
57*c8dee2aaSAndroid Build Coastguard Worker 0.630f, 0.340f, 0.310f, 0.595f, 0.155f, 0.070f, 0.3127f, 0.3290f, sk_primaries);
58*c8dee2aaSAndroid Build Coastguard Worker case 7:
59*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
60*c8dee2aaSAndroid Build Coastguard Worker 0.630f, 0.340f, 0.310f, 0.595f, 0.155f, 0.070f, 0.3127f, 0.3290f, sk_primaries);
61*c8dee2aaSAndroid Build Coastguard Worker case 8:
62*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
63*c8dee2aaSAndroid Build Coastguard Worker 0.681f, 0.319f, 0.243f, 0.692f, 0.145f, 0.049f, 0.310f, 0.316f, sk_primaries);
64*c8dee2aaSAndroid Build Coastguard Worker case 9:
65*c8dee2aaSAndroid Build Coastguard Worker *sk_primaries = SkNamedGamut::kRec2020;
66*c8dee2aaSAndroid Build Coastguard Worker return true;
67*c8dee2aaSAndroid Build Coastguard Worker case 10:
68*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
69*c8dee2aaSAndroid Build Coastguard Worker 1.f, 0.f, 0.f, 1.f, 0.f, 0.f, 1.f / 3.f, 1.f / 3.f, sk_primaries);
70*c8dee2aaSAndroid Build Coastguard Worker case 11:
71*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
72*c8dee2aaSAndroid Build Coastguard Worker 0.680f, 0.320f, 0.265f, 0.690f, 0.150f, 0.060f, 0.314f, 0.351f, sk_primaries);
73*c8dee2aaSAndroid Build Coastguard Worker case 12:
74*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
75*c8dee2aaSAndroid Build Coastguard Worker 0.680f, 0.320f, 0.265f, 0.690f, 0.150f, 0.060f, 0.3127f, 0.3290f, sk_primaries);
76*c8dee2aaSAndroid Build Coastguard Worker case 22:
77*c8dee2aaSAndroid Build Coastguard Worker return skcms_PrimariesToXYZD50(
78*c8dee2aaSAndroid Build Coastguard Worker 0.630f, 0.340f, 0.295f, 0.605f, 0.155f, 0.077f, 0.3127f, 0.3290f, sk_primaries);
79*c8dee2aaSAndroid Build Coastguard Worker default:
80*c8dee2aaSAndroid Build Coastguard Worker // Reserved.
81*c8dee2aaSAndroid Build Coastguard Worker break;
82*c8dee2aaSAndroid Build Coastguard Worker }
83*c8dee2aaSAndroid Build Coastguard Worker *sk_primaries = SkNamedGamut::kSRGB;
84*c8dee2aaSAndroid Build Coastguard Worker return false;
85*c8dee2aaSAndroid Build Coastguard Worker }
86*c8dee2aaSAndroid Build Coastguard Worker
cicp_get_transfer_fn(uint8_t transfer_characteristics,skcms_TransferFunction * trfn)87*c8dee2aaSAndroid Build Coastguard Worker static bool cicp_get_transfer_fn(uint8_t transfer_characteristics, skcms_TransferFunction* trfn) {
88*c8dee2aaSAndroid Build Coastguard Worker // Rec. ITU-T H.273, Table 3.
89*c8dee2aaSAndroid Build Coastguard Worker switch (transfer_characteristics) {
90*c8dee2aaSAndroid Build Coastguard Worker case 0:
91*c8dee2aaSAndroid Build Coastguard Worker // Reserved.
92*c8dee2aaSAndroid Build Coastguard Worker break;
93*c8dee2aaSAndroid Build Coastguard Worker case 1:
94*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kRec2020;
95*c8dee2aaSAndroid Build Coastguard Worker return true;
96*c8dee2aaSAndroid Build Coastguard Worker case 2:
97*c8dee2aaSAndroid Build Coastguard Worker // Unspecified.
98*c8dee2aaSAndroid Build Coastguard Worker break;
99*c8dee2aaSAndroid Build Coastguard Worker case 3:
100*c8dee2aaSAndroid Build Coastguard Worker // Reserved.
101*c8dee2aaSAndroid Build Coastguard Worker break;
102*c8dee2aaSAndroid Build Coastguard Worker case 4:
103*c8dee2aaSAndroid Build Coastguard Worker *trfn = {2.2f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
104*c8dee2aaSAndroid Build Coastguard Worker return true;
105*c8dee2aaSAndroid Build Coastguard Worker case 5:
106*c8dee2aaSAndroid Build Coastguard Worker *trfn = {2.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f};
107*c8dee2aaSAndroid Build Coastguard Worker return true;
108*c8dee2aaSAndroid Build Coastguard Worker case 6:
109*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kRec2020;
110*c8dee2aaSAndroid Build Coastguard Worker return true;
111*c8dee2aaSAndroid Build Coastguard Worker case 7:
112*c8dee2aaSAndroid Build Coastguard Worker *trfn = {2.222222222222f,
113*c8dee2aaSAndroid Build Coastguard Worker 0.899626676224f,
114*c8dee2aaSAndroid Build Coastguard Worker 0.100373323776f,
115*c8dee2aaSAndroid Build Coastguard Worker 0.25f,
116*c8dee2aaSAndroid Build Coastguard Worker 0.091286342118f,
117*c8dee2aaSAndroid Build Coastguard Worker 0.f,
118*c8dee2aaSAndroid Build Coastguard Worker 0.f};
119*c8dee2aaSAndroid Build Coastguard Worker return true;
120*c8dee2aaSAndroid Build Coastguard Worker case 8:
121*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kLinear;
122*c8dee2aaSAndroid Build Coastguard Worker return true;
123*c8dee2aaSAndroid Build Coastguard Worker case 9:
124*c8dee2aaSAndroid Build Coastguard Worker // Logarithmic transfer characteristic (100:1 range).
125*c8dee2aaSAndroid Build Coastguard Worker // Not supported by skcms
126*c8dee2aaSAndroid Build Coastguard Worker break;
127*c8dee2aaSAndroid Build Coastguard Worker case 10:
128*c8dee2aaSAndroid Build Coastguard Worker // Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range).
129*c8dee2aaSAndroid Build Coastguard Worker // Not supported by skcms
130*c8dee2aaSAndroid Build Coastguard Worker break;
131*c8dee2aaSAndroid Build Coastguard Worker case 11:
132*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kSRGB;
133*c8dee2aaSAndroid Build Coastguard Worker break;
134*c8dee2aaSAndroid Build Coastguard Worker case 12:
135*c8dee2aaSAndroid Build Coastguard Worker // Rec. ITU-R BT.1361-0 extended colour gamut system (historical).
136*c8dee2aaSAndroid Build Coastguard Worker // Same as kRec709 on positive values, differs on negative values.
137*c8dee2aaSAndroid Build Coastguard Worker // Not supported by skcms
138*c8dee2aaSAndroid Build Coastguard Worker break;
139*c8dee2aaSAndroid Build Coastguard Worker case 13:
140*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kSRGB;
141*c8dee2aaSAndroid Build Coastguard Worker return true;
142*c8dee2aaSAndroid Build Coastguard Worker case 14:
143*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kRec2020;
144*c8dee2aaSAndroid Build Coastguard Worker return true;
145*c8dee2aaSAndroid Build Coastguard Worker case 15:
146*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kRec2020;
147*c8dee2aaSAndroid Build Coastguard Worker return true;
148*c8dee2aaSAndroid Build Coastguard Worker case 16:
149*c8dee2aaSAndroid Build Coastguard Worker // Android expects PQ to match 203 nits to SDR white
150*c8dee2aaSAndroid Build Coastguard Worker *trfn = {-2.f,
151*c8dee2aaSAndroid Build Coastguard Worker -1.55522297832f,
152*c8dee2aaSAndroid Build Coastguard Worker 1.86045365631f,
153*c8dee2aaSAndroid Build Coastguard Worker 32 / 2523.0f,
154*c8dee2aaSAndroid Build Coastguard Worker 2413 / 128.0f,
155*c8dee2aaSAndroid Build Coastguard Worker -2392 / 128.0f,
156*c8dee2aaSAndroid Build Coastguard Worker 8192 / 1305.0f};
157*c8dee2aaSAndroid Build Coastguard Worker return true;
158*c8dee2aaSAndroid Build Coastguard Worker case 17:
159*c8dee2aaSAndroid Build Coastguard Worker *trfn = {2.6f, 1.034080527699f, 0.f, 0.f, 0.f, 0.f, 0.f};
160*c8dee2aaSAndroid Build Coastguard Worker return true;
161*c8dee2aaSAndroid Build Coastguard Worker case 18:
162*c8dee2aaSAndroid Build Coastguard Worker // Android expects HLG to match 203 nits to SDR white
163*c8dee2aaSAndroid Build Coastguard Worker if (skcms_TransferFunction_makeScaledHLGish(trfn,
164*c8dee2aaSAndroid Build Coastguard Worker 0.314509843f,
165*c8dee2aaSAndroid Build Coastguard Worker 2.f,
166*c8dee2aaSAndroid Build Coastguard Worker 2.f,
167*c8dee2aaSAndroid Build Coastguard Worker 1.f / 0.17883277f,
168*c8dee2aaSAndroid Build Coastguard Worker 0.28466892f,
169*c8dee2aaSAndroid Build Coastguard Worker 0.55991073f)) {
170*c8dee2aaSAndroid Build Coastguard Worker return true;
171*c8dee2aaSAndroid Build Coastguard Worker }
172*c8dee2aaSAndroid Build Coastguard Worker break;
173*c8dee2aaSAndroid Build Coastguard Worker default:
174*c8dee2aaSAndroid Build Coastguard Worker // 19-255 Reserved.
175*c8dee2aaSAndroid Build Coastguard Worker break;
176*c8dee2aaSAndroid Build Coastguard Worker }
177*c8dee2aaSAndroid Build Coastguard Worker
178*c8dee2aaSAndroid Build Coastguard Worker *trfn = SkNamedTransferFn::kSRGB;
179*c8dee2aaSAndroid Build Coastguard Worker return false;
180*c8dee2aaSAndroid Build Coastguard Worker }
181*c8dee2aaSAndroid Build Coastguard Worker
cicp_get_sk_color_space(uint8_t color_primaries,uint8_t transfer_characteristics,uint8_t matrix_coefficients,uint8_t full_range_flag)182*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkColorSpace> cicp_get_sk_color_space(uint8_t color_primaries,
183*c8dee2aaSAndroid Build Coastguard Worker uint8_t transfer_characteristics,
184*c8dee2aaSAndroid Build Coastguard Worker uint8_t matrix_coefficients,
185*c8dee2aaSAndroid Build Coastguard Worker uint8_t full_range_flag) {
186*c8dee2aaSAndroid Build Coastguard Worker if (matrix_coefficients != 0) return nullptr;
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker if (full_range_flag != 1) return nullptr;
189*c8dee2aaSAndroid Build Coastguard Worker
190*c8dee2aaSAndroid Build Coastguard Worker skcms_TransferFunction trfn;
191*c8dee2aaSAndroid Build Coastguard Worker if (!cicp_get_transfer_fn(transfer_characteristics, &trfn)) return nullptr;
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker skcms_Matrix3x3 primaries;
194*c8dee2aaSAndroid Build Coastguard Worker if (!cicp_get_primaries(color_primaries, &primaries)) return nullptr;
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker return SkColorSpace::MakeRGB(trfn, primaries);
197*c8dee2aaSAndroid Build Coastguard Worker }
198*c8dee2aaSAndroid Build Coastguard Worker
SkAndroidCodec(SkCodec * codec)199*c8dee2aaSAndroid Build Coastguard Worker SkAndroidCodec::SkAndroidCodec(SkCodec* codec)
200*c8dee2aaSAndroid Build Coastguard Worker : fInfo(codec->getInfo())
201*c8dee2aaSAndroid Build Coastguard Worker , fCodec(codec)
202*c8dee2aaSAndroid Build Coastguard Worker {}
203*c8dee2aaSAndroid Build Coastguard Worker
~SkAndroidCodec()204*c8dee2aaSAndroid Build Coastguard Worker SkAndroidCodec::~SkAndroidCodec() {}
205*c8dee2aaSAndroid Build Coastguard Worker
MakeFromStream(std::unique_ptr<SkStream> stream,SkPngChunkReader * chunkReader)206*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkAndroidCodec> SkAndroidCodec::MakeFromStream(std::unique_ptr<SkStream> stream,
207*c8dee2aaSAndroid Build Coastguard Worker SkPngChunkReader* chunkReader) {
208*c8dee2aaSAndroid Build Coastguard Worker auto codec = SkCodec::MakeFromStream(std::move(stream), nullptr, chunkReader);
209*c8dee2aaSAndroid Build Coastguard Worker return MakeFromCodec(std::move(codec));
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker
MakeFromCodec(std::unique_ptr<SkCodec> codec)212*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkAndroidCodec> SkAndroidCodec::MakeFromCodec(std::unique_ptr<SkCodec> codec) {
213*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == codec) {
214*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
215*c8dee2aaSAndroid Build Coastguard Worker }
216*c8dee2aaSAndroid Build Coastguard Worker
217*c8dee2aaSAndroid Build Coastguard Worker const SkEncodedImageFormat format = codec->getEncodedFormat();
218*c8dee2aaSAndroid Build Coastguard Worker if (format == SkEncodedImageFormat::kAVIF) {
219*c8dee2aaSAndroid Build Coastguard Worker if (SkCodecs::HasDecoder("avif")) {
220*c8dee2aaSAndroid Build Coastguard Worker // If a dedicated AVIF decoder has been registered, SkAvifCodec can
221*c8dee2aaSAndroid Build Coastguard Worker // handle scaling internally.
222*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<SkAndroidCodecAdapter>(codec.release());
223*c8dee2aaSAndroid Build Coastguard Worker }
224*c8dee2aaSAndroid Build Coastguard Worker // This will fallback to SkHeifCodec, which needs sampling.
225*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<SkSampledCodec>(codec.release());
226*c8dee2aaSAndroid Build Coastguard Worker }
227*c8dee2aaSAndroid Build Coastguard Worker
228*c8dee2aaSAndroid Build Coastguard Worker switch (format) {
229*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kPNG:
230*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kICO:
231*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kJPEG:
232*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kBMP:
233*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kWBMP:
234*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kHEIF:
235*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<SkSampledCodec>(codec.release());
236*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kGIF:
237*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kWEBP:
238*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kDNG:
239*c8dee2aaSAndroid Build Coastguard Worker return std::make_unique<SkAndroidCodecAdapter>(codec.release());
240*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kAVIF: // Handled above
241*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kPKM:
242*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kKTX:
243*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kASTC:
244*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kJPEGXL:
245*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
246*c8dee2aaSAndroid Build Coastguard Worker }
247*c8dee2aaSAndroid Build Coastguard Worker SkUNREACHABLE;
248*c8dee2aaSAndroid Build Coastguard Worker }
249*c8dee2aaSAndroid Build Coastguard Worker
MakeFromData(sk_sp<SkData> data,SkPngChunkReader * chunkReader)250*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkAndroidCodec> SkAndroidCodec::MakeFromData(sk_sp<SkData> data,
251*c8dee2aaSAndroid Build Coastguard Worker SkPngChunkReader* chunkReader) {
252*c8dee2aaSAndroid Build Coastguard Worker if (!data) {
253*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
254*c8dee2aaSAndroid Build Coastguard Worker }
255*c8dee2aaSAndroid Build Coastguard Worker
256*c8dee2aaSAndroid Build Coastguard Worker return MakeFromStream(SkMemoryStream::Make(std::move(data)), chunkReader);
257*c8dee2aaSAndroid Build Coastguard Worker }
258*c8dee2aaSAndroid Build Coastguard Worker
computeOutputColorType(SkColorType requestedColorType)259*c8dee2aaSAndroid Build Coastguard Worker SkColorType SkAndroidCodec::computeOutputColorType(SkColorType requestedColorType) {
260*c8dee2aaSAndroid Build Coastguard Worker bool highPrecision = fCodec->getEncodedInfo().bitsPerComponent() > 8;
261*c8dee2aaSAndroid Build Coastguard Worker uint8_t colorDepth = fCodec->getEncodedInfo().getColorDepth();
262*c8dee2aaSAndroid Build Coastguard Worker switch (requestedColorType) {
263*c8dee2aaSAndroid Build Coastguard Worker case kARGB_4444_SkColorType:
264*c8dee2aaSAndroid Build Coastguard Worker return kN32_SkColorType;
265*c8dee2aaSAndroid Build Coastguard Worker case kN32_SkColorType:
266*c8dee2aaSAndroid Build Coastguard Worker break;
267*c8dee2aaSAndroid Build Coastguard Worker case kAlpha_8_SkColorType:
268*c8dee2aaSAndroid Build Coastguard Worker // Fall through to kGray_8. Before kGray_8_SkColorType existed,
269*c8dee2aaSAndroid Build Coastguard Worker // we allowed clients to request kAlpha_8 when they wanted a
270*c8dee2aaSAndroid Build Coastguard Worker // grayscale decode.
271*c8dee2aaSAndroid Build Coastguard Worker case kGray_8_SkColorType:
272*c8dee2aaSAndroid Build Coastguard Worker if (kGray_8_SkColorType == this->getInfo().colorType()) {
273*c8dee2aaSAndroid Build Coastguard Worker return kGray_8_SkColorType;
274*c8dee2aaSAndroid Build Coastguard Worker }
275*c8dee2aaSAndroid Build Coastguard Worker break;
276*c8dee2aaSAndroid Build Coastguard Worker case kRGB_565_SkColorType:
277*c8dee2aaSAndroid Build Coastguard Worker if (kOpaque_SkAlphaType == this->getInfo().alphaType()) {
278*c8dee2aaSAndroid Build Coastguard Worker return kRGB_565_SkColorType;
279*c8dee2aaSAndroid Build Coastguard Worker }
280*c8dee2aaSAndroid Build Coastguard Worker break;
281*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_1010102_SkColorType:
282*c8dee2aaSAndroid Build Coastguard Worker if (colorDepth == 10) {
283*c8dee2aaSAndroid Build Coastguard Worker return kRGBA_1010102_SkColorType;
284*c8dee2aaSAndroid Build Coastguard Worker }
285*c8dee2aaSAndroid Build Coastguard Worker break;
286*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16_SkColorType:
287*c8dee2aaSAndroid Build Coastguard Worker return kRGBA_F16_SkColorType;
288*c8dee2aaSAndroid Build Coastguard Worker default:
289*c8dee2aaSAndroid Build Coastguard Worker break;
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker // F16 is the Android default for high precision images.
293*c8dee2aaSAndroid Build Coastguard Worker return highPrecision ? kRGBA_F16_SkColorType :
294*c8dee2aaSAndroid Build Coastguard Worker (colorDepth == 10 ? kRGBA_1010102_SkColorType : kN32_SkColorType);
295*c8dee2aaSAndroid Build Coastguard Worker }
296*c8dee2aaSAndroid Build Coastguard Worker
computeOutputAlphaType(bool requestedUnpremul)297*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType SkAndroidCodec::computeOutputAlphaType(bool requestedUnpremul) {
298*c8dee2aaSAndroid Build Coastguard Worker if (kOpaque_SkAlphaType == this->getInfo().alphaType()) {
299*c8dee2aaSAndroid Build Coastguard Worker return kOpaque_SkAlphaType;
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker return requestedUnpremul ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
302*c8dee2aaSAndroid Build Coastguard Worker }
303*c8dee2aaSAndroid Build Coastguard Worker
computeOutputColorSpace(SkColorType outputColorType,sk_sp<SkColorSpace> prefColorSpace)304*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> SkAndroidCodec::computeOutputColorSpace(SkColorType outputColorType,
305*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> prefColorSpace) {
306*c8dee2aaSAndroid Build Coastguard Worker switch (outputColorType) {
307*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_F16_SkColorType:
308*c8dee2aaSAndroid Build Coastguard Worker case kRGB_565_SkColorType:
309*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_8888_SkColorType:
310*c8dee2aaSAndroid Build Coastguard Worker case kBGRA_8888_SkColorType:
311*c8dee2aaSAndroid Build Coastguard Worker case kRGBA_1010102_SkColorType: {
312*c8dee2aaSAndroid Build Coastguard Worker // If |prefColorSpace| is supplied, choose it.
313*c8dee2aaSAndroid Build Coastguard Worker if (prefColorSpace) {
314*c8dee2aaSAndroid Build Coastguard Worker return prefColorSpace;
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker
317*c8dee2aaSAndroid Build Coastguard Worker const skcms_ICCProfile* encodedProfile = fCodec->getEncodedInfo().profile();
318*c8dee2aaSAndroid Build Coastguard Worker if (encodedProfile) {
319*c8dee2aaSAndroid Build Coastguard Worker // Prefer CICP information if it exists.
320*c8dee2aaSAndroid Build Coastguard Worker if (encodedProfile->has_CICP) {
321*c8dee2aaSAndroid Build Coastguard Worker const auto cicpColorSpace =
322*c8dee2aaSAndroid Build Coastguard Worker cicp_get_sk_color_space(encodedProfile->CICP.color_primaries,
323*c8dee2aaSAndroid Build Coastguard Worker encodedProfile->CICP.transfer_characteristics,
324*c8dee2aaSAndroid Build Coastguard Worker encodedProfile->CICP.matrix_coefficients,
325*c8dee2aaSAndroid Build Coastguard Worker encodedProfile->CICP.video_full_range_flag);
326*c8dee2aaSAndroid Build Coastguard Worker if (cicpColorSpace) {
327*c8dee2aaSAndroid Build Coastguard Worker return cicpColorSpace;
328*c8dee2aaSAndroid Build Coastguard Worker }
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker if (auto encodedSpace = SkColorSpace::Make(*encodedProfile)) {
331*c8dee2aaSAndroid Build Coastguard Worker // Leave the pixels in the encoded color space. Color space conversion
332*c8dee2aaSAndroid Build Coastguard Worker // will be handled after decode time.
333*c8dee2aaSAndroid Build Coastguard Worker return encodedSpace;
334*c8dee2aaSAndroid Build Coastguard Worker }
335*c8dee2aaSAndroid Build Coastguard Worker
336*c8dee2aaSAndroid Build Coastguard Worker if (encodedProfile->has_toXYZD50) {
337*c8dee2aaSAndroid Build Coastguard Worker return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
338*c8dee2aaSAndroid Build Coastguard Worker encodedProfile->toXYZD50);
339*c8dee2aaSAndroid Build Coastguard Worker }
340*c8dee2aaSAndroid Build Coastguard Worker }
341*c8dee2aaSAndroid Build Coastguard Worker
342*c8dee2aaSAndroid Build Coastguard Worker return SkColorSpace::MakeSRGB();
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker default:
345*c8dee2aaSAndroid Build Coastguard Worker // Color correction not supported for kGray.
346*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
347*c8dee2aaSAndroid Build Coastguard Worker }
348*c8dee2aaSAndroid Build Coastguard Worker }
349*c8dee2aaSAndroid Build Coastguard Worker
supports_any_down_scale(const SkCodec * codec)350*c8dee2aaSAndroid Build Coastguard Worker static bool supports_any_down_scale(const SkCodec* codec) {
351*c8dee2aaSAndroid Build Coastguard Worker return codec->getEncodedFormat() == SkEncodedImageFormat::kWEBP;
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker
354*c8dee2aaSAndroid Build Coastguard Worker // There are a variety of ways two SkISizes could be compared. This method
355*c8dee2aaSAndroid Build Coastguard Worker // returns true if either dimensions of a is < that of b.
356*c8dee2aaSAndroid Build Coastguard Worker // computeSampleSize also uses the opposite, which means that both
357*c8dee2aaSAndroid Build Coastguard Worker // dimensions of a >= b.
smaller_than(const SkISize & a,const SkISize & b)358*c8dee2aaSAndroid Build Coastguard Worker static inline bool smaller_than(const SkISize& a, const SkISize& b) {
359*c8dee2aaSAndroid Build Coastguard Worker return a.width() < b.width() || a.height() < b.height();
360*c8dee2aaSAndroid Build Coastguard Worker }
361*c8dee2aaSAndroid Build Coastguard Worker
362*c8dee2aaSAndroid Build Coastguard Worker // Both dimensions of a > that of b.
strictly_bigger_than(const SkISize & a,const SkISize & b)363*c8dee2aaSAndroid Build Coastguard Worker static inline bool strictly_bigger_than(const SkISize& a, const SkISize& b) {
364*c8dee2aaSAndroid Build Coastguard Worker return a.width() > b.width() && a.height() > b.height();
365*c8dee2aaSAndroid Build Coastguard Worker }
366*c8dee2aaSAndroid Build Coastguard Worker
computeSampleSize(SkISize * desiredSize) const367*c8dee2aaSAndroid Build Coastguard Worker int SkAndroidCodec::computeSampleSize(SkISize* desiredSize) const {
368*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(desiredSize);
369*c8dee2aaSAndroid Build Coastguard Worker
370*c8dee2aaSAndroid Build Coastguard Worker const auto origDims = fCodec->dimensions();
371*c8dee2aaSAndroid Build Coastguard Worker if (!desiredSize || *desiredSize == origDims) {
372*c8dee2aaSAndroid Build Coastguard Worker return 1;
373*c8dee2aaSAndroid Build Coastguard Worker }
374*c8dee2aaSAndroid Build Coastguard Worker
375*c8dee2aaSAndroid Build Coastguard Worker if (smaller_than(origDims, *desiredSize)) {
376*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = origDims;
377*c8dee2aaSAndroid Build Coastguard Worker return 1;
378*c8dee2aaSAndroid Build Coastguard Worker }
379*c8dee2aaSAndroid Build Coastguard Worker
380*c8dee2aaSAndroid Build Coastguard Worker // Handle bad input:
381*c8dee2aaSAndroid Build Coastguard Worker if (desiredSize->width() < 1 || desiredSize->height() < 1) {
382*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = SkISize::Make(std::max(1, desiredSize->width()),
383*c8dee2aaSAndroid Build Coastguard Worker std::max(1, desiredSize->height()));
384*c8dee2aaSAndroid Build Coastguard Worker }
385*c8dee2aaSAndroid Build Coastguard Worker
386*c8dee2aaSAndroid Build Coastguard Worker if (supports_any_down_scale(fCodec.get())) {
387*c8dee2aaSAndroid Build Coastguard Worker return 1;
388*c8dee2aaSAndroid Build Coastguard Worker }
389*c8dee2aaSAndroid Build Coastguard Worker
390*c8dee2aaSAndroid Build Coastguard Worker int sampleX = origDims.width() / desiredSize->width();
391*c8dee2aaSAndroid Build Coastguard Worker int sampleY = origDims.height() / desiredSize->height();
392*c8dee2aaSAndroid Build Coastguard Worker int sampleSize = std::min(sampleX, sampleY);
393*c8dee2aaSAndroid Build Coastguard Worker auto computedSize = this->getSampledDimensions(sampleSize);
394*c8dee2aaSAndroid Build Coastguard Worker if (computedSize == *desiredSize) {
395*c8dee2aaSAndroid Build Coastguard Worker return sampleSize;
396*c8dee2aaSAndroid Build Coastguard Worker }
397*c8dee2aaSAndroid Build Coastguard Worker
398*c8dee2aaSAndroid Build Coastguard Worker if (computedSize == origDims || sampleSize == 1) {
399*c8dee2aaSAndroid Build Coastguard Worker // Cannot downscale
400*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = computedSize;
401*c8dee2aaSAndroid Build Coastguard Worker return 1;
402*c8dee2aaSAndroid Build Coastguard Worker }
403*c8dee2aaSAndroid Build Coastguard Worker
404*c8dee2aaSAndroid Build Coastguard Worker if (strictly_bigger_than(computedSize, *desiredSize)) {
405*c8dee2aaSAndroid Build Coastguard Worker // See if there is a tighter fit.
406*c8dee2aaSAndroid Build Coastguard Worker while (true) {
407*c8dee2aaSAndroid Build Coastguard Worker auto smaller = this->getSampledDimensions(sampleSize + 1);
408*c8dee2aaSAndroid Build Coastguard Worker if (smaller == *desiredSize) {
409*c8dee2aaSAndroid Build Coastguard Worker return sampleSize + 1;
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker if (smaller == computedSize || smaller_than(smaller, *desiredSize)) {
412*c8dee2aaSAndroid Build Coastguard Worker // Cannot get any smaller without being smaller than desired.
413*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = computedSize;
414*c8dee2aaSAndroid Build Coastguard Worker return sampleSize;
415*c8dee2aaSAndroid Build Coastguard Worker }
416*c8dee2aaSAndroid Build Coastguard Worker
417*c8dee2aaSAndroid Build Coastguard Worker sampleSize++;
418*c8dee2aaSAndroid Build Coastguard Worker computedSize = smaller;
419*c8dee2aaSAndroid Build Coastguard Worker }
420*c8dee2aaSAndroid Build Coastguard Worker
421*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
422*c8dee2aaSAndroid Build Coastguard Worker }
423*c8dee2aaSAndroid Build Coastguard Worker
424*c8dee2aaSAndroid Build Coastguard Worker if (!smaller_than(computedSize, *desiredSize)) {
425*c8dee2aaSAndroid Build Coastguard Worker // This means one of the computed dimensions is equal to desired, and
426*c8dee2aaSAndroid Build Coastguard Worker // the other is bigger. This is as close as we can get.
427*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = computedSize;
428*c8dee2aaSAndroid Build Coastguard Worker return sampleSize;
429*c8dee2aaSAndroid Build Coastguard Worker }
430*c8dee2aaSAndroid Build Coastguard Worker
431*c8dee2aaSAndroid Build Coastguard Worker // computedSize is too small. Make it larger.
432*c8dee2aaSAndroid Build Coastguard Worker while (sampleSize > 2) {
433*c8dee2aaSAndroid Build Coastguard Worker auto bigger = this->getSampledDimensions(sampleSize - 1);
434*c8dee2aaSAndroid Build Coastguard Worker if (bigger == *desiredSize || !smaller_than(bigger, *desiredSize)) {
435*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = bigger;
436*c8dee2aaSAndroid Build Coastguard Worker return sampleSize - 1;
437*c8dee2aaSAndroid Build Coastguard Worker }
438*c8dee2aaSAndroid Build Coastguard Worker sampleSize--;
439*c8dee2aaSAndroid Build Coastguard Worker }
440*c8dee2aaSAndroid Build Coastguard Worker
441*c8dee2aaSAndroid Build Coastguard Worker *desiredSize = origDims;
442*c8dee2aaSAndroid Build Coastguard Worker return 1;
443*c8dee2aaSAndroid Build Coastguard Worker }
444*c8dee2aaSAndroid Build Coastguard Worker
getSampledDimensions(int sampleSize) const445*c8dee2aaSAndroid Build Coastguard Worker SkISize SkAndroidCodec::getSampledDimensions(int sampleSize) const {
446*c8dee2aaSAndroid Build Coastguard Worker if (!is_valid_sample_size(sampleSize)) {
447*c8dee2aaSAndroid Build Coastguard Worker return {0, 0};
448*c8dee2aaSAndroid Build Coastguard Worker }
449*c8dee2aaSAndroid Build Coastguard Worker
450*c8dee2aaSAndroid Build Coastguard Worker // Fast path for when we are not scaling.
451*c8dee2aaSAndroid Build Coastguard Worker if (1 == sampleSize) {
452*c8dee2aaSAndroid Build Coastguard Worker return fCodec->dimensions();
453*c8dee2aaSAndroid Build Coastguard Worker }
454*c8dee2aaSAndroid Build Coastguard Worker
455*c8dee2aaSAndroid Build Coastguard Worker return this->onGetSampledDimensions(sampleSize);
456*c8dee2aaSAndroid Build Coastguard Worker }
457*c8dee2aaSAndroid Build Coastguard Worker
getSupportedSubset(SkIRect * desiredSubset) const458*c8dee2aaSAndroid Build Coastguard Worker bool SkAndroidCodec::getSupportedSubset(SkIRect* desiredSubset) const {
459*c8dee2aaSAndroid Build Coastguard Worker if (!desiredSubset || !is_valid_subset(*desiredSubset, fCodec->dimensions())) {
460*c8dee2aaSAndroid Build Coastguard Worker return false;
461*c8dee2aaSAndroid Build Coastguard Worker }
462*c8dee2aaSAndroid Build Coastguard Worker
463*c8dee2aaSAndroid Build Coastguard Worker return this->onGetSupportedSubset(desiredSubset);
464*c8dee2aaSAndroid Build Coastguard Worker }
465*c8dee2aaSAndroid Build Coastguard Worker
getSampledSubsetDimensions(int sampleSize,const SkIRect & subset) const466*c8dee2aaSAndroid Build Coastguard Worker SkISize SkAndroidCodec::getSampledSubsetDimensions(int sampleSize, const SkIRect& subset) const {
467*c8dee2aaSAndroid Build Coastguard Worker if (!is_valid_sample_size(sampleSize)) {
468*c8dee2aaSAndroid Build Coastguard Worker return {0, 0};
469*c8dee2aaSAndroid Build Coastguard Worker }
470*c8dee2aaSAndroid Build Coastguard Worker
471*c8dee2aaSAndroid Build Coastguard Worker // We require that the input subset is a subset that is supported by SkAndroidCodec.
472*c8dee2aaSAndroid Build Coastguard Worker // We test this by calling getSupportedSubset() and verifying that no modifications
473*c8dee2aaSAndroid Build Coastguard Worker // are made to the subset.
474*c8dee2aaSAndroid Build Coastguard Worker SkIRect copySubset = subset;
475*c8dee2aaSAndroid Build Coastguard Worker if (!this->getSupportedSubset(©Subset) || copySubset != subset) {
476*c8dee2aaSAndroid Build Coastguard Worker return {0, 0};
477*c8dee2aaSAndroid Build Coastguard Worker }
478*c8dee2aaSAndroid Build Coastguard Worker
479*c8dee2aaSAndroid Build Coastguard Worker // If the subset is the entire image, for consistency, use getSampledDimensions().
480*c8dee2aaSAndroid Build Coastguard Worker if (fCodec->dimensions() == subset.size()) {
481*c8dee2aaSAndroid Build Coastguard Worker return this->getSampledDimensions(sampleSize);
482*c8dee2aaSAndroid Build Coastguard Worker }
483*c8dee2aaSAndroid Build Coastguard Worker
484*c8dee2aaSAndroid Build Coastguard Worker // This should perhaps call a virtual function, but currently both of our subclasses
485*c8dee2aaSAndroid Build Coastguard Worker // want the same implementation.
486*c8dee2aaSAndroid Build Coastguard Worker return {get_scaled_dimension(subset.width(), sampleSize),
487*c8dee2aaSAndroid Build Coastguard Worker get_scaled_dimension(subset.height(), sampleSize)};
488*c8dee2aaSAndroid Build Coastguard Worker }
489*c8dee2aaSAndroid Build Coastguard Worker
getAndroidPixels(const SkImageInfo & requestInfo,void * requestPixels,size_t requestRowBytes,const AndroidOptions * options)490*c8dee2aaSAndroid Build Coastguard Worker SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& requestInfo,
491*c8dee2aaSAndroid Build Coastguard Worker void* requestPixels, size_t requestRowBytes, const AndroidOptions* options) {
492*c8dee2aaSAndroid Build Coastguard Worker if (!requestPixels) {
493*c8dee2aaSAndroid Build Coastguard Worker return SkCodec::kInvalidParameters;
494*c8dee2aaSAndroid Build Coastguard Worker }
495*c8dee2aaSAndroid Build Coastguard Worker if (requestRowBytes < requestInfo.minRowBytes()) {
496*c8dee2aaSAndroid Build Coastguard Worker return SkCodec::kInvalidParameters;
497*c8dee2aaSAndroid Build Coastguard Worker }
498*c8dee2aaSAndroid Build Coastguard Worker
499*c8dee2aaSAndroid Build Coastguard Worker AndroidOptions defaultOptions;
500*c8dee2aaSAndroid Build Coastguard Worker if (!options) {
501*c8dee2aaSAndroid Build Coastguard Worker options = &defaultOptions;
502*c8dee2aaSAndroid Build Coastguard Worker } else {
503*c8dee2aaSAndroid Build Coastguard Worker if (options->fSubset) {
504*c8dee2aaSAndroid Build Coastguard Worker if (!is_valid_subset(*options->fSubset, fCodec->dimensions())) {
505*c8dee2aaSAndroid Build Coastguard Worker return SkCodec::kInvalidParameters;
506*c8dee2aaSAndroid Build Coastguard Worker }
507*c8dee2aaSAndroid Build Coastguard Worker
508*c8dee2aaSAndroid Build Coastguard Worker if (SkIRect::MakeSize(fCodec->dimensions()) == *options->fSubset) {
509*c8dee2aaSAndroid Build Coastguard Worker // The caller wants the whole thing, rather than a subset. Modify
510*c8dee2aaSAndroid Build Coastguard Worker // the AndroidOptions passed to onGetAndroidPixels to not specify
511*c8dee2aaSAndroid Build Coastguard Worker // a subset.
512*c8dee2aaSAndroid Build Coastguard Worker defaultOptions = *options;
513*c8dee2aaSAndroid Build Coastguard Worker defaultOptions.fSubset = nullptr;
514*c8dee2aaSAndroid Build Coastguard Worker options = &defaultOptions;
515*c8dee2aaSAndroid Build Coastguard Worker }
516*c8dee2aaSAndroid Build Coastguard Worker }
517*c8dee2aaSAndroid Build Coastguard Worker }
518*c8dee2aaSAndroid Build Coastguard Worker
519*c8dee2aaSAndroid Build Coastguard Worker // We may need to have handleFrameIndex recursively call this method
520*c8dee2aaSAndroid Build Coastguard Worker // to resolve one frame depending on another. The recursion stops
521*c8dee2aaSAndroid Build Coastguard Worker // when we find a frame which does not require an earlier frame
522*c8dee2aaSAndroid Build Coastguard Worker // e.g. frame->getRequiredFrame() returns kNoFrame
523*c8dee2aaSAndroid Build Coastguard Worker auto getPixelsFn = [&](const SkImageInfo& info, void* pixels, size_t rowBytes,
524*c8dee2aaSAndroid Build Coastguard Worker const SkCodec::Options& opts, int requiredFrame
525*c8dee2aaSAndroid Build Coastguard Worker ) -> SkCodec::Result {
526*c8dee2aaSAndroid Build Coastguard Worker SkAndroidCodec::AndroidOptions prevFrameOptions(
527*c8dee2aaSAndroid Build Coastguard Worker reinterpret_cast<const SkAndroidCodec::AndroidOptions&>(opts));
528*c8dee2aaSAndroid Build Coastguard Worker prevFrameOptions.fFrameIndex = requiredFrame;
529*c8dee2aaSAndroid Build Coastguard Worker return this->getAndroidPixels(info, pixels, rowBytes, &prevFrameOptions);
530*c8dee2aaSAndroid Build Coastguard Worker };
531*c8dee2aaSAndroid Build Coastguard Worker if (auto result = fCodec->handleFrameIndex(requestInfo, requestPixels, requestRowBytes,
532*c8dee2aaSAndroid Build Coastguard Worker *options, getPixelsFn); result != SkCodec::kSuccess) {
533*c8dee2aaSAndroid Build Coastguard Worker return result;
534*c8dee2aaSAndroid Build Coastguard Worker }
535*c8dee2aaSAndroid Build Coastguard Worker
536*c8dee2aaSAndroid Build Coastguard Worker return this->onGetAndroidPixels(requestInfo, requestPixels, requestRowBytes, *options);
537*c8dee2aaSAndroid Build Coastguard Worker }
538*c8dee2aaSAndroid Build Coastguard Worker
getAndroidPixels(const SkImageInfo & info,void * pixels,size_t rowBytes)539*c8dee2aaSAndroid Build Coastguard Worker SkCodec::Result SkAndroidCodec::getAndroidPixels(const SkImageInfo& info, void* pixels,
540*c8dee2aaSAndroid Build Coastguard Worker size_t rowBytes) {
541*c8dee2aaSAndroid Build Coastguard Worker return this->getAndroidPixels(info, pixels, rowBytes, nullptr);
542*c8dee2aaSAndroid Build Coastguard Worker }
543*c8dee2aaSAndroid Build Coastguard Worker
getGainmapAndroidCodec(SkGainmapInfo * info,std::unique_ptr<SkAndroidCodec> * outCodec)544*c8dee2aaSAndroid Build Coastguard Worker bool SkAndroidCodec::getGainmapAndroidCodec(SkGainmapInfo* info,
545*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkAndroidCodec>* outCodec) {
546*c8dee2aaSAndroid Build Coastguard Worker if (outCodec) {
547*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> gainmapCodec;
548*c8dee2aaSAndroid Build Coastguard Worker if (!fCodec->onGetGainmapCodec(info, &gainmapCodec)) {
549*c8dee2aaSAndroid Build Coastguard Worker return false;
550*c8dee2aaSAndroid Build Coastguard Worker }
551*c8dee2aaSAndroid Build Coastguard Worker *outCodec = MakeFromCodec(std::move(gainmapCodec));
552*c8dee2aaSAndroid Build Coastguard Worker return true;
553*c8dee2aaSAndroid Build Coastguard Worker }
554*c8dee2aaSAndroid Build Coastguard Worker return fCodec->onGetGainmapCodec(info, nullptr);
555*c8dee2aaSAndroid Build Coastguard Worker }
556*c8dee2aaSAndroid Build Coastguard Worker
getAndroidGainmap(SkGainmapInfo * info,std::unique_ptr<SkStream> * outGainmapImageStream)557*c8dee2aaSAndroid Build Coastguard Worker bool SkAndroidCodec::getAndroidGainmap(SkGainmapInfo* info,
558*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStream>* outGainmapImageStream) {
559*c8dee2aaSAndroid Build Coastguard Worker return fCodec->onGetGainmapInfo(info, outGainmapImageStream);
560*c8dee2aaSAndroid Build Coastguard Worker }
561