blob: e18b4a9d242018e60e2af74ef3b01c4095394110 [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 Lubick08409e22023-02-14 14:29:25 +000028#include <SkAlphaType.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050029#include <SkCodec.h>
Kevin Lubick08409e22023-02-14 14:29:25 +000030#include <SkCodecAnimation.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050031#include <SkColorSpace.h>
Kevin Lubick08409e22023-02-14 14:29:25 +000032#include <SkColorType.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050033#include <SkImageInfo.h>
34#include <SkRect.h>
Kevin Lubick08409e22023-02-14 14:29:25 +000035#include <SkRefCnt.h>
Kevin Lubick1175dc02022-02-28 12:41:27 -050036#include <SkSize.h>
37#include <SkStream.h>
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -050038#include <utils/Color.h>
Leon Scroggins III407b5442019-11-22 17:10:20 -050039
40#include <fcntl.h>
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -050041#include <limits>
Leon Scroggins III407b5442019-11-22 17:10:20 -050042#include <optional>
43#include <sys/stat.h>
44#include <sys/types.h>
45#include <unistd.h>
46
47using namespace android;
48
49int ResultToErrorCode(SkCodec::Result result) {
50 switch (result) {
51 case SkCodec::kIncompleteInput:
52 return ANDROID_IMAGE_DECODER_INCOMPLETE;
53 case SkCodec::kErrorInInput:
54 return ANDROID_IMAGE_DECODER_ERROR;
55 case SkCodec::kInvalidInput:
56 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
57 case SkCodec::kCouldNotRewind:
58 return ANDROID_IMAGE_DECODER_SEEK_ERROR;
59 case SkCodec::kUnimplemented:
60 return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
61 case SkCodec::kInvalidConversion:
62 return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
63 case SkCodec::kInvalidParameters:
64 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
65 case SkCodec::kSuccess:
66 return ANDROID_IMAGE_DECODER_SUCCESS;
67 case SkCodec::kInvalidScale:
68 return ANDROID_IMAGE_DECODER_INVALID_SCALE;
69 case SkCodec::kInternalError:
70 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
71 }
72}
73
Leon Scroggins III946f8d42020-12-02 14:05:44 -050074const char* AImageDecoder_resultToString(int result) {
75 switch (result) {
76 case ANDROID_IMAGE_DECODER_SUCCESS:
77 return "ANDROID_IMAGE_DECODER_SUCCESS";
78 case ANDROID_IMAGE_DECODER_INCOMPLETE:
79 return "ANDROID_IMAGE_DECODER_INCOMPLETE";
80 case ANDROID_IMAGE_DECODER_ERROR:
81 return "ANDROID_IMAGE_DECODER_ERROR";
82 case ANDROID_IMAGE_DECODER_INVALID_CONVERSION:
83 return "ANDROID_IMAGE_DECODER_INVALID_CONVERSION";
84 case ANDROID_IMAGE_DECODER_INVALID_SCALE:
85 return "ANDROID_IMAGE_DECODER_INVALID_SCALE";
86 case ANDROID_IMAGE_DECODER_BAD_PARAMETER:
87 return "ANDROID_IMAGE_DECODER_BAD_PARAMETER";
88 case ANDROID_IMAGE_DECODER_INVALID_INPUT:
89 return "ANDROID_IMAGE_DECODER_INVALID_INPUT";
90 case ANDROID_IMAGE_DECODER_SEEK_ERROR:
91 return "ANDROID_IMAGE_DECODER_SEEK_ERROR";
92 case ANDROID_IMAGE_DECODER_INTERNAL_ERROR:
93 return "ANDROID_IMAGE_DECODER_INTERNAL_ERROR";
94 case ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT:
95 return "ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT";
96 case ANDROID_IMAGE_DECODER_FINISHED:
97 return "ANDROID_IMAGE_DECODER_FINISHED";
98 case ANDROID_IMAGE_DECODER_INVALID_STATE:
99 return "ANDROID_IMAGE_DECODER_INVALID_STATE";
100 default:
101 return nullptr;
102 }
103}
104
Leon Scroggins III407b5442019-11-22 17:10:20 -0500105static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
106 SkCodec::Result result;
107 auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
108 SkCodec::SelectionPolicy::kPreferAnimation);
Leon Scroggins III139145b2020-12-17 15:43:54 -0500109 // These may be swapped due to the SkEncodedOrigin, but we're just checking
110 // them to make sure they fit in int32_t.
111 auto dimensions = codec->dimensions();
112 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec));
Leon Scroggins III407b5442019-11-22 17:10:20 -0500113 if (!androidCodec) {
114 return ResultToErrorCode(result);
115 }
116
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -0500117 // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
118 // the conversion is safe.
Leon Scroggins III139145b2020-12-17 15:43:54 -0500119 if (dimensions.width() > std::numeric_limits<int32_t>::max() ||
120 dimensions.height() > std::numeric_limits<int32_t>::max()) {
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -0500121 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
122 }
123
Leon Scroggins III407b5442019-11-22 17:10:20 -0500124 *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
125 return ANDROID_IMAGE_DECODER_SUCCESS;
126}
127
128int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
129 if (!asset || !outDecoder) {
130 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
131 }
132 *outDecoder = nullptr;
133
Leon Scroggins IIIc72d0fb2020-12-30 16:38:23 -0500134#ifdef __ANDROID__
Leon Scroggins III407b5442019-11-22 17:10:20 -0500135 auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
136 return createFromStream(std::move(stream), outDecoder);
Leon Scroggins IIIc72d0fb2020-12-30 16:38:23 -0500137#else
138 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
139#endif
Leon Scroggins III407b5442019-11-22 17:10:20 -0500140}
141
142static bool isSeekable(int descriptor) {
143 return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
144}
145
146int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
147 if (fd <= 0 || !outDecoder) {
148 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
149 }
150
151 struct stat fdStat;
152 if (fstat(fd, &fdStat) == -1) {
153 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
154 }
155
156 if (!isSeekable(fd)) {
157 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
158 }
159
160 // SkFILEStream will close its descriptor. Duplicate it so the client will
161 // still be responsible for closing the original.
162 int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
163 FILE* file = fdopen(dupDescriptor, "r");
164 if (!file) {
165 close(dupDescriptor);
166 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
167 }
168
169 auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
170 return createFromStream(std::move(stream), outDecoder);
171}
172
173int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
174 AImageDecoder** outDecoder) {
175 if (!buffer || !length || !outDecoder) {
176 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
177 }
178 *outDecoder = nullptr;
179
180 // The client is expected to keep the buffer alive as long as the
181 // AImageDecoder, so we do not need to copy the buffer.
182 auto stream = std::unique_ptr<SkStreamRewindable>(
183 new SkMemoryStream(buffer, length, false /* copyData */));
184 return createFromStream(std::move(stream), outDecoder);
185}
186
187static ImageDecoder* toDecoder(AImageDecoder* d) {
188 return reinterpret_cast<ImageDecoder*>(d);
189}
190
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500191static const ImageDecoder* toDecoder(const AImageDecoder* d) {
192 return reinterpret_cast<const ImageDecoder*>(d);
193}
194
Leon Scroggins III407b5442019-11-22 17:10:20 -0500195// Note: This differs from the version in android_bitmap.cpp in that this
196// version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
197// allows decoding single channel images to gray, which Android then treats
198// as A_8/ALPHA_8.
199static SkColorType getColorType(AndroidBitmapFormat format) {
200 switch (format) {
201 case ANDROID_BITMAP_FORMAT_RGBA_8888:
202 return kN32_SkColorType;
203 case ANDROID_BITMAP_FORMAT_RGB_565:
204 return kRGB_565_SkColorType;
205 case ANDROID_BITMAP_FORMAT_RGBA_4444:
206 return kARGB_4444_SkColorType;
207 case ANDROID_BITMAP_FORMAT_A_8:
208 return kGray_8_SkColorType;
209 case ANDROID_BITMAP_FORMAT_RGBA_F16:
210 return kRGBA_F16_SkColorType;
Alec Mouri1efd0a52022-01-20 13:58:23 -0800211 case ANDROID_BITMAP_FORMAT_RGBA_1010102:
212 return kRGBA_1010102_SkColorType;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500213 default:
214 return kUnknown_SkColorType;
215 }
216}
217
218int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
Alec Mouri1efd0a52022-01-20 13:58:23 -0800219 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE ||
220 format > ANDROID_BITMAP_FORMAT_RGBA_1010102) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500221 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
222 }
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500223
224 auto* imageDecoder = toDecoder(decoder);
225 if (imageDecoder->currentFrame() != 0) {
226 return ANDROID_IMAGE_DECODER_INVALID_STATE;
227 }
228
229 return imageDecoder->setOutColorType(getColorType((AndroidBitmapFormat) format))
Leon Scroggins III407b5442019-11-22 17:10:20 -0500230 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
231}
232
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500233int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
234 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
235 // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
236 if (!decoder || !dataspace || !cs) {
237 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
238 }
239
240 ImageDecoder* imageDecoder = toDecoder(decoder);
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500241 if (imageDecoder->currentFrame() != 0) {
242 return ANDROID_IMAGE_DECODER_INVALID_STATE;
243 }
244
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500245 imageDecoder->setOutColorSpace(std::move(cs));
246 return ANDROID_IMAGE_DECODER_SUCCESS;
247}
248
Leon Scroggins III407b5442019-11-22 17:10:20 -0500249const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
250 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
251}
252
253static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
254 return reinterpret_cast<const ImageDecoder*>(info);
255}
256
257int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
258 if (!info) {
259 return 0;
260 }
Leon Scroggins III139145b2020-12-17 15:43:54 -0500261 return toDecoder(info)->width();
Leon Scroggins III407b5442019-11-22 17:10:20 -0500262}
263
264int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
265 if (!info) {
266 return 0;
267 }
Leon Scroggins III139145b2020-12-17 15:43:54 -0500268 return toDecoder(info)->height();
Leon Scroggins III407b5442019-11-22 17:10:20 -0500269}
270
271const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
272 if (!info) {
273 return nullptr;
274 }
275 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
276}
277
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500278int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
279 if (!info) {
280 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
281 }
282
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500283 // Note: This recomputes the color type because it's possible the client has
284 // changed the output color type, so we cannot rely on it. Alternatively,
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500285 // we could store the ADataSpace in the ImageDecoder.
286 const ImageDecoder* imageDecoder = toDecoder(info);
287 SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500288 sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500289 return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
290}
291
Leon Scroggins III407b5442019-11-22 17:10:20 -0500292// FIXME: Share with getFormat in android_bitmap.cpp?
293static AndroidBitmapFormat getFormat(SkColorType colorType) {
294 switch (colorType) {
295 case kN32_SkColorType:
296 return ANDROID_BITMAP_FORMAT_RGBA_8888;
297 case kRGB_565_SkColorType:
298 return ANDROID_BITMAP_FORMAT_RGB_565;
299 case kARGB_4444_SkColorType:
300 return ANDROID_BITMAP_FORMAT_RGBA_4444;
301 case kAlpha_8_SkColorType:
302 return ANDROID_BITMAP_FORMAT_A_8;
303 case kRGBA_F16_SkColorType:
304 return ANDROID_BITMAP_FORMAT_RGBA_F16;
Alec Mouri1efd0a52022-01-20 13:58:23 -0800305 case kRGBA_1010102_SkColorType:
306 return ANDROID_BITMAP_FORMAT_RGBA_1010102;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500307 default:
308 return ANDROID_BITMAP_FORMAT_NONE;
309 }
310}
311
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500312int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500313 if (!info) {
314 return ANDROID_BITMAP_FORMAT_NONE;
315 }
316 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
317}
318
319int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
320 if (!info) {
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500321 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500322 }
323 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
324 case kUnknown_SkAlphaType:
325 LOG_ALWAYS_FATAL("Invalid alpha type");
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500326 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500327 case kUnpremul_SkAlphaType:
328 // fall through. premul is the default.
329 case kPremul_SkAlphaType:
330 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
331 case kOpaque_SkAlphaType:
332 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
333 }
334}
335
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500336int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
337 if (!decoder) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500338 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
339 }
340
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500341 auto* imageDecoder = toDecoder(decoder);
342 if (imageDecoder->currentFrame() != 0) {
343 return ANDROID_IMAGE_DECODER_INVALID_STATE;
344 }
345
346 return imageDecoder->setUnpremultipliedRequired(required)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500347 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
348}
349
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500350int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500351 if (!decoder) {
352 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
353 }
354
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500355 auto* imageDecoder = toDecoder(decoder);
356 if (imageDecoder->currentFrame() != 0) {
357 return ANDROID_IMAGE_DECODER_INVALID_STATE;
358 }
359
360 return imageDecoder->setTargetSize(width, height)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500361 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
362}
363
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500364int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500365 int32_t* width, int32_t* height) {
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500366 if (!decoder || !width || !height || sampleSize < 1) {
367 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
368 }
369
Leon Scroggins III5a5c2ce2021-01-15 14:09:13 -0500370 SkISize size = toDecoder(decoder)->getSampledDimensions(sampleSize);
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500371 *width = size.width();
372 *height = size.height();
373 return ANDROID_IMAGE_DECODER_SUCCESS;
374}
375
Leon Scroggins III407b5442019-11-22 17:10:20 -0500376int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
377 if (!decoder) {
378 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
379 }
380
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500381 auto* imageDecoder = toDecoder(decoder);
382 if (imageDecoder->currentFrame() != 0) {
383 return ANDROID_IMAGE_DECODER_INVALID_STATE;
384 }
385
Leon Scroggins III407b5442019-11-22 17:10:20 -0500386 SkIRect cropIRect;
387 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
Leon Scrogginsad70c8a2022-08-29 16:02:02 +0000388 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500389 return imageDecoder->setCropRect(cropPtr)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500390 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
391}
392
393
394size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
395 if (!decoder) {
396 return 0;
397 }
398
399 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
400 return info.minRowBytes();
401}
402
403int AImageDecoder_decodeImage(AImageDecoder* decoder,
404 void* pixels, size_t stride,
405 size_t size) {
406 if (!decoder || !pixels || !stride) {
407 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
408 }
409
410 ImageDecoder* imageDecoder = toDecoder(decoder);
411
Leon Scroggins IIId894c592020-01-22 14:18:12 -0500412 SkImageInfo info = imageDecoder->getOutputInfo();
413 size_t minSize = info.computeByteSize(stride);
414 if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500415 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
416 }
417
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500418 if (imageDecoder->finished()) {
419 return ANDROID_IMAGE_DECODER_FINISHED;
420 }
421
Leon Scroggins III407b5442019-11-22 17:10:20 -0500422 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
423}
424
425void AImageDecoder_delete(AImageDecoder* decoder) {
426 delete toDecoder(decoder);
427}
Leon Scroggins III24ae7d72020-10-09 13:14:35 -0400428
429bool AImageDecoder_isAnimated(AImageDecoder* decoder) {
430 if (!decoder) return false;
431
432 ImageDecoder* imageDecoder = toDecoder(decoder);
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500433 return imageDecoder->isAnimated();
Leon Scroggins III24ae7d72020-10-09 13:14:35 -0400434}
Leon Scroggins III3ad12c42020-10-12 10:56:42 -0400435
436int32_t AImageDecoder_getRepeatCount(AImageDecoder* decoder) {
437 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
438
439 ImageDecoder* imageDecoder = toDecoder(decoder);
440 const int count = imageDecoder->mCodec->codec()->getRepetitionCount();
441
442 // Skia should not report anything out of range, but defensively treat
443 // negative and too big as INFINITE.
444 if (count == SkCodec::kRepetitionCountInfinite || count < 0
445 || count > std::numeric_limits<int32_t>::max()) {
446 return ANDROID_IMAGE_DECODER_INFINITE;
447 }
448 return count;
449}
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500450
451int AImageDecoder_advanceFrame(AImageDecoder* decoder) {
452 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
453
454 ImageDecoder* imageDecoder = toDecoder(decoder);
455 if (!imageDecoder->isAnimated()) {
456 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
457 }
458
Leon Scroggins IIIdf33b952021-04-26 15:35:56 -0400459 const auto colorType = imageDecoder->getOutputInfo().colorType();
460 switch (colorType) {
461 case kN32_SkColorType:
462 case kRGBA_F16_SkColorType:
463 break;
464 default:
465 return ANDROID_IMAGE_DECODER_INVALID_STATE;
466 }
467
Leon Scroggins IIIb26aebc2020-12-21 14:55:22 -0500468 if (imageDecoder->advanceFrame()) {
469 return ANDROID_IMAGE_DECODER_SUCCESS;
470 }
471
472 if (imageDecoder->finished()) {
473 return ANDROID_IMAGE_DECODER_FINISHED;
474 }
475
476 return ANDROID_IMAGE_DECODER_INCOMPLETE;
477}
478
479int AImageDecoder_rewind(AImageDecoder* decoder) {
480 if (!decoder) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
481
482 ImageDecoder* imageDecoder = toDecoder(decoder);
483 if (!imageDecoder->isAnimated()) {
484 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
485 }
486
487 return imageDecoder->rewind() ? ANDROID_IMAGE_DECODER_SUCCESS
488 : ANDROID_IMAGE_DECODER_SEEK_ERROR;
489}
Leon Scroggins III06213132020-12-28 15:31:48 -0500490
491AImageDecoderFrameInfo* AImageDecoderFrameInfo_create() {
492 return reinterpret_cast<AImageDecoderFrameInfo*>(new SkCodec::FrameInfo);
493}
494
495static SkCodec::FrameInfo* toFrameInfo(AImageDecoderFrameInfo* info) {
496 return reinterpret_cast<SkCodec::FrameInfo*>(info);
497}
498
499static const SkCodec::FrameInfo* toFrameInfo(const AImageDecoderFrameInfo* info) {
500 return reinterpret_cast<const SkCodec::FrameInfo*>(info);
501}
502
503void AImageDecoderFrameInfo_delete(AImageDecoderFrameInfo* info) {
504 delete toFrameInfo(info);
505}
506
507int AImageDecoder_getFrameInfo(AImageDecoder* decoder,
508 AImageDecoderFrameInfo* info) {
509 if (!decoder || !info) {
510 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
511 }
512
513 auto* imageDecoder = toDecoder(decoder);
514 if (imageDecoder->finished()) {
515 return ANDROID_IMAGE_DECODER_FINISHED;
516 }
517
518 *toFrameInfo(info) = imageDecoder->getCurrentFrameInfo();
519 return ANDROID_IMAGE_DECODER_SUCCESS;
520}
521
522int64_t AImageDecoderFrameInfo_getDuration(const AImageDecoderFrameInfo* info) {
Leon Scroggins III6116e5c2021-05-03 11:34:34 -0400523 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III06213132020-12-28 15:31:48 -0500524
525 return toFrameInfo(info)->fDuration * 1'000'000;
526}
527
528ARect AImageDecoderFrameInfo_getFrameRect(const AImageDecoderFrameInfo* info) {
529 if (!info) {
530 return { 0, 0, 0, 0};
531 }
532
533 const SkIRect& r = toFrameInfo(info)->fFrameRect;
534 return { r.left(), r.top(), r.right(), r.bottom() };
535}
536
537bool AImageDecoderFrameInfo_hasAlphaWithinBounds(const AImageDecoderFrameInfo* info) {
538 if (!info) return false;
539
540 return toFrameInfo(info)->fHasAlphaWithinBounds;
541}
542
543int32_t AImageDecoderFrameInfo_getDisposeOp(const AImageDecoderFrameInfo* info) {
544 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
545
546 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kKeep)
547 == ANDROID_IMAGE_DECODER_DISPOSE_OP_NONE);
548 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestoreBGColor)
549 == ANDROID_IMAGE_DECODER_DISPOSE_OP_BACKGROUND);
550 static_assert(static_cast<int>(SkCodecAnimation::DisposalMethod::kRestorePrevious)
551 == ANDROID_IMAGE_DECODER_DISPOSE_OP_PREVIOUS);
552 return static_cast<int>(toFrameInfo(info)->fDisposalMethod);
553}
554
555int32_t AImageDecoderFrameInfo_getBlendOp(const AImageDecoderFrameInfo* info) {
556 if (!info) return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
557
558 switch (toFrameInfo(info)->fBlend) {
559 case SkCodecAnimation::Blend::kSrc:
560 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC;
561 case SkCodecAnimation::Blend::kSrcOver:
562 return ANDROID_IMAGE_DECODER_BLEND_OP_SRC_OVER;
563 }
564}
Leon Scroggins IIIc2ebc2b2021-01-13 09:46:06 -0500565
566void AImageDecoder_setInternallyHandleDisposePrevious(AImageDecoder* decoder, bool handle) {
567 if (decoder) {
568 toDecoder(decoder)->setHandleRestorePrevious(handle);
569 }
570}