xref: /aosp_15_r20/frameworks/base/native/graphics/jni/imagedecoder.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 /*
2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <MimeType.h>
18 #include <SkAlphaType.h>
19 #include <SkAndroidCodec.h>
20 #include <SkCodec.h>
21 #include <SkCodecAnimation.h>
22 #include <SkColorSpace.h>
23 #include <SkColorType.h>
24 #include <SkImageInfo.h>
25 #include <SkRect.h>
26 #include <SkRefCnt.h>
27 #include <SkSize.h>
28 #include <SkStream.h>
29 #include <android/asset_manager.h>
30 #include <android/bitmap.h>
31 #include <android/data_space.h>
32 #include <android/imagedecoder.h>
33 #include <android/rect.h>
34 #include <fcntl.h>
35 #include <hwui/ImageDecoder.h>
36 #include <log/log.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <utils/Color.h>
41 #include <utils/StatsUtils.h>
42 
43 #include <limits>
44 #include <optional>
45 
46 #include "aassetstreamadaptor.h"
47 
48 using namespace android;
49 
ResultToErrorCode(SkCodec::Result result)50 int ResultToErrorCode(SkCodec::Result result) {
51     switch (result) {
52         case SkCodec::kIncompleteInput:
53             return ANDROID_IMAGE_DECODER_INCOMPLETE;
54         case SkCodec::kErrorInInput:
55             return ANDROID_IMAGE_DECODER_ERROR;
56         case SkCodec::kInvalidInput:
57             return ANDROID_IMAGE_DECODER_INVALID_INPUT;
58         case SkCodec::kCouldNotRewind:
59             return ANDROID_IMAGE_DECODER_SEEK_ERROR;
60         case SkCodec::kUnimplemented:
61             return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
62         case SkCodec::kInvalidConversion:
63             return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
64         case SkCodec::kInvalidParameters:
65             return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
66         case SkCodec::kSuccess:
67             return ANDROID_IMAGE_DECODER_SUCCESS;
68         case SkCodec::kInvalidScale:
69             return ANDROID_IMAGE_DECODER_INVALID_SCALE;
70         case SkCodec::kInternalError:
71             return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
72     }
73 }
74 
AImageDecoder_resultToString(int result)75 const char* AImageDecoder_resultToString(int result) {
76     switch (result) {
77         case        ANDROID_IMAGE_DECODER_SUCCESS:
78             return "ANDROID_IMAGE_DECODER_SUCCESS";
79         case        ANDROID_IMAGE_DECODER_INCOMPLETE:
80             return "ANDROID_IMAGE_DECODER_INCOMPLETE";
81         case        ANDROID_IMAGE_DECODER_ERROR:
82             return "ANDROID_IMAGE_DECODER_ERROR";
83         case        ANDROID_IMAGE_DECODER_INVALID_CONVERSION:
84             return "ANDROID_IMAGE_DECODER_INVALID_CONVERSION";
85         case        ANDROID_IMAGE_DECODER_INVALID_SCALE:
86             return "ANDROID_IMAGE_DECODER_INVALID_SCALE";
87         case        ANDROID_IMAGE_DECODER_BAD_PARAMETER:
88             return "ANDROID_IMAGE_DECODER_BAD_PARAMETER";
89         case        ANDROID_IMAGE_DECODER_INVALID_INPUT:
90             return "ANDROID_IMAGE_DECODER_INVALID_INPUT";
91         case        ANDROID_IMAGE_DECODER_SEEK_ERROR:
92             return "ANDROID_IMAGE_DECODER_SEEK_ERROR";
93         case        ANDROID_IMAGE_DECODER_INTERNAL_ERROR:
94             return "ANDROID_IMAGE_DECODER_INTERNAL_ERROR";
95         case        ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT:
96             return "ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT";
97         case        ANDROID_IMAGE_DECODER_FINISHED:
98             return "ANDROID_IMAGE_DECODER_FINISHED";
99         case        ANDROID_IMAGE_DECODER_INVALID_STATE:
100             return "ANDROID_IMAGE_DECODER_INVALID_STATE";
101         default:
102             return nullptr;
103     }
104 }
105 
createFromStream(std::unique_ptr<SkStreamRewindable> stream,AImageDecoder ** outDecoder)106 static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
107     SkCodec::Result result;
108     auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
109                                          SkCodec::SelectionPolicy::kPreferAnimation);
110     // These may be swapped due to the SkEncodedOrigin, but we're just checking
111     // them to make sure they fit in int32_t.
112     auto dimensions = codec->dimensions();
113     auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
114     if (!androidCodec) {
115         return ResultToErrorCode(result);
116     }
117 
118     // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
119     // the conversion is safe.
120     if (dimensions.width() > std::numeric_limits<int32_t>::max() ||
121         dimensions.height() > std::numeric_limits<int32_t>::max()) {
122         return ANDROID_IMAGE_DECODER_INVALID_INPUT;
123     }
124 
125     *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
126     return ANDROID_IMAGE_DECODER_SUCCESS;
127 }
128 
AImageDecoder_createFromAAsset(AAsset * asset,AImageDecoder ** outDecoder)129 int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
130     if (!asset || !outDecoder) {
131         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
132     }
133     *outDecoder = nullptr;
134 
135 #ifdef __ANDROID__
136     auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
137     return createFromStream(std::move(stream), outDecoder);
138 #else
139     return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
140 #endif
141 }
142 
isSeekable(int descriptor)143 static bool isSeekable(int descriptor) {
144     return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
145 }
146 
AImageDecoder_createFromFd(int fd,AImageDecoder ** outDecoder)147 int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
148     if (fd <= 0 || !outDecoder) {
149         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
150     }
151 
152     struct stat fdStat;
153     if (fstat(fd, &fdStat) == -1) {
154         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
155     }
156 
157     if (!isSeekable(fd)) {
158         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
159     }
160 
161     // SkFILEStream will close its descriptor. Duplicate it so the client will
162     // still be responsible for closing the original.
163     int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
164     FILE* file = fdopen(dupDescriptor, "r");
165     if (!file) {
166         close(dupDescriptor);
167         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
168     }
169 
170     auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
171     return createFromStream(std::move(stream), outDecoder);
172 }
173 
AImageDecoder_createFromBuffer(const void * buffer,size_t length,AImageDecoder ** outDecoder)174 int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
175                                    AImageDecoder** outDecoder) {
176     if (!buffer || !length  || !outDecoder) {
177         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
178     }
179     *outDecoder = nullptr;
180 
181     // The client is expected to keep the buffer alive as long as the
182     // AImageDecoder, so we do not need to copy the buffer.
183     auto stream = std::unique_ptr<SkStreamRewindable>(
184             new SkMemoryStream(buffer, length, false /* copyData */));
185     return createFromStream(std::move(stream), outDecoder);
186 }
187 
toDecoder(AImageDecoder * d)188 static ImageDecoder* toDecoder(AImageDecoder* d) {
189     return reinterpret_cast<ImageDecoder*>(d);
190 }
191 
toDecoder(const AImageDecoder * d)192 static const ImageDecoder* toDecoder(const AImageDecoder* d) {
193     return reinterpret_cast<const ImageDecoder*>(d);
194 }
195 
196 // Note: This differs from the version in android_bitmap.cpp in that this
197 // version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
198 // allows decoding single channel images to gray, which Android then treats
199 // as A_8/ALPHA_8.
getColorType(AndroidBitmapFormat format)200 static SkColorType getColorType(AndroidBitmapFormat format) {
201     switch (format) {
202         case ANDROID_BITMAP_FORMAT_RGBA_8888:
203             return kN32_SkColorType;
204         case ANDROID_BITMAP_FORMAT_RGB_565:
205             return kRGB_565_SkColorType;
206         case ANDROID_BITMAP_FORMAT_RGBA_4444:
207             return kARGB_4444_SkColorType;
208         case ANDROID_BITMAP_FORMAT_A_8:
209             return kGray_8_SkColorType;
210         case ANDROID_BITMAP_FORMAT_RGBA_F16:
211             return kRGBA_F16_SkColorType;
212         case ANDROID_BITMAP_FORMAT_RGBA_1010102:
213             return kRGBA_1010102_SkColorType;
214         default:
215             return kUnknown_SkColorType;
216     }
217 }
218 
AImageDecoder_setAndroidBitmapFormat(AImageDecoder * decoder,int32_t format)219 int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
220     if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE ||
221         format > ANDROID_BITMAP_FORMAT_RGBA_1010102) {
222         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
223     }
224 
225     auto* imageDecoder = toDecoder(decoder);
226     if (imageDecoder->currentFrame() != 0) {
227         return ANDROID_IMAGE_DECODER_INVALID_STATE;
228     }
229 
230     return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
231             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
232 }
233 
AImageDecoder_setDataSpace(AImageDecoder * decoder,int32_t dataspace)234 int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
235     sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
236     // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
237     if (!decoder || !dataspace || !cs) {
238         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
239     }
240 
241     ImageDecoder* imageDecoder = toDecoder(decoder);
242     if (imageDecoder->currentFrame() != 0) {
243         return ANDROID_IMAGE_DECODER_INVALID_STATE;
244     }
245 
246     imageDecoder->setOutColorSpace(std::move(cs));
247     return ANDROID_IMAGE_DECODER_SUCCESS;
248 }
249 
AImageDecoder_getHeaderInfo(const AImageDecoder * decoder)250 const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
251     return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
252 }
253 
toDecoder(const AImageDecoderHeaderInfo * info)254 static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
255     return reinterpret_cast<const ImageDecoder*>(info);
256 }
257 
AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo * info)258 int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
259     if (!info) {
260         return 0;
261     }
262     return toDecoder(info)->width();
263 }
264 
AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo * info)265 int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
266     if (!info) {
267         return 0;
268     }
269     return toDecoder(info)->height();
270 }
271 
AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo * info)272 const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
273     if (!info) {
274         return nullptr;
275     }
276     return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
277 }
278 
AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo * info)279 int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
280     if (!info) {
281         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
282     }
283 
284     // Note: This recomputes the color type because it's possible the client has
285     // changed the output color type, so we cannot rely on it. Alternatively,
286     // we could store the ADataSpace in the ImageDecoder.
287     const ImageDecoder* imageDecoder = toDecoder(info);
288     SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
289     sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
290     return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
291 }
292 
293 // FIXME: Share with getFormat in android_bitmap.cpp?
getFormat(SkColorType colorType)294 static AndroidBitmapFormat getFormat(SkColorType colorType) {
295     switch (colorType) {
296         case kN32_SkColorType:
297             return ANDROID_BITMAP_FORMAT_RGBA_8888;
298         case kRGB_565_SkColorType:
299             return ANDROID_BITMAP_FORMAT_RGB_565;
300         case kARGB_4444_SkColorType:
301             return ANDROID_BITMAP_FORMAT_RGBA_4444;
302         case kAlpha_8_SkColorType:
303             return ANDROID_BITMAP_FORMAT_A_8;
304         case kRGBA_F16_SkColorType:
305             return ANDROID_BITMAP_FORMAT_RGBA_F16;
306         case kRGBA_1010102_SkColorType:
307             return ANDROID_BITMAP_FORMAT_RGBA_1010102;
308         default:
309             return ANDROID_BITMAP_FORMAT_NONE;
310     }
311 }
312 
AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo * info)313 int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
314     if (!info) {
315         return ANDROID_BITMAP_FORMAT_NONE;
316     }
317     return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
318 }
319 
AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo * info)320 int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
321     if (!info) {
322         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
323     }
324     switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
325         case kUnknown_SkAlphaType:
326             LOG_ALWAYS_FATAL("Invalid alpha type");
327             return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
328         case kUnpremul_SkAlphaType:
329             // fall through. premul is the default.
330         case kPremul_SkAlphaType:
331             return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
332         case kOpaque_SkAlphaType:
333             return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
334     }
335 }
336 
AImageDecoder_setUnpremultipliedRequired(AImageDecoder * decoder,bool required)337 int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
338     if (!decoder) {
339         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
340     }
341 
342     auto* imageDecoder = toDecoder(decoder);
343     if (imageDecoder->currentFrame() != 0) {
344         return ANDROID_IMAGE_DECODER_INVALID_STATE;
345     }
346 
347     return imageDecoder->setUnpremultipliedRequired(required)
348             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
349 }
350 
AImageDecoder_setTargetSize(AImageDecoder * decoder,int32_t width,int32_t height)351 int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
352     if (!decoder) {
353         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
354     }
355 
356     auto* imageDecoder = toDecoder(decoder);
357     if (imageDecoder->currentFrame() != 0) {
358         return ANDROID_IMAGE_DECODER_INVALID_STATE;
359     }
360 
361     return imageDecoder->setTargetSize(width, height)
362             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
363 }
364 
AImageDecoder_computeSampledSize(const AImageDecoder * decoder,int sampleSize,int32_t * width,int32_t * height)365 int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
366                                      int32_t* width, int32_t* height) {
367     if (!decoder || !width || !height || sampleSize < 1) {
368         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
369     }
370 
371     SkISize size = toDecoder(decoder)->getSampledDimensions(sampleSize);
372     *width = size.width();
373     *height = size.height();
374     return ANDROID_IMAGE_DECODER_SUCCESS;
375 }
376 
AImageDecoder_setCrop(AImageDecoder * decoder,ARect crop)377 int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
378     if (!decoder) {
379         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
380     }
381 
382     auto* imageDecoder = toDecoder(decoder);
383     if (imageDecoder->currentFrame() != 0) {
384         return ANDROID_IMAGE_DECODER_INVALID_STATE;
385     }
386 
387     SkIRect cropIRect;
388     cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
389     SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
390     return imageDecoder->setCropRect(cropPtr)
391             ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
392 }
393 
394 
AImageDecoder_getMinimumStride(AImageDecoder * decoder)395 size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
396     if (!decoder) {
397         return 0;
398     }
399 
400     SkImageInfo info = toDecoder(decoder)->getOutputInfo();
401     return info.minRowBytes();
402 }
403 
AImageDecoder_decodeImage(AImageDecoder * decoder,void * pixels,size_t stride,size_t size)404 int AImageDecoder_decodeImage(AImageDecoder* decoder, void* pixels, size_t stride, size_t size) {
405     if (!decoder || !pixels || !stride) {
406         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
407     }
408 
409     ImageDecoder* imageDecoder = toDecoder(decoder);
410 
411     SkImageInfo info = imageDecoder->getOutputInfo();
412     size_t minSize = info.computeByteSize(stride);
413     if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
414         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
415     }
416 
417     if (imageDecoder->finished()) {
418         return ANDROID_IMAGE_DECODER_FINISHED;
419     }
420 
421     const auto result = ResultToErrorCode(imageDecoder->decode(pixels, stride));
422 
423     if (result == ANDROID_IMAGE_DECODER_SUCCESS) {
424         uirenderer::logBitmapDecode(imageDecoder->getOutputInfo(), false);
425     }
426 
427     return result;
428 }
429 
AImageDecoder_delete(AImageDecoder * decoder)430 void AImageDecoder_delete(AImageDecoder* decoder) {
431     delete toDecoder(decoder);
432 }
433 
AImageDecoder_isAnimated(AImageDecoder * decoder)434 bool AImageDecoder_isAnimated(AImageDecoder* decoder) {
435     if (!decoder) return false;
436 
437     ImageDecoder* imageDecoder = toDecoder(decoder);
438     return imageDecoder->isAnimated();
439 }
440 
AImageDecoder_getRepeatCount(AImageDecoder * decoder)441 int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
442     if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
443 
444     ImageDecoder* imageDecoder = toDecoder(decoder);
445     const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
446 
447     // Skia should not report anything out of range, but defensively treat
448     // negative and too big as INFINITE.
449     if (count == SkCodec::kRepetitionCountInfinite || count < 0
450         || count > std::numeric_limits<int32_t>::max()) {
451         return ANDROID_IMAGE_DECODER_INFINITE;
452     }
453     return count;
454 }
455 
AImageDecoder_advanceFrame(AImageDecoder * decoder)456 int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
457     if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
458 
459     ImageDecoder* imageDecoder = toDecoder(decoder);
460     if (!imageDecoder->isAnimated()) {
461         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
462     }
463 
464     const auto colorType = imageDecoder->getOutputInfo().colorType();
465     switch (colorType) {
466         case kN32_SkColorType:
467         case kRGBA_F16_SkColorType:
468             break;
469         default:
470             return ANDROID_IMAGE_DECODER_INVALID_STATE;
471     }
472 
473     if (imageDecoder->advanceFrame()) {
474         return ANDROID_IMAGE_DECODER_SUCCESS;
475     }
476 
477     if (imageDecoder->finished()) {
478         return ANDROID_IMAGE_DECODER_FINISHED;
479     }
480 
481     return ANDROID_IMAGE_DECODER_INCOMPLETE;
482 }
483 
AImageDecoder_rewind(AImageDecoder * decoder)484 int AImageDecoder_rewind(AImageDecoder* decoder) {
485     if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
486 
487     ImageDecoder* imageDecoder = toDecoder(decoder);
488     if (!imageDecoder->isAnimated()) {
489         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
490     }
491 
492     return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
493                                   : ANDROID_IMAGE_DECODER_SEEK_ERROR;
494 }
495 
AImageDecoderFrameInfo_create()496 AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
497     return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
498 }
499 
toFrameInfo(AImageDecoderFrameInfo * info)500 static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
501     return reinterpret_cast<SkCodec::FrameInfo*>(info);
502 }
503 
toFrameInfo(const AImageDecoderFrameInfo * info)504 static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
505     return reinterpret_cast<const SkCodec::FrameInfo*>(info);
506 }
507 
AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo * info)508 void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
509     delete toFrameInfo(info);
510 }
511 
AImageDecoder_getFrameInfo(AImageDecoder * decoder,AImageDecoderFrameInfo * info)512 int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
513         AImageDecoderFrameInfo* info) {
514     if (!decoder || !info) {
515         return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
516     }
517 
518     auto* imageDecoder = toDecoder(decoder);
519     if (imageDecoder->finished()) {
520         return ANDROID_IMAGE_DECODER_FINISHED;
521     }
522 
523     *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
524     return ANDROID_IMAGE_DECODER_SUCCESS;
525 }
526 
AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo * info)527 int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
528     if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
529 
530     return toFrameInfo(info)->fDuration * 1'000'000;
531 }
532 
AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo * info)533 ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
534     if (!info) {
535         return { 0, 0, 0, 0};
536     }
537 
538     const SkIRect& r = toFrameInfo(info)->fFrameRect;
539     return { r.left(), r.top(), r.right(), r.bottom() };
540 }
541 
AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo * info)542 bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
543     if (!info) return false;
544 
545     return toFrameInfo(info)->fHasAlphaWithinBounds;
546 }
547 
AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo * info)548 int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
549     if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
550 
551     static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
552                   == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
553     static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
554                   == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
555     static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
556                   == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
557     return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
558 }
559 
AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo * info)560 int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
561     if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
562 
563     switch (toFrameInfo(info)->fBlend) {
564         case SkCodecAnimation::Blend::kSrc:
565             return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
566         case SkCodecAnimation::Blend::kSrcOver:
567             return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
568     }
569 }
570 
AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder * decoder,bool handle)571 void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
572     if (decoder) {
573         toDecoder(decoder)->setHandleRestorePrevious(handle);
574     }
575 }
576