blob: 51439672d40488d58f46865fa7f0cf0c0b36046f [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>
21#include <android/imagedecoder.h>
22#include <android/graphics/MimeType.h>
23#include <android/rect.h>
24#include <hwui/ImageDecoder.h>
25#include <log/log.h>
26#include <SkAndroidCodec.h>
27
28#include <fcntl.h>
29#include <optional>
30#include <sys/stat.h>
31#include <sys/types.h>
32#include <unistd.h>
33
34using namespace android;
35
36int ResultToErrorCode(SkCodec::Result result) {
37 switch (result) {
38 case SkCodec::kIncompleteInput:
39 return ANDROID_IMAGE_DECODER_INCOMPLETE;
40 case SkCodec::kErrorInInput:
41 return ANDROID_IMAGE_DECODER_ERROR;
42 case SkCodec::kInvalidInput:
43 return ANDROID_IMAGE_DECODER_INVALID_INPUT;
44 case SkCodec::kCouldNotRewind:
45 return ANDROID_IMAGE_DECODER_SEEK_ERROR;
46 case SkCodec::kUnimplemented:
47 return ANDROID_IMAGE_DECODER_UNSUPPORTED_FORMAT;
48 case SkCodec::kInvalidConversion:
49 return ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
50 case SkCodec::kInvalidParameters:
51 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
52 case SkCodec::kSuccess:
53 return ANDROID_IMAGE_DECODER_SUCCESS;
54 case SkCodec::kInvalidScale:
55 return ANDROID_IMAGE_DECODER_INVALID_SCALE;
56 case SkCodec::kInternalError:
57 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
58 }
59}
60
61static int createFromStream(std::unique_ptr<SkStreamRewindable> stream, AImageDecoder** outDecoder) {
62 SkCodec::Result result;
63 auto codec = SkCodec::MakeFromStream(std::move(stream), &result, nullptr,
64 SkCodec::SelectionPolicy::kPreferAnimation);
65 auto androidCodec = SkAndroidCodec::MakeFromCodec(std::move(codec),
66 SkAndroidCodec::ExifOrientationBehavior::kRespect);
67 if (!androidCodec) {
68 return ResultToErrorCode(result);
69 }
70
71 *outDecoder = reinterpret_cast<AImageDecoder*>(new ImageDecoder(std::move(androidCodec)));
72 return ANDROID_IMAGE_DECODER_SUCCESS;
73}
74
75int AImageDecoder_createFromAAsset(AAsset* asset, AImageDecoder** outDecoder) {
76 if (!asset || !outDecoder) {
77 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
78 }
79 *outDecoder = nullptr;
80
81 auto stream = std::make_unique<AAssetStreamAdaptor>(asset);
82 return createFromStream(std::move(stream), outDecoder);
83}
84
85static bool isSeekable(int descriptor) {
86 return ::lseek64(descriptor, 0, SEEK_CUR) != -1;
87}
88
89int AImageDecoder_createFromFd(int fd, AImageDecoder** outDecoder) {
90 if (fd <= 0 || !outDecoder) {
91 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
92 }
93
94 struct stat fdStat;
95 if (fstat(fd, &fdStat) == -1) {
96 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
97 }
98
99 if (!isSeekable(fd)) {
100 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
101 }
102
103 // SkFILEStream will close its descriptor. Duplicate it so the client will
104 // still be responsible for closing the original.
105 int dupDescriptor = fcntl(fd, F_DUPFD_CLOEXEC, 0);
106 FILE* file = fdopen(dupDescriptor, "r");
107 if (!file) {
108 close(dupDescriptor);
109 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
110 }
111
112 auto stream = std::unique_ptr<SkStreamRewindable>(new SkFILEStream(file));
113 return createFromStream(std::move(stream), outDecoder);
114}
115
116int AImageDecoder_createFromBuffer(const void* buffer, size_t length,
117 AImageDecoder** outDecoder) {
118 if (!buffer || !length || !outDecoder) {
119 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
120 }
121 *outDecoder = nullptr;
122
123 // The client is expected to keep the buffer alive as long as the
124 // AImageDecoder, so we do not need to copy the buffer.
125 auto stream = std::unique_ptr<SkStreamRewindable>(
126 new SkMemoryStream(buffer, length, false /* copyData */));
127 return createFromStream(std::move(stream), outDecoder);
128}
129
130static ImageDecoder* toDecoder(AImageDecoder* d) {
131 return reinterpret_cast<ImageDecoder*>(d);
132}
133
134// Note: This differs from the version in android_bitmap.cpp in that this
135// version returns kGray_8_SkColorType for ANDROID_BITMAP_FORMAT_A_8. SkCodec
136// allows decoding single channel images to gray, which Android then treats
137// as A_8/ALPHA_8.
138static SkColorType getColorType(AndroidBitmapFormat format) {
139 switch (format) {
140 case ANDROID_BITMAP_FORMAT_RGBA_8888:
141 return kN32_SkColorType;
142 case ANDROID_BITMAP_FORMAT_RGB_565:
143 return kRGB_565_SkColorType;
144 case ANDROID_BITMAP_FORMAT_RGBA_4444:
145 return kARGB_4444_SkColorType;
146 case ANDROID_BITMAP_FORMAT_A_8:
147 return kGray_8_SkColorType;
148 case ANDROID_BITMAP_FORMAT_RGBA_F16:
149 return kRGBA_F16_SkColorType;
150 default:
151 return kUnknown_SkColorType;
152 }
153}
154
155int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
156 if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
157 || format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
158 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
159 }
160 return toDecoder(decoder)->setOutColorType(getColorType((AndroidBitmapFormat) format))
161 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
162}
163
164const AImageDecoderHeaderInfo* AImageDecoder_getHeaderInfo(const AImageDecoder* decoder) {
165 return reinterpret_cast<const AImageDecoderHeaderInfo*>(decoder);
166}
167
168static const ImageDecoder* toDecoder(const AImageDecoderHeaderInfo* info) {
169 return reinterpret_cast<const ImageDecoder*>(info);
170}
171
172int32_t AImageDecoderHeaderInfo_getWidth(const AImageDecoderHeaderInfo* info) {
173 if (!info) {
174 return 0;
175 }
176 return toDecoder(info)->mCodec->getInfo().width();
177}
178
179int32_t AImageDecoderHeaderInfo_getHeight(const AImageDecoderHeaderInfo* info) {
180 if (!info) {
181 return 0;
182 }
183 return toDecoder(info)->mCodec->getInfo().height();
184}
185
186const char* AImageDecoderHeaderInfo_getMimeType(const AImageDecoderHeaderInfo* info) {
187 if (!info) {
188 return nullptr;
189 }
190 return getMimeType(toDecoder(info)->mCodec->getEncodedFormat());
191}
192
193bool AImageDecoderHeaderInfo_isAnimated(const AImageDecoderHeaderInfo* info) {
194 if (!info) {
195 return false;
196 }
197 return toDecoder(info)->mCodec->codec()->getFrameCount() > 1;
198}
199
200// FIXME: Share with getFormat in android_bitmap.cpp?
201static AndroidBitmapFormat getFormat(SkColorType colorType) {
202 switch (colorType) {
203 case kN32_SkColorType:
204 return ANDROID_BITMAP_FORMAT_RGBA_8888;
205 case kRGB_565_SkColorType:
206 return ANDROID_BITMAP_FORMAT_RGB_565;
207 case kARGB_4444_SkColorType:
208 return ANDROID_BITMAP_FORMAT_RGBA_4444;
209 case kAlpha_8_SkColorType:
210 return ANDROID_BITMAP_FORMAT_A_8;
211 case kRGBA_F16_SkColorType:
212 return ANDROID_BITMAP_FORMAT_RGBA_F16;
213 default:
214 return ANDROID_BITMAP_FORMAT_NONE;
215 }
216}
217
218AndroidBitmapFormat AImageDecoderHeaderInfo_getAndroidBitmapFormat(
219 const AImageDecoderHeaderInfo* info) {
220 if (!info) {
221 return ANDROID_BITMAP_FORMAT_NONE;
222 }
223 return getFormat(toDecoder(info)->mCodec->computeOutputColorType(kN32_SkColorType));
224}
225
226int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) {
227 if (!info) {
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500228 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500229 }
230 switch (toDecoder(info)->mCodec->getInfo().alphaType()) {
231 case kUnknown_SkAlphaType:
232 LOG_ALWAYS_FATAL("Invalid alpha type");
Leon Scroggins IIId8840bd2020-01-15 04:09:48 -0500233 return ANDROID_IMAGE_DECODER_INTERNAL_ERROR;
Leon Scroggins III407b5442019-11-22 17:10:20 -0500234 case kUnpremul_SkAlphaType:
235 // fall through. premul is the default.
236 case kPremul_SkAlphaType:
237 return ANDROID_BITMAP_FLAGS_ALPHA_PREMUL;
238 case kOpaque_SkAlphaType:
239 return ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE;
240 }
241}
242
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500243int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) {
244 if (!decoder) {
Leon Scroggins III407b5442019-11-22 17:10:20 -0500245 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
246 }
247
Leon Scroggins III1ade46d2020-01-15 05:41:06 -0500248 return toDecoder(decoder)->setUnpremultipliedRequired(required)
Leon Scroggins III407b5442019-11-22 17:10:20 -0500249 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION;
250}
251
252int AImageDecoder_setTargetSize(AImageDecoder* decoder, int width, int height) {
253 if (!decoder) {
254 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
255 }
256
257 return toDecoder(decoder)->setTargetSize(width, height)
258 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_SCALE;
259}
260
261int AImageDecoder_setCrop(AImageDecoder* decoder, ARect crop) {
262 if (!decoder) {
263 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
264 }
265
266 SkIRect cropIRect;
267 cropIRect.setLTRB(crop.left, crop.top, crop.right, crop.bottom);
268 SkIRect* cropPtr = cropIRect == SkIRect::MakeEmpty() ? nullptr : &cropIRect;
269 return toDecoder(decoder)->setCropRect(cropPtr)
270 ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_BAD_PARAMETER;
271}
272
273
274size_t AImageDecoder_getMinimumStride(AImageDecoder* decoder) {
275 if (!decoder) {
276 return 0;
277 }
278
279 SkImageInfo info = toDecoder(decoder)->getOutputInfo();
280 return info.minRowBytes();
281}
282
283int AImageDecoder_decodeImage(AImageDecoder* decoder,
284 void* pixels, size_t stride,
285 size_t size) {
286 if (!decoder || !pixels || !stride) {
287 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
288 }
289
290 ImageDecoder* imageDecoder = toDecoder(decoder);
291
292 const int height = imageDecoder->getOutputInfo().height();
293 const size_t minStride = AImageDecoder_getMinimumStride(decoder);
294 // If this calculation were to overflow, it would have been caught in
295 // setTargetSize.
296 if (stride < minStride || size < stride * (height - 1) + minStride) {
297 return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
298 }
299
300 return ResultToErrorCode(imageDecoder->decode(pixels, stride));
301}
302
303void AImageDecoder_delete(AImageDecoder* decoder) {
304 delete toDecoder(decoder);
305}