blob: cd6ed23916083e3aaa20ed0c8ad1661bd0568072 [file] [log] [blame]
Leon Scroggins III407b5442019-11-22 17:10:20 -05001/*
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 "aassetstreamadaptor.h"
18
19#include <android/asset_manager.h>
20#include <android/bitmap.h>
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -050021#include <android/data_space.h>
Leon Scroggins III407b5442019-11-22 17:10:20 -050022#include <android/imagedecoder.h>
Derek Sollenberger2173ea22020-02-19 15:37:29 -050023#include <MimeType.h>
Leon Scroggins III407b5442019-11-22 17:10:20 -050024#include <android/rect.h>
25#include <hwui/ImageDecoder.h>
26#include <log/log.h>
27#include <SkAndroidCodec.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050028#include <SkCodec.h>
29#include <SkColorSpace.h>
30#include <SkImageInfo.h>
31#include <SkRect.h>
32#include <SkSize.h>
33#include <SkStream.h>
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -050034#include <utils/Color.h>
Leon Scroggins III407b5442019-11-22 17:10:20 -050035
36#include <fcntl.h>
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -050037#include <limits>
Leon Scroggins III407b5442019-11-22 17:10:20 -050038#include <optional>
39#include <sys/stat.h>
40#include <sys/types.h>
41#include <unistd.h>
42
43using namespace android;
44
45int ResultToErrorCode(SkCodec::Result result) {
46 switch (result) {
47 case SkCodec::kIncompleteInput:
48 return ANDROID_IMAGE_DECODER_INCOMPLETE;
49 case SkCodec::kErrorInInput:
50 return ANDROID_IMAGE_DECODER_ERROR;
51 case SkCodec::kInvalidInput:
52 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
53 case SkCodec::kCouldNotRewind:
54 return ANDROID_IMAGE_DECODER_SEEK_ERROR;
55 case SkCodec::kUnimplemented:
56 return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
57 case SkCodec::kInvalidConversion:
58 return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
59 case SkCodec::kInvalidParameters:
60 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
61 case SkCodec::kSuccess:
62 return ANDROID_IMAGE_DECODER_SUCCESS;
63 case SkCodec::kInvalidScale:
64 return ANDROID_IMAGE_DECODER_INVALID_SCALE;
65 case SkCodec::kInternalError:
66 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
67 }
68}
69
Leon Scroggins III946f8d42020-12-02 14:05:44 -050070const char* AImageDecoder_resultToString(int result) {
71 switch (result) {
72 case ANDROID_IMAGE_DECODER_SUCCESS:
73 return "ANDROID_IMAGE_DECODER_SUCCESS";
74 case ANDROID_IMAGE_DECODER_INCOMPLETE:
75 return "ANDROID_IMAGE_DECODER_INCOMPLETE";
76 case ANDROID_IMAGE_DECODER_ERROR:
77 return "ANDROID_IMAGE_DECODER_ERROR";
78 case ANDROID_IMAGE_DECODER_INVALID_CONVERSION:
79 return "ANDROID_IMAGE_DECODER_INVALID_CONVERSION";
80 case ANDROID_IMAGE_DECODER_INVALID_SCALE:
81 return "ANDROID_IMAGE_DECODER_INVALID_SCALE";
82 case ANDROID_IMAGE_DECODER_BAD_PARAMETER:
83 return "ANDROID_IMAGE_DECODER_BAD_PARAMETER";
84 case ANDROID_IMAGE_DECODER_INVALID_INPUT:
85 return "ANDROID_IMAGE_DECODER_INVALID_INPUT";
86 case ANDROID_IMAGE_DECODER_SEEK_ERROR:
87 return "ANDROID_IMAGE_DECODER_SEEK_ERROR";
88 case ANDROID_IMAGE_DECODER_INTERNAL_ERROR:
89 return "ANDROID_IMAGE_DECODER_INTERNAL_ERROR";
90 case ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT:
91 return "ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT";
92 case ANDROID_IMAGE_DECODER_FINISHED:
93 return "ANDROID_IMAGE_DECODER_FINISHED";
94 case ANDROID_IMAGE_DECODER_INVALID_STATE:
95 return "ANDROID_IMAGE_DECODER_INVALID_STATE";
96 default:
97 return nullptr;
98 }
99}
100
Leon Scroggins III407b5442019-11-22 17:10:20 -0500101static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
102 SkCodec::Result result;
103 auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
104 SkCodec::SelectionPolicy::kPreferAnimation);
Leon Scroggins III139145b2020-12-17 15:43:54 -0500105 // These may be swapped due to the SkEncodedOrigin, but we're just checking
106 // them to make sure they fit in int32_t.
107 auto dimensions = codec->dimensions();
108 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
Leon Scroggins III407b5442019-11-22 17:10:20 -0500109 if (!androidCodec) {
110 return ResultToErrorCode(result);
111 }
112
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -0500113 // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
114 // the conversion is safe.
Leon Scroggins III139145b2020-12-17 15:43:54 -0500115 if (dimensions.width() > std::numeric_limits<int32_t>::max() ||
116 dimensions.height() > std::numeric_limits<int32_t>::max()) {
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -0500117 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
118 }
119
Leon Scroggins III407b5442019-11-22 17:10:20 -0500120 *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
121 return ANDROID_IMAGE_DECODER_SUCCESS;
122}
123
124int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
125 if (!asset || !outDecoder) {
126 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
127 }
128 *outDecoder = nullptr;
129
Leon Scroggins IIIc72d0fb2020-12-30 16:38:23 -0500130#ifdef __ANDROID__
Leon Scroggins III407b5442019-11-22 17:10:20 -0500131 auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
132 return createFromStream(std::move(stream), outDecoder);
Leon Scroggins IIIc72d0fb2020-12-30 16:38:23 -0500133#else
134 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
135#endif
Leon Scroggins III407b5442019-11-22 17:10:20 -0500136}
137
138static bool isSeekable(int descriptor) {
139 return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
140}
141
142int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
143 if (fd <= 0 || !outDecoder) {
144 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
145 }
146
147 struct stat fdStat;
148 if (fstat(fd, &fdStat) == -1) {
149 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
150 }
151
152 if (!isSeekable(fd)) {
153 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
154 }
155
156 // SkFILEStream will close its descriptor. Duplicate it so the client will
157 // still be responsible for closing the original.
158 int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
159 FILE* file = fdopen(dupDescriptor, "r");
160 if (!file) {
161 close(dupDescriptor);
162 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
163 }
164
165 auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
166 return createFromStream(std::move(stream), outDecoder);
167}
168
169int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
170 AImageDecoder** outDecoder) {
171 if (!buffer || !length || !outDecoder) {
172 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
173 }
174 *outDecoder = nullptr;
175
176 // The client is expected to keep the buffer alive as long as the
177 // AImageDecoder, so we do not need to copy the buffer.
178 auto stream = std::unique_ptr<SkStreamRewindable>(
179 new SkMemoryStream(buffer, length, false /* copyData */));
180 return createFromStream(std::move(stream), outDecoder);
181}
182
183static ImageDecoder* toDecoder(AImageDecoder* d) {
184 return reinterpret_cast<ImageDecoder*>(d);
185}
186
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500187static const ImageDecoder* toDecoder(const AImageDecoder* d) {
188 return reinterpret_cast<const ImageDecoder*>(d);
189}
190
Leon Scroggins III407b5442019-11-22 17:10:20 -0500191// Note: This differs from the version in android_bitmap.cpp in that this
192// version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
193// allows decoding single channel images to gray, which Android then treats
194// as A_8/ALPHA_8.
195static SkColorType getColorType(AndroidBitmapFormat format) {
196 switch (format) {
197 case ANDROID_BITMAP_FORMAT_RGBA_8888:
198 return kN32_SkColorType;
199 case ANDROID_BITMAP_FORMAT_RGB_565:
200 return kRGB_565_SkColorType;
201 case ANDROID_BITMAP_FORMAT_RGBA_4444:
202 return kARGB_4444_SkColorType;
203 case ANDROID_BITMAP_FORMAT_A_8:
204 return kGray_8_SkColorType;
205 case ANDROID_BITMAP_FORMAT_RGBA_F16:
206 return kRGBA_F16_SkColorType;
Alec Mouri1efd0a52022-01-20 13:58:23 -0800207 case ANDROID_BITMAP_FORMAT_RGBA_1010102:
208 return kRGBA_1010102_SkColorType;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500209 default:
210 return kUnknown_SkColorType;
211 }
212}
213
214int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
Alec Mouri1efd0a52022-01-20 13:58:23 -0800215 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE ||
216 format > ANDROID_BITMAP_FORMAT_RGBA_1010102) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500217 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
218 }
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500219
220 auto* imageDecoder = toDecoder(decoder);
221 if (imageDecoder->currentFrame() != 0) {
222 return ANDROID_IMAGE_DECODER_INVALID_STATE;
223 }
224
225 return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
Leon Scroggins III407b5442019-11-22 17:10:20 -0500226 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
227}
228
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500229int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
230 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
231 // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
232 if (!decoder || !dataspace || !cs) {
233 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
234 }
235
236 ImageDecoder* imageDecoder = toDecoder(decoder);
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500237 if (imageDecoder->currentFrame() != 0) {
238 return ANDROID_IMAGE_DECODER_INVALID_STATE;
239 }
240
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500241 imageDecoder->setOutColorSpace(std::move(cs));
242 return ANDROID_IMAGE_DECODER_SUCCESS;
243}
244
Leon Scroggins III407b5442019-11-22 17:10:20 -0500245const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
246 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
247}
248
249static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
250 return reinterpret_cast<const ImageDecoder*>(info);
251}
252
253int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
254 if (!info) {
255 return 0;
256 }
Leon Scroggins III139145b2020-12-17 15:43:54 -0500257 return toDecoder(info)->width();
Leon Scroggins III407b5442019-11-22 17:10:20 -0500258}
259
260int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
261 if (!info) {
262 return 0;
263 }
Leon Scroggins III139145b2020-12-17 15:43:54 -0500264 return toDecoder(info)->height();
Leon Scroggins III407b5442019-11-22 17:10:20 -0500265}
266
267const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
268 if (!info) {
269 return nullptr;
270 }
271 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
272}
273
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500274int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
275 if (!info) {
276 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
277 }
278
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500279 // Note: This recomputes the color type because it's possible the client has
280 // changed the output color type, so we cannot rely on it. Alternatively,
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500281 // we could store the ADataSpace in the ImageDecoder.
282 const ImageDecoder* imageDecoder = toDecoder(info);
283 SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500284 sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500285 return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
286}
287
Leon Scroggins III407b5442019-11-22 17:10:20 -0500288// FIXME: Share with getFormat in android_bitmap.cpp?
289static AndroidBitmapFormat getFormat(SkColorType colorType) {
290 switch (colorType) {
291 case kN32_SkColorType:
292 return ANDROID_BITMAP_FORMAT_RGBA_8888;
293 case kRGB_565_SkColorType:
294 return ANDROID_BITMAP_FORMAT_RGB_565;
295 case kARGB_4444_SkColorType:
296 return ANDROID_BITMAP_FORMAT_RGBA_4444;
297 case kAlpha_8_SkColorType:
298 return ANDROID_BITMAP_FORMAT_A_8;
299 case kRGBA_F16_SkColorType:
300 return ANDROID_BITMAP_FORMAT_RGBA_F16;
Alec Mouri1efd0a52022-01-20 13:58:23 -0800301 case kRGBA_1010102_SkColorType:
302 return ANDROID_BITMAP_FORMAT_RGBA_1010102;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500303 default:
304 return ANDROID_BITMAP_FORMAT_NONE;
305 }
306}
307
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500308int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500309 if (!info) {
310 return ANDROID_BITMAP_FORMAT_NONE;
311 }
312 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
313}
314
315int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
316 if (!info) {
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500317 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500318 }
319 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
320 case kUnknown_SkAlphaType:
321 LOG_ALWAYS_FATAL("Invalid alpha type");
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500322 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500323 case kUnpremul_SkAlphaType:
324 // fall through. premul is the default.
325 case kPremul_SkAlphaType:
326 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
327 case kOpaque_SkAlphaType:
328 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
329 }
330}
331
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500332int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
333 if (!decoder) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500334 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
335 }
336
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500337 auto* imageDecoder = toDecoder(decoder);
338 if (imageDecoder->currentFrame() != 0) {
339 return ANDROID_IMAGE_DECODER_INVALID_STATE;
340 }
341
342 return imageDecoder->setUnpremultipliedRequired(required)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500343 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
344}
345
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500346int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500347 if (!decoder) {
348 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
349 }
350
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500351 auto* imageDecoder = toDecoder(decoder);
352 if (imageDecoder->currentFrame() != 0) {
353 return ANDROID_IMAGE_DECODER_INVALID_STATE;
354 }
355
356 return imageDecoder->setTargetSize(width, height)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500357 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
358}
359
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500360int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500361 int32_t* width, int32_t* height) {
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500362 if (!decoder || !width || !height || sampleSize < 1) {
363 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
364 }
365
Leon Scroggins III5a5c2ce2021-01-15 14:09:13 -0500366 SkISize size = toDecoder(decoder)->getSampledDimensions(sampleSize);
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500367 *width = size.width();
368 *height = size.height();
369 return ANDROID_IMAGE_DECODER_SUCCESS;
370}
371
Leon Scroggins III407b5442019-11-22 17:10:20 -0500372int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
373 if (!decoder) {
374 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
375 }
376
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500377 auto* imageDecoder = toDecoder(decoder);
378 if (imageDecoder->currentFrame() != 0) {
379 return ANDROID_IMAGE_DECODER_INVALID_STATE;
380 }
381
Leon Scroggins III407b5442019-11-22 17:10:20 -0500382 SkIRect cropIRect;
383 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
384 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500385 return imageDecoder->setCropRect(cropPtr)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500386 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
387}
388
389
390size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
391 if (!decoder) {
392 return 0;
393 }
394
395 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
396 return info.minRowBytes();
397}
398
399int AImageDecoder_decodeImage(AImageDecoder* decoder,
400 void* pixels, size_t stride,
401 size_t size) {
402 if (!decoder || !pixels || !stride) {
403 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
404 }
405
406 ImageDecoder* imageDecoder = toDecoder(decoder);
407
Leon Scroggins IIId894c592020-01-22 14:18:12 -0500408 SkImageInfo info = imageDecoder->getOutputInfo();
409 size_t minSize = info.computeByteSize(stride);
410 if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500411 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
412 }
413
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500414 if (imageDecoder->finished()) {
415 return ANDROID_IMAGE_DECODER_FINISHED;
416 }
417
Leon Scroggins III407b5442019-11-22 17:10:20 -0500418 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
419}
420
421void AImageDecoder_delete(AImageDecoder* decoder) {
422 delete toDecoder(decoder);
423}
Leon Scroggins III24ae7d72020-10-09 13:14:35 -0400424
425bool AImageDecoder_isAnimated(AImageDecoder* decoder) {
426 if (!decoder) return false;
427
428 ImageDecoder* imageDecoder = toDecoder(decoder);
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500429 return imageDecoder->isAnimated();
Leon Scroggins III24ae7d72020-10-09 13:14:35 -0400430}
Leon Scroggins III3ad12c42020-10-12 10:56:42 -0400431
432int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
433 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
434
435 ImageDecoder* imageDecoder = toDecoder(decoder);
436 const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
437
438 // Skia should not report anything out of range, but defensively treat
439 // negative and too big as INFINITE.
440 if (count == SkCodec::kRepetitionCountInfinite || count < 0
441 || count > std::numeric_limits<int32_t>::max()) {
442 return ANDROID_IMAGE_DECODER_INFINITE;
443 }
444 return count;
445}
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500446
447int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
448 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
449
450 ImageDecoder* imageDecoder = toDecoder(decoder);
451 if (!imageDecoder->isAnimated()) {
452 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
453 }
454
Leon Scroggins IIIdf33b952021-04-26 15:35:56 -0400455 const auto colorType = imageDecoder->getOutputInfo().colorType();
456 switch (colorType) {
457 case kN32_SkColorType:
458 case kRGBA_F16_SkColorType:
459 break;
460 default:
461 return ANDROID_IMAGE_DECODER_INVALID_STATE;
462 }
463
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500464 if (imageDecoder->advanceFrame()) {
465 return ANDROID_IMAGE_DECODER_SUCCESS;
466 }
467
468 if (imageDecoder->finished()) {
469 return ANDROID_IMAGE_DECODER_FINISHED;
470 }
471
472 return ANDROID_IMAGE_DECODER_INCOMPLETE;
473}
474
475int AImageDecoder_rewind(AImageDecoder* decoder) {
476 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
477
478 ImageDecoder* imageDecoder = toDecoder(decoder);
479 if (!imageDecoder->isAnimated()) {
480 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
481 }
482
483 return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
484 : ANDROID_IMAGE_DECODER_SEEK_ERROR;
485}
Leon Scroggins III06213132020-12-28 15:31:48 -0500486
487AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
488 return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
489}
490
491static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
492 return reinterpret_cast<SkCodec::FrameInfo*>(info);
493}
494
495static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
496 return reinterpret_cast<const SkCodec::FrameInfo*>(info);
497}
498
499void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
500 delete toFrameInfo(info);
501}
502
503int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
504 AImageDecoderFrameInfo* info) {
505 if (!decoder || !info) {
506 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
507 }
508
509 auto* imageDecoder = toDecoder(decoder);
510 if (imageDecoder->finished()) {
511 return ANDROID_IMAGE_DECODER_FINISHED;
512 }
513
514 *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
515 return ANDROID_IMAGE_DECODER_SUCCESS;
516}
517
518int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
Leon Scroggins III6116e5c2021-05-03 11:34:34 -0400519 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III06213132020-12-28 15:31:48 -0500520
521 return toFrameInfo(info)->fDuration * 1'000'000;
522}
523
524ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
525 if (!info) {
526 return { 0, 0, 0, 0};
527 }
528
529 const SkIRect& r = toFrameInfo(info)->fFrameRect;
530 return { r.left(), r.top(), r.right(), r.bottom() };
531}
532
533bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
534 if (!info) return false;
535
536 return toFrameInfo(info)->fHasAlphaWithinBounds;
537}
538
539int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
540 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
541
542 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
543 == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
544 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
545 == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
546 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
547 == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
548 return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
549}
550
551int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
552 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
553
554 switch (toFrameInfo(info)->fBlend) {
555 case SkCodecAnimation::Blend::kSrc:
556 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
557 case SkCodecAnimation::Blend::kSrcOver:
558 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
559 }
560}
Leon Scroggins IIIc2ebc2b2021-01-13 09:46:06 -0500561
562void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
563 if (decoder) {
564 toDecoder(decoder)->setHandleRestorePrevious(handle);
565 }
566}