blob: 5973790e48fdfaa5c2eb4bd3136779f9782e09f2 [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>
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -050028#include <utils/Color.h>
Leon Scroggins III407b5442019-11-22 17:10:20 -050029
30#include <fcntl.h>
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -050031#include <limits>
Leon Scroggins III407b5442019-11-22 17:10:20 -050032#include <optional>
33#include <sys/stat.h>
34#include <sys/types.h>
35#include <unistd.h>
36
37using namespace android;
38
39int ResultToErrorCode(SkCodec::Result result) {
40 switch (result) {
41 case SkCodec::kIncompleteInput:
42 return ANDROID_IMAGE_DECODER_INCOMPLETE;
43 case SkCodec::kErrorInInput:
44 return ANDROID_IMAGE_DECODER_ERROR;
45 case SkCodec::kInvalidInput:
46 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
47 case SkCodec::kCouldNotRewind:
48 return ANDROID_IMAGE_DECODER_SEEK_ERROR;
49 case SkCodec::kUnimplemented:
50 return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
51 case SkCodec::kInvalidConversion:
52 return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
53 case SkCodec::kInvalidParameters:
54 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
55 case SkCodec::kSuccess:
56 return ANDROID_IMAGE_DECODER_SUCCESS;
57 case SkCodec::kInvalidScale:
58 return ANDROID_IMAGE_DECODER_INVALID_SCALE;
59 case SkCodec::kInternalError:
60 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
61 }
62}
63
Leon Scroggins III946f8d42020-12-02 14:05:44 -050064const char* AImageDecoder_resultToString(int result) {
65 switch (result) {
66 case ANDROID_IMAGE_DECODER_SUCCESS:
67 return "ANDROID_IMAGE_DECODER_SUCCESS";
68 case ANDROID_IMAGE_DECODER_INCOMPLETE:
69 return "ANDROID_IMAGE_DECODER_INCOMPLETE";
70 case ANDROID_IMAGE_DECODER_ERROR:
71 return "ANDROID_IMAGE_DECODER_ERROR";
72 case ANDROID_IMAGE_DECODER_INVALID_CONVERSION:
73 return "ANDROID_IMAGE_DECODER_INVALID_CONVERSION";
74 case ANDROID_IMAGE_DECODER_INVALID_SCALE:
75 return "ANDROID_IMAGE_DECODER_INVALID_SCALE";
76 case ANDROID_IMAGE_DECODER_BAD_PARAMETER:
77 return "ANDROID_IMAGE_DECODER_BAD_PARAMETER";
78 case ANDROID_IMAGE_DECODER_INVALID_INPUT:
79 return "ANDROID_IMAGE_DECODER_INVALID_INPUT";
80 case ANDROID_IMAGE_DECODER_SEEK_ERROR:
81 return "ANDROID_IMAGE_DECODER_SEEK_ERROR";
82 case ANDROID_IMAGE_DECODER_INTERNAL_ERROR:
83 return "ANDROID_IMAGE_DECODER_INTERNAL_ERROR";
84 case ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT:
85 return "ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT";
86 case ANDROID_IMAGE_DECODER_FINISHED:
87 return "ANDROID_IMAGE_DECODER_FINISHED";
88 case ANDROID_IMAGE_DECODER_INVALID_STATE:
89 return "ANDROID_IMAGE_DECODER_INVALID_STATE";
90 default:
91 return nullptr;
92 }
93}
94
Leon Scroggins III407b5442019-11-22 17:10:20 -050095static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
96 SkCodec::Result result;
97 auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
98 SkCodec::SelectionPolicy::kPreferAnimation);
Leon Scroggins III139145b2020-12-17 15:43:54 -050099 // These may be swapped due to the SkEncodedOrigin, but we're just checking
100 // them to make sure they fit in int32_t.
101 auto dimensions = codec->dimensions();
102 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
Leon Scroggins III407b5442019-11-22 17:10:20 -0500103 if (!androidCodec) {
104 return ResultToErrorCode(result);
105 }
106
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -0500107 // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
108 // the conversion is safe.
Leon Scroggins III139145b2020-12-17 15:43:54 -0500109 if (dimensions.width() > std::numeric_limits<int32_t>::max() ||
110 dimensions.height() > std::numeric_limits<int32_t>::max()) {
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -0500111 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
112 }
113
Leon Scroggins III407b5442019-11-22 17:10:20 -0500114 *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
115 return ANDROID_IMAGE_DECODER_SUCCESS;
116}
117
118int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
119 if (!asset || !outDecoder) {
120 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
121 }
122 *outDecoder = nullptr;
123
124 auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
125 return createFromStream(std::move(stream), outDecoder);
126}
127
128static bool isSeekable(int descriptor) {
129 return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
130}
131
132int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
133 if (fd <= 0 || !outDecoder) {
134 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
135 }
136
137 struct stat fdStat;
138 if (fstat(fd, &fdStat) == -1) {
139 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
140 }
141
142 if (!isSeekable(fd)) {
143 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
144 }
145
146 // SkFILEStream will close its descriptor. Duplicate it so the client will
147 // still be responsible for closing the original.
148 int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
149 FILE* file = fdopen(dupDescriptor, "r");
150 if (!file) {
151 close(dupDescriptor);
152 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
153 }
154
155 auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
156 return createFromStream(std::move(stream), outDecoder);
157}
158
159int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
160 AImageDecoder** outDecoder) {
161 if (!buffer || !length || !outDecoder) {
162 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
163 }
164 *outDecoder = nullptr;
165
166 // The client is expected to keep the buffer alive as long as the
167 // AImageDecoder, so we do not need to copy the buffer.
168 auto stream = std::unique_ptr<SkStreamRewindable>(
169 new SkMemoryStream(buffer, length, false /* copyData */));
170 return createFromStream(std::move(stream), outDecoder);
171}
172
173static ImageDecoder* toDecoder(AImageDecoder* d) {
174 return reinterpret_cast<ImageDecoder*>(d);
175}
176
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500177static const ImageDecoder* toDecoder(const AImageDecoder* d) {
178 return reinterpret_cast<const ImageDecoder*>(d);
179}
180
Leon Scroggins III407b5442019-11-22 17:10:20 -0500181// Note: This differs from the version in android_bitmap.cpp in that this
182// version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
183// allows decoding single channel images to gray, which Android then treats
184// as A_8/ALPHA_8.
185static SkColorType getColorType(AndroidBitmapFormat format) {
186 switch (format) {
187 case ANDROID_BITMAP_FORMAT_RGBA_8888:
188 return kN32_SkColorType;
189 case ANDROID_BITMAP_FORMAT_RGB_565:
190 return kRGB_565_SkColorType;
191 case ANDROID_BITMAP_FORMAT_RGBA_4444:
192 return kARGB_4444_SkColorType;
193 case ANDROID_BITMAP_FORMAT_A_8:
194 return kGray_8_SkColorType;
195 case ANDROID_BITMAP_FORMAT_RGBA_F16:
196 return kRGBA_F16_SkColorType;
197 default:
198 return kUnknown_SkColorType;
199 }
200}
201
202int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
203 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
204 || format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
205 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
206 }
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500207
208 auto* imageDecoder = toDecoder(decoder);
209 if (imageDecoder->currentFrame() != 0) {
210 return ANDROID_IMAGE_DECODER_INVALID_STATE;
211 }
212
213 return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
Leon Scroggins III407b5442019-11-22 17:10:20 -0500214 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
215}
216
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500217int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
218 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
219 // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
220 if (!decoder || !dataspace || !cs) {
221 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
222 }
223
224 ImageDecoder* imageDecoder = toDecoder(decoder);
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500225 if (imageDecoder->currentFrame() != 0) {
226 return ANDROID_IMAGE_DECODER_INVALID_STATE;
227 }
228
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500229 imageDecoder->setOutColorSpace(std::move(cs));
230 return ANDROID_IMAGE_DECODER_SUCCESS;
231}
232
Leon Scroggins III407b5442019-11-22 17:10:20 -0500233const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
234 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
235}
236
237static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
238 return reinterpret_cast<const ImageDecoder*>(info);
239}
240
241int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
242 if (!info) {
243 return 0;
244 }
Leon Scroggins III139145b2020-12-17 15:43:54 -0500245 return toDecoder(info)->width();
Leon Scroggins III407b5442019-11-22 17:10:20 -0500246}
247
248int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
249 if (!info) {
250 return 0;
251 }
Leon Scroggins III139145b2020-12-17 15:43:54 -0500252 return toDecoder(info)->height();
Leon Scroggins III407b5442019-11-22 17:10:20 -0500253}
254
255const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
256 if (!info) {
257 return nullptr;
258 }
259 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
260}
261
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500262int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
263 if (!info) {
264 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
265 }
266
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500267 // Note: This recomputes the color type because it's possible the client has
268 // changed the output color type, so we cannot rely on it. Alternatively,
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500269 // we could store the ADataSpace in the ImageDecoder.
270 const ImageDecoder* imageDecoder = toDecoder(info);
271 SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500272 sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500273 return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
274}
275
Leon Scroggins III407b5442019-11-22 17:10:20 -0500276// FIXME: Share with getFormat in android_bitmap.cpp?
277static AndroidBitmapFormat getFormat(SkColorType colorType) {
278 switch (colorType) {
279 case kN32_SkColorType:
280 return ANDROID_BITMAP_FORMAT_RGBA_8888;
281 case kRGB_565_SkColorType:
282 return ANDROID_BITMAP_FORMAT_RGB_565;
283 case kARGB_4444_SkColorType:
284 return ANDROID_BITMAP_FORMAT_RGBA_4444;
285 case kAlpha_8_SkColorType:
286 return ANDROID_BITMAP_FORMAT_A_8;
287 case kRGBA_F16_SkColorType:
288 return ANDROID_BITMAP_FORMAT_RGBA_F16;
289 default:
290 return ANDROID_BITMAP_FORMAT_NONE;
291 }
292}
293
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500294int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500295 if (!info) {
296 return ANDROID_BITMAP_FORMAT_NONE;
297 }
298 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
299}
300
301int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
302 if (!info) {
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500303 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500304 }
305 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
306 case kUnknown_SkAlphaType:
307 LOG_ALWAYS_FATAL("Invalid alpha type");
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500308 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500309 case kUnpremul_SkAlphaType:
310 // fall through. premul is the default.
311 case kPremul_SkAlphaType:
312 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
313 case kOpaque_SkAlphaType:
314 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
315 }
316}
317
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500318int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
319 if (!decoder) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500320 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
321 }
322
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500323 auto* imageDecoder = toDecoder(decoder);
324 if (imageDecoder->currentFrame() != 0) {
325 return ANDROID_IMAGE_DECODER_INVALID_STATE;
326 }
327
328 return imageDecoder->setUnpremultipliedRequired(required)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500329 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
330}
331
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500332int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500333 if (!decoder) {
334 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->setTargetSize(width, height)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500343 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
344}
345
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500346int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500347 int32_t* width, int32_t* height) {
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500348 if (!decoder || !width || !height || sampleSize < 1) {
349 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
350 }
351
352 SkISize size = toDecoder(decoder)->mCodec->getSampledDimensions(sampleSize);
353 *width = size.width();
354 *height = size.height();
355 return ANDROID_IMAGE_DECODER_SUCCESS;
356}
357
Leon Scroggins III407b5442019-11-22 17:10:20 -0500358int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
359 if (!decoder) {
360 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
361 }
362
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500363 auto* imageDecoder = toDecoder(decoder);
364 if (imageDecoder->currentFrame() != 0) {
365 return ANDROID_IMAGE_DECODER_INVALID_STATE;
366 }
367
Leon Scroggins III407b5442019-11-22 17:10:20 -0500368 SkIRect cropIRect;
369 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
370 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500371 return imageDecoder->setCropRect(cropPtr)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500372 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
373}
374
375
376size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
377 if (!decoder) {
378 return 0;
379 }
380
381 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
382 return info.minRowBytes();
383}
384
385int AImageDecoder_decodeImage(AImageDecoder* decoder,
386 void* pixels, size_t stride,
387 size_t size) {
388 if (!decoder || !pixels || !stride) {
389 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
390 }
391
392 ImageDecoder* imageDecoder = toDecoder(decoder);
393
Leon Scroggins IIId894c592020-01-22 14:18:12 -0500394 SkImageInfo info = imageDecoder->getOutputInfo();
395 size_t minSize = info.computeByteSize(stride);
396 if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500397 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
398 }
399
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500400 if (imageDecoder->finished()) {
401 return ANDROID_IMAGE_DECODER_FINISHED;
402 }
403
Leon Scroggins III407b5442019-11-22 17:10:20 -0500404 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
405}
406
407void AImageDecoder_delete(AImageDecoder* decoder) {
408 delete toDecoder(decoder);
409}
Leon Scroggins III24ae7d72020-10-09 13:14:35 -0400410
411bool AImageDecoder_isAnimated(AImageDecoder* decoder) {
412 if (!decoder) return false;
413
414 ImageDecoder* imageDecoder = toDecoder(decoder);
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500415 return imageDecoder->isAnimated();
Leon Scroggins III24ae7d72020-10-09 13:14:35 -0400416}
Leon Scroggins III3ad12c42020-10-12 10:56:42 -0400417
418int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
419 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
420
421 ImageDecoder* imageDecoder = toDecoder(decoder);
422 const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
423
424 // Skia should not report anything out of range, but defensively treat
425 // negative and too big as INFINITE.
426 if (count == SkCodec::kRepetitionCountInfinite || count < 0
427 || count > std::numeric_limits<int32_t>::max()) {
428 return ANDROID_IMAGE_DECODER_INFINITE;
429 }
430 return count;
431}
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500432
433int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
434 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
435
436 ImageDecoder* imageDecoder = toDecoder(decoder);
437 if (!imageDecoder->isAnimated()) {
438 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
439 }
440
441 if (imageDecoder->advanceFrame()) {
442 return ANDROID_IMAGE_DECODER_SUCCESS;
443 }
444
445 if (imageDecoder->finished()) {
446 return ANDROID_IMAGE_DECODER_FINISHED;
447 }
448
449 return ANDROID_IMAGE_DECODER_INCOMPLETE;
450}
451
452int AImageDecoder_rewind(AImageDecoder* decoder) {
453 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
454
455 ImageDecoder* imageDecoder = toDecoder(decoder);
456 if (!imageDecoder->isAnimated()) {
457 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
458 }
459
460 return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
461 : ANDROID_IMAGE_DECODER_SEEK_ERROR;
462}
Leon Scroggins III06213132020-12-28 15:31:48 -0500463
464AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
465 return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
466}
467
468static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
469 return reinterpret_cast<SkCodec::FrameInfo*>(info);
470}
471
472static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
473 return reinterpret_cast<const SkCodec::FrameInfo*>(info);
474}
475
476void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
477 delete toFrameInfo(info);
478}
479
480int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
481 AImageDecoderFrameInfo* info) {
482 if (!decoder || !info) {
483 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
484 }
485
486 auto* imageDecoder = toDecoder(decoder);
487 if (imageDecoder->finished()) {
488 return ANDROID_IMAGE_DECODER_FINISHED;
489 }
490
491 *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
492 return ANDROID_IMAGE_DECODER_SUCCESS;
493}
494
495int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
496 if (!info) return 0;
497
498 return toFrameInfo(info)->fDuration * 1'000'000;
499}
500
501ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
502 if (!info) {
503 return { 0, 0, 0, 0};
504 }
505
506 const SkIRect& r = toFrameInfo(info)->fFrameRect;
507 return { r.left(), r.top(), r.right(), r.bottom() };
508}
509
510bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
511 if (!info) return false;
512
513 return toFrameInfo(info)->fHasAlphaWithinBounds;
514}
515
516int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
517 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
518
519 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
520 == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
521 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
522 == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
523 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
524 == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
525 return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
526}
527
528int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
529 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
530
531 switch (toFrameInfo(info)->fBlend) {
532 case SkCodecAnimation::Blend::kSrc:
533 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
534 case SkCodecAnimation::Blend::kSrcOver:
535 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
536 }
537}
Leon Scroggins IIIc2ebc2b2021-01-13 09:46:06 -0500538
539void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
540 if (decoder) {
541 toDecoder(decoder)->setHandleRestorePrevious(handle);
542 }
543}