blob: 79bcc15e1f0ffc7ba5de586a22353ef1d2b5c050 [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>
23#include <android/graphics/MimeType.h>
24#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>
31#include <optional>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <unistd.h>
35
36using namespace android;
37
38int ResultToErrorCode(SkCodec::Result result) {
39 switch (result) {
40 case SkCodec::kIncompleteInput:
41 return ANDROID_IMAGE_DECODER_INCOMPLETE;
42 case SkCodec::kErrorInInput:
43 return ANDROID_IMAGE_DECODER_ERROR;
44 case SkCodec::kInvalidInput:
45 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
46 case SkCodec::kCouldNotRewind:
47 return ANDROID_IMAGE_DECODER_SEEK_ERROR;
48 case SkCodec::kUnimplemented:
49 return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
50 case SkCodec::kInvalidConversion:
51 return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
52 case SkCodec::kInvalidParameters:
53 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
54 case SkCodec::kSuccess:
55 return ANDROID_IMAGE_DECODER_SUCCESS;
56 case SkCodec::kInvalidScale:
57 return ANDROID_IMAGE_DECODER_INVALID_SCALE;
58 case SkCodec::kInternalError:
59 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
60 }
61}
62
63static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
64 SkCodec::Result result;
65 auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
66 SkCodec::SelectionPolicy::kPreferAnimation);
67 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec),
68 SkAndroidCodec::ExifOrientationBehavior::kRespect);
69 if (!androidCodec) {
70 return ResultToErrorCode(result);
71 }
72
73 *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
74 return ANDROID_IMAGE_DECODER_SUCCESS;
75}
76
77int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
78 if (!asset || !outDecoder) {
79 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
80 }
81 *outDecoder = nullptr;
82
83 auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
84 return createFromStream(std::move(stream), outDecoder);
85}
86
87static bool isSeekable(int descriptor) {
88 return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
89}
90
91int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
92 if (fd <= 0 || !outDecoder) {
93 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
94 }
95
96 struct stat fdStat;
97 if (fstat(fd, &fdStat) == -1) {
98 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
99 }
100
101 if (!isSeekable(fd)) {
102 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
103 }
104
105 // SkFILEStream will close its descriptor. Duplicate it so the client will
106 // still be responsible for closing the original.
107 int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
108 FILE* file = fdopen(dupDescriptor, "r");
109 if (!file) {
110 close(dupDescriptor);
111 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
112 }
113
114 auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
115 return createFromStream(std::move(stream), outDecoder);
116}
117
118int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
119 AImageDecoder** outDecoder) {
120 if (!buffer || !length || !outDecoder) {
121 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
122 }
123 *outDecoder = nullptr;
124
125 // The client is expected to keep the buffer alive as long as the
126 // AImageDecoder, so we do not need to copy the buffer.
127 auto stream = std::unique_ptr<SkStreamRewindable>(
128 new SkMemoryStream(buffer, length, false /* copyData */));
129 return createFromStream(std::move(stream), outDecoder);
130}
131
132static ImageDecoder* toDecoder(AImageDecoder* d) {
133 return reinterpret_cast<ImageDecoder*>(d);
134}
135
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500136static const ImageDecoder* toDecoder(const AImageDecoder* d) {
137 return reinterpret_cast<const ImageDecoder*>(d);
138}
139
Leon Scroggins III407b5442019-11-22 17:10:20 -0500140// Note: This differs from the version in android_bitmap.cpp in that this
141// version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
142// allows decoding single channel images to gray, which Android then treats
143// as A_8/ALPHA_8.
144static SkColorType getColorType(AndroidBitmapFormat format) {
145 switch (format) {
146 case ANDROID_BITMAP_FORMAT_RGBA_8888:
147 return kN32_SkColorType;
148 case ANDROID_BITMAP_FORMAT_RGB_565:
149 return kRGB_565_SkColorType;
150 case ANDROID_BITMAP_FORMAT_RGBA_4444:
151 return kARGB_4444_SkColorType;
152 case ANDROID_BITMAP_FORMAT_A_8:
153 return kGray_8_SkColorType;
154 case ANDROID_BITMAP_FORMAT_RGBA_F16:
155 return kRGBA_F16_SkColorType;
156 default:
157 return kUnknown_SkColorType;
158 }
159}
160
161int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
162 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
163 || format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
164 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
165 }
166 return toDecoder(decoder)->setOutColorType(getColorType((AndroidBitmapFormat) format))
167 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
168}
169
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500170int AImageDecoder_setDataSpace(AImageDecoder* decoder, int32_t dataspace) {
171 sk_sp<SkColorSpace> cs = uirenderer::DataSpaceToColorSpace((android_dataspace)dataspace);
172 // 0 is ADATASPACE_UNKNOWN. We need an explicit request for an ADataSpace.
173 if (!decoder || !dataspace || !cs) {
174 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
175 }
176
177 ImageDecoder* imageDecoder = toDecoder(decoder);
178 imageDecoder->setOutColorSpace(std::move(cs));
179 return ANDROID_IMAGE_DECODER_SUCCESS;
180}
181
Leon Scroggins III407b5442019-11-22 17:10:20 -0500182const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
183 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
184}
185
186static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
187 return reinterpret_cast<const ImageDecoder*>(info);
188}
189
190int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
191 if (!info) {
192 return 0;
193 }
194 return toDecoder(info)->mCodec->getInfo().width();
195}
196
197int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
198 if (!info) {
199 return 0;
200 }
201 return toDecoder(info)->mCodec->getInfo().height();
202}
203
204const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
205 if (!info) {
206 return nullptr;
207 }
208 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
209}
210
Leon Scroggins IIIe5ace3f2020-01-15 15:31:40 -0500211int32_t AImageDecoderHeaderInfo_getDataSpace(const AImageDecoderHeaderInfo* info) {
212 if (!info) {
213 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
214 }
215
216 // Note: This recomputes the data space because it's possible the client has
217 // changed the output color space, so we cannot rely on it. Alternatively,
218 // we could store the ADataSpace in the ImageDecoder.
219 const ImageDecoder* imageDecoder = toDecoder(info);
220 SkColorType colorType = imageDecoder->mCodec->computeOutputColorType(kN32_SkColorType);
221 sk_sp<SkColorSpace> colorSpace = imageDecoder->mCodec->computeOutputColorSpace(colorType);
222 return uirenderer::ColorSpaceToADataSpace(colorSpace.get(), colorType);
223}
224
Leon Scroggins III407b5442019-11-22 17:10:20 -0500225// FIXME: Share with getFormat in android_bitmap.cpp?
226static AndroidBitmapFormat getFormat(SkColorType colorType) {
227 switch (colorType) {
228 case kN32_SkColorType:
229 return ANDROID_BITMAP_FORMAT_RGBA_8888;
230 case kRGB_565_SkColorType:
231 return ANDROID_BITMAP_FORMAT_RGB_565;
232 case kARGB_4444_SkColorType:
233 return ANDROID_BITMAP_FORMAT_RGBA_4444;
234 case kAlpha_8_SkColorType:
235 return ANDROID_BITMAP_FORMAT_A_8;
236 case kRGBA_F16_SkColorType:
237 return ANDROID_BITMAP_FORMAT_RGBA_F16;
238 default:
239 return ANDROID_BITMAP_FORMAT_NONE;
240 }
241}
242
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500243int32_t AImageDecoderHeaderInfo_getAndroidBitmapFormat(const AImageDecoderHeaderInfo* info) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500244 if (!info) {
245 return ANDROID_BITMAP_FORMAT_NONE;
246 }
247 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
248}
249
250int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
251 if (!info) {
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500252 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500253 }
254 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
255 case kUnknown_SkAlphaType:
256 LOG_ALWAYS_FATAL("Invalid alpha type");
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500257 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500258 case kUnpremul_SkAlphaType:
259 // fall through. premul is the default.
260 case kPremul_SkAlphaType:
261 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
262 case kOpaque_SkAlphaType:
263 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
264 }
265}
266
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500267int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
268 if (!decoder) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500269 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
270 }
271
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500272 return toDecoder(decoder)->setUnpremultipliedRequired(required)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500273 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
274}
275
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500276int AImageDecoder_setTargetSize(AImageDecoder* decoder, int32_t width, int32_t height) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500277 if (!decoder) {
278 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
279 }
280
281 return toDecoder(decoder)->setTargetSize(width, height)
282 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
283}
284
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500285int AImageDecoder_computeSampledSize(const AImageDecoder* decoder, int sampleSize,
Leon Scroggins III64301cb2020-01-23 09:47:47 -0500286 int32_t* width, int32_t* height) {
Leon Scroggins IIIf89de632020-01-19 21:22:18 -0500287 if (!decoder || !width || !height || sampleSize < 1) {
288 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
289 }
290
291 SkISize size = toDecoder(decoder)->mCodec->getSampledDimensions(sampleSize);
292 *width = size.width();
293 *height = size.height();
294 return ANDROID_IMAGE_DECODER_SUCCESS;
295}
296
Leon Scroggins III407b5442019-11-22 17:10:20 -0500297int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
298 if (!decoder) {
299 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
300 }
301
302 SkIRect cropIRect;
303 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
304 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
305 return toDecoder(decoder)->setCropRect(cropPtr)
306 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
307}
308
309
310size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
311 if (!decoder) {
312 return 0;
313 }
314
315 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
316 return info.minRowBytes();
317}
318
319int AImageDecoder_decodeImage(AImageDecoder* decoder,
320 void* pixels, size_t stride,
321 size_t size) {
322 if (!decoder || !pixels || !stride) {
323 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
324 }
325
326 ImageDecoder* imageDecoder = toDecoder(decoder);
327
328 const int height = imageDecoder->getOutputInfo().height();
329 const size_t minStride = AImageDecoder_getMinimumStride(decoder);
330 // If this calculation were to overflow, it would have been caught in
331 // setTargetSize.
332 if (stride < minStride || size < stride * (height - 1) + minStride) {
333 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
334 }
335
336 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
337}
338
339void AImageDecoder_delete(AImageDecoder* decoder) {
340 delete toDecoder(decoder);
341}