blob: 56f390698eb2abd7fd713309e44b89d0fd55151b [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
64static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
65 SkCodec::Result result;
66 auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
67 SkCodec::SelectionPolicy::kPreferAnimation);
68 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec),
69 SkAndroidCodec::ExifOrientationBehavior::kRespect);
70 if (!androidCodec) {
71 return ResultToErrorCode(result);
72 }
73
Leon Scroggins III2e6bedf2020-02-11 16:31:21 -050074 // AImageDecoderHeaderInfo_getWidth/Height return an int32_t. Ensure that
75 // the conversion is safe.
76 const auto& info = androidCodec->getInfo();
77 if (info.width() > std::numeric_limits<int32_t>::max()
78 || info.height() > std::numeric_limits<int32_t>::max()) {
79 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
80 }
81
Leon Scroggins III407b5442019-11-22 17:10:20 -050082 *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
83 return ANDROID_IMAGE_DECODER_SUCCESS;
84}
85
86int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
87 if (!asset || !outDecoder) {
88 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
89 }
90 *outDecoder = nullptr;
91
92 auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
93 return createFromStream(std::move(stream), outDecoder);
94}
95
96static bool isSeekable(int descriptor) {
97 return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
98}
99
100int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
101 if (fd <= 0 || !outDecoder) {
102 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
103 }
104
105 struct stat fdStat;
106 if (fstat(fd, &fdStat) == -1) {
107 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
108 }
109
110 if (!isSeekable(fd)) {
111 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
112 }
113
114 // SkFILEStream will close its descriptor. Duplicate it so the client will
115 // still be responsible for closing the original.
116 int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
117 FILE* file = fdopen(dupDescriptor, "r");
118 if (!file) {
119 close(dupDescriptor);
120 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
121 }
122
123 auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
124 return createFromStream(std::move(stream), outDecoder);
125}
126
127int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
128 AImageDecoder** outDecoder) {
129 if (!buffer || !length || !outDecoder) {
130 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
131 }
132 *outDecoder = nullptr;
133
134 // The client is expected to keep the buffer alive as long as the
135 // AImageDecoder, so we do not need to copy the buffer.
136 auto stream = std::unique_ptr<SkStreamRewindable>(
137 new SkMemoryStream(buffer, length, false /* copyData */));
138 return createFromStream(std::move(stream), outDecoder);
139}
140
141static ImageDecoder* toDecoder(AImageDecoder* d) {
142 return reinterpret_cast<ImageDecoder*>(d);
143}
144
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500145static const ImageDecoder* toDecoder(const AImageDecoder* d) {
146 return reinterpret_cast<const ImageDecoder*>(d);
147}
148
Leon Scroggins III407b5442019-11-22 17:10:20 -0500149// Note: This differs from the version in android_bitmap.cpp in that this
150// version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
151// allows decoding single channel images to gray, which Android then treats
152// as A_8/ALPHA_8.
153static SkColorType getColorType(AndroidBitmapFormat format) {
154 switch (format) {
155 case ANDROID_BITMAP_FORMAT_RGBA_8888:
156 return kN32_SkColorType;
157 case ANDROID_BITMAP_FORMAT_RGB_565:
158 return kRGB_565_SkColorType;
159 case ANDROID_BITMAP_FORMAT_RGBA_4444:
160 return kARGB_4444_SkColorType;
161 case ANDROID_BITMAP_FORMAT_A_8:
162 return kGray_8_SkColorType;
163 case ANDROID_BITMAP_FORMAT_RGBA_F16:
164 return kRGBA_F16_SkColorType;
165 default:
166 return kUnknown_SkColorType;
167 }
168}
169
170int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
171 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
172 || format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
173 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
174 }
175 return toDecoder(decoder)->setOutColorType(getColorType((AndroidBitmapFormat) format))
176 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
177}
178
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500179int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
180 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
181 // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
182 if (!decoder || !dataspace || !cs) {
183 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
184 }
185
186 ImageDecoder* imageDecoder = toDecoder(decoder);
187 imageDecoder->setOutColorSpace(std::move(cs));
188 return ANDROID_IMAGE_DECODER_SUCCESS;
189}
190
Leon Scroggins III407b5442019-11-22 17:10:20 -0500191const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
192 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
193}
194
195static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
196 return reinterpret_cast<const ImageDecoder*>(info);
197}
198
199int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
200 if (!info) {
201 return 0;
202 }
203 return toDecoder(info)->mCodec->getInfo().width();
204}
205
206int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
207 if (!info) {
208 return 0;
209 }
210 return toDecoder(info)->mCodec->getInfo().height();
211}
212
213const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
214 if (!info) {
215 return nullptr;
216 }
217 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
218}
219
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500220int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
221 if (!info) {
222 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
223 }
224
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500225 // Note: This recomputes the color type because it's possible the client has
226 // changed the output color type, so we cannot rely on it. Alternatively,
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500227 // we could store the ADataSpace in the ImageDecoder.
228 const ImageDecoder* imageDecoder = toDecoder(info);
229 SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
Leon Scroggins III6eeca5c2020-01-30 13:59:50 -0500230 sk_sp<SkColorSpace> colorSpace = imageDecoder->getDefaultColorSpace();
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500231 return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
232}
233
Leon Scroggins III407b5442019-11-22 17:10:20 -0500234// FIXME: Share with getFormat in android_bitmap.cpp?
235static AndroidBitmapFormat getFormat(SkColorType colorType) {
236 switch (colorType) {
237 case kN32_SkColorType:
238 return ANDROID_BITMAP_FORMAT_RGBA_8888;
239 case kRGB_565_SkColorType:
240 return ANDROID_BITMAP_FORMAT_RGB_565;
241 case kARGB_4444_SkColorType:
242 return ANDROID_BITMAP_FORMAT_RGBA_4444;
243 case kAlpha_8_SkColorType:
244 return ANDROID_BITMAP_FORMAT_A_8;
245 case kRGBA_F16_SkColorType:
246 return ANDROID_BITMAP_FORMAT_RGBA_F16;
247 default:
248 return ANDROID_BITMAP_FORMAT_NONE;
249 }
250}
251
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500252int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500253 if (!info) {
254 return ANDROID_BITMAP_FORMAT_NONE;
255 }
256 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
257}
258
259int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
260 if (!info) {
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500261 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500262 }
263 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
264 case kUnknown_SkAlphaType:
265 LOG_ALWAYS_FATAL("Invalid alpha type");
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500266 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500267 case kUnpremul_SkAlphaType:
268 // fall through. premul is the default.
269 case kPremul_SkAlphaType:
270 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
271 case kOpaque_SkAlphaType:
272 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
273 }
274}
275
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500276int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
277 if (!decoder) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500278 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
279 }
280
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500281 return toDecoder(decoder)->setUnpremultipliedRequired(required)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500282 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
283}
284
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500285int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500286 if (!decoder) {
287 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
288 }
289
290 return toDecoder(decoder)->setTargetSize(width, height)
291 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
292}
293
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500294int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500295 int32_t* width, int32_t* height) {
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500296 if (!decoder || !width || !height || sampleSize < 1) {
297 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
298 }
299
300 SkISize size = toDecoder(decoder)->mCodec->getSampledDimensions(sampleSize);
301 *width = size.width();
302 *height = size.height();
303 return ANDROID_IMAGE_DECODER_SUCCESS;
304}
305
Leon Scroggins III407b5442019-11-22 17:10:20 -0500306int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
307 if (!decoder) {
308 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
309 }
310
311 SkIRect cropIRect;
312 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
313 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
314 return toDecoder(decoder)->setCropRect(cropPtr)
315 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
316}
317
318
319size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
320 if (!decoder) {
321 return 0;
322 }
323
324 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
325 return info.minRowBytes();
326}
327
328int AImageDecoder_decodeImage(AImageDecoder* decoder,
329 void* pixels, size_t stride,
330 size_t size) {
331 if (!decoder || !pixels || !stride) {
332 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
333 }
334
335 ImageDecoder* imageDecoder = toDecoder(decoder);
336
Leon Scroggins IIId894c592020-01-22 14:18:12 -0500337 SkImageInfo info = imageDecoder->getOutputInfo();
338 size_t minSize = info.computeByteSize(stride);
339 if (SkImageInfo::ByteSizeOverflowed(minSize) || size < minSize || !info.validRowBytes(stride)) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500340 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
341 }
342
343 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
344}
345
346void AImageDecoder_delete(AImageDecoder* decoder) {
347 delete toDecoder(decoder);
348}