1 /*
2 * Copyright (C) 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 "ImageDecoder.h"
18
19 #include <Gainmap.h>
20 #include <SkAlphaType.h>
21 #include <SkAndroidCodec.h>
22 #include <SkBitmap.h>
23 #include <SkBlendMode.h>
24 #include <SkCanvas.h>
25 #include <SkCodec.h>
26 #include <SkCodecAnimation.h>
27 #include <SkColorSpace.h>
28 #include <SkColorType.h>
29 #include <SkEncodedOrigin.h>
30 #include <SkImageInfo.h>
31 #include <SkGainmapInfo.h>
32 #include <SkMatrix.h>
33 #include <SkPaint.h>
34 #include <SkPngChunkReader.h>
35 #include <SkRect.h>
36 #include <SkRefCnt.h>
37 #include <SkSamplingOptions.h>
38 #include <SkSize.h>
39 #include <SkStream.h>
40 #include <hwui/Bitmap.h>
41 #include <log/log.h>
42 #include <utils/Trace.h>
43
44 #include <memory>
45
46 using namespace android;
47
getDefaultColorSpace() const48 sk_sp<SkColorSpace> ImageDecoder::getDefaultColorSpace() const {
49 const skcms_ICCProfile* encodedProfile = mCodec->getICCProfile();
50 if (encodedProfile) {
51 if (encodedProfile->has_CICP) {
52 return mCodec->computeOutputColorSpace(kN32_SkColorType);
53 }
54 // If the profile maps directly to an SkColorSpace, that SkColorSpace
55 // will be returned. Otherwise, nullptr will be returned. In either
56 // case, using this SkColorSpace results in doing no color correction.
57 return SkColorSpace::Make(*encodedProfile);
58 }
59
60 // The image has no embedded color profile, and should be treated as SRGB.
61 return SkColorSpace::MakeSRGB();
62 }
63
ImageDecoder(std::unique_ptr<SkAndroidCodec> codec,sk_sp<SkPngChunkReader> peeker,SkCodec::ZeroInitialized zeroInit)64 ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChunkReader> peeker,
65 SkCodec::ZeroInitialized zeroInit)
66 : mCodec(std::move(codec))
67 , mPeeker(std::move(peeker))
68 , mDecodeSize(mCodec->codec()->dimensions())
69 , mOutColorType(mCodec->computeOutputColorType(kN32_SkColorType))
70 , mUnpremultipliedRequired(false)
71 , mOutColorSpace(getDefaultColorSpace())
72 , mHandleRestorePrevious(true)
73 {
74 mTargetSize = swapWidthHeight() ? SkISize { mDecodeSize.height(), mDecodeSize.width() }
75 : mDecodeSize;
76 this->rewind();
77 mOptions.fZeroInitialized = zeroInit;
78 }
79
80 ImageDecoder::~ImageDecoder() = default;
81
getOutAlphaType() const82 SkAlphaType ImageDecoder::getOutAlphaType() const {
83 return opaque() ? kOpaque_SkAlphaType
84 : mUnpremultipliedRequired ? kUnpremul_SkAlphaType : kPremul_SkAlphaType;
85 }
86
swapped(const SkISize & size)87 static SkISize swapped(const SkISize& size) {
88 return SkISize { size.height(), size.width() };
89 }
90
requires_matrix_scaling(bool swapWidthHeight,const SkISize & decodeSize,const SkISize & targetSize)91 static bool requires_matrix_scaling(bool swapWidthHeight, const SkISize& decodeSize,
92 const SkISize& targetSize) {
93 return (swapWidthHeight && decodeSize != swapped(targetSize))
94 || (!swapWidthHeight && decodeSize != targetSize);
95 }
96
getSampledDimensions(int sampleSize) const97 SkISize ImageDecoder::getSampledDimensions(int sampleSize) const {
98 auto size = mCodec->getSampledDimensions(sampleSize);
99 return swapWidthHeight() ? swapped(size) : size;
100 }
101
setTargetSize(int width,int height)102 bool ImageDecoder::setTargetSize(int width, int height) {
103 if (width <= 0 || height <= 0) {
104 return false;
105 }
106
107 auto info = SkImageInfo::Make(width, height, mOutColorType, getOutAlphaType());
108 size_t rowBytes = info.minRowBytes();
109 if (rowBytes == 0) {
110 // This would have overflowed.
111 return false;
112 }
113
114 size_t pixelMemorySize;
115 if (!Bitmap::computeAllocationSize(rowBytes, height, &pixelMemorySize)) {
116 return false;
117 }
118
119 if (mCropRect) {
120 if (mCropRect->right() > width || mCropRect->bottom() > height) {
121 return false;
122 }
123 }
124
125 const bool swap = swapWidthHeight();
126 const SkISize targetSize = { width, height };
127 SkISize decodeSize = swap ? SkISize { height, width } : targetSize;
128 int sampleSize = mCodec->computeSampleSize(&decodeSize);
129
130 if (mUnpremultipliedRequired && !opaque()) {
131 // Allow using a matrix to handle orientation, but not scaling.
132 if (requires_matrix_scaling(swap, decodeSize, targetSize)) {
133 return false;
134 }
135 }
136
137 mTargetSize = targetSize;
138 mDecodeSize = decodeSize;
139 mOptions.fSampleSize = sampleSize;
140 return true;
141 }
142
setCropRect(const SkIRect * crop)143 bool ImageDecoder::setCropRect(const SkIRect* crop) {
144 if (!crop) {
145 mCropRect.reset();
146 return true;
147 }
148
149 if (crop->left() >= crop->right() || crop->top() >= crop->bottom()) {
150 return false;
151 }
152
153 const auto& size = mTargetSize;
154 if (crop->left() < 0 || crop->top() < 0
155 || crop->right() > size.width() || crop->bottom() > size.height()) {
156 return false;
157 }
158
159 mCropRect.emplace(*crop);
160 return true;
161 }
162
setOutColorType(SkColorType colorType)163 bool ImageDecoder::setOutColorType(SkColorType colorType) {
164 switch (colorType) {
165 case kRGB_565_SkColorType:
166 if (!opaque()) {
167 return false;
168 }
169 break;
170 case kGray_8_SkColorType:
171 if (!gray()) {
172 return false;
173 }
174 break;
175 case kN32_SkColorType:
176 break;
177 case kRGBA_F16_SkColorType:
178 break;
179 case kRGBA_1010102_SkColorType:
180 break;
181 default:
182 return false;
183 }
184
185 mOutColorType = colorType;
186 return true;
187 }
188
setUnpremultipliedRequired(bool required)189 bool ImageDecoder::setUnpremultipliedRequired(bool required) {
190 if (required && !opaque()) {
191 if (requires_matrix_scaling(swapWidthHeight(), mDecodeSize, mTargetSize)) {
192 return false;
193 }
194 }
195 mUnpremultipliedRequired = required;
196 return true;
197 }
198
setOutColorSpace(sk_sp<SkColorSpace> colorSpace)199 void ImageDecoder::setOutColorSpace(sk_sp<SkColorSpace> colorSpace) {
200 mOutColorSpace = std::move(colorSpace);
201 }
202
getOutputColorSpace() const203 sk_sp<SkColorSpace> ImageDecoder::getOutputColorSpace() const {
204 // kGray_8 is used for ALPHA_8, which ignores the color space.
205 return mOutColorType == kGray_8_SkColorType ? nullptr : mOutColorSpace;
206 }
207
208
getOutputInfo() const209 SkImageInfo ImageDecoder::getOutputInfo() const {
210 SkISize size = mCropRect ? mCropRect->size() : mTargetSize;
211 return SkImageInfo::Make(size, mOutColorType, getOutAlphaType(), getOutputColorSpace());
212 }
213
swapWidthHeight() const214 bool ImageDecoder::swapWidthHeight() const {
215 return SkEncodedOriginSwapsWidthHeight(getOrigin());
216 }
217
width() const218 int ImageDecoder::width() const {
219 return swapWidthHeight()
220 ? mCodec->codec()->dimensions().height()
221 : mCodec->codec()->dimensions().width();
222 }
223
height() const224 int ImageDecoder::height() const {
225 return swapWidthHeight()
226 ? mCodec->codec()->dimensions().width()
227 : mCodec->codec()->dimensions().height();
228 }
229
opaque() const230 bool ImageDecoder::opaque() const {
231 return mCurrentFrameIsOpaque;
232 }
233
gray() const234 bool ImageDecoder::gray() const {
235 return mCodec->getInfo().colorType() == kGray_8_SkColorType;
236 }
237
isAnimated()238 bool ImageDecoder::isAnimated() {
239 return mCodec->codec()->getFrameCount() > 1;
240 }
241
currentFrame() const242 int ImageDecoder::currentFrame() const {
243 return mOptions.fFrameIndex;
244 }
245
rewind()246 bool ImageDecoder::rewind() {
247 mOptions.fFrameIndex = 0;
248 mOptions.fPriorFrame = SkCodec::kNoFrame;
249 mCurrentFrameIsIndependent = true;
250 mCurrentFrameIsOpaque = mCodec->getInfo().isOpaque();
251 mRestoreState = RestoreState::kDoNothing;
252 mRestoreFrame = nullptr;
253
254 // TODO: Rewind the input now instead of in the next call to decode, and
255 // plumb through whether rewind succeeded.
256 return true;
257 }
258
setHandleRestorePrevious(bool handle)259 void ImageDecoder::setHandleRestorePrevious(bool handle) {
260 mHandleRestorePrevious = handle;
261 if (!handle) {
262 mRestoreFrame = nullptr;
263 }
264 }
265
advanceFrame()266 bool ImageDecoder::advanceFrame() {
267 const int frameIndex = ++mOptions.fFrameIndex;
268 const int frameCount = mCodec->codec()->getFrameCount();
269 if (frameIndex >= frameCount) {
270 // Prevent overflow from repeated calls to advanceFrame.
271 mOptions.fFrameIndex = frameCount;
272 return false;
273 }
274
275 SkCodec::FrameInfo frameInfo;
276 if (!mCodec->codec()->getFrameInfo(frameIndex, &frameInfo)
277 || !frameInfo.fFullyReceived) {
278 // Mark the decoder as finished, requiring a rewind.
279 mOptions.fFrameIndex = frameCount;
280 return false;
281 }
282
283 mCurrentFrameIsIndependent = frameInfo.fRequiredFrame == SkCodec::kNoFrame;
284 mCurrentFrameIsOpaque = frameInfo.fAlphaType == kOpaque_SkAlphaType;
285
286 if (frameInfo.fDisposalMethod == SkCodecAnimation::DisposalMethod::kRestorePrevious) {
287 switch (mRestoreState) {
288 case RestoreState::kDoNothing:
289 case RestoreState::kNeedsRestore:
290 mRestoreState = RestoreState::kFirstRPFrame;
291 mOptions.fPriorFrame = frameIndex - 1;
292 break;
293 case RestoreState::kFirstRPFrame:
294 mRestoreState = RestoreState::kRPFrame;
295 break;
296 case RestoreState::kRPFrame:
297 // Unchanged.
298 break;
299 }
300 } else { // New frame is not restore previous
301 switch (mRestoreState) {
302 case RestoreState::kFirstRPFrame:
303 case RestoreState::kRPFrame:
304 mRestoreState = RestoreState::kNeedsRestore;
305 break;
306 case RestoreState::kNeedsRestore:
307 mRestoreState = RestoreState::kDoNothing;
308 mRestoreFrame = nullptr;
309 [[fallthrough]];
310 case RestoreState::kDoNothing:
311 mOptions.fPriorFrame = frameIndex - 1;
312 break;
313 }
314 }
315
316 return true;
317 }
318
getCurrentFrameInfo()319 SkCodec::FrameInfo ImageDecoder::getCurrentFrameInfo() {
320 LOG_ALWAYS_FATAL_IF(finished());
321
322 auto dims = mCodec->codec()->dimensions();
323 SkCodec::FrameInfo info;
324 if (!mCodec->codec()->getFrameInfo(mOptions.fFrameIndex, &info)) {
325 // SkCodec may return false for a non-animated image. Provide defaults.
326 info.fRequiredFrame = SkCodec::kNoFrame;
327 info.fDuration = 0;
328 info.fFullyReceived = true;
329 info.fAlphaType = mCodec->codec()->getInfo().alphaType();
330 info.fHasAlphaWithinBounds = info.fAlphaType != kOpaque_SkAlphaType;
331 info.fDisposalMethod = SkCodecAnimation::DisposalMethod::kKeep;
332 info.fBlend = SkCodecAnimation::Blend::kSrc;
333 info.fFrameRect = SkIRect::MakeSize(dims);
334 }
335
336 if (auto origin = getOrigin(); origin != kDefault_SkEncodedOrigin) {
337 if (SkEncodedOriginSwapsWidthHeight(origin)) {
338 dims = swapped(dims);
339 }
340 auto matrix = SkEncodedOriginToMatrix(origin, dims.width(), dims.height());
341 auto rect = SkRect::Make(info.fFrameRect);
342 LOG_ALWAYS_FATAL_IF(!matrix.mapRect(&rect));
343 rect.roundIn(&info.fFrameRect);
344 }
345 return info;
346 }
347
finished() const348 bool ImageDecoder::finished() const {
349 return mOptions.fFrameIndex >= mCodec->codec()->getFrameCount();
350 }
351
handleRestorePrevious(const SkImageInfo & outputInfo,void * pixels,size_t rowBytes)352 bool ImageDecoder::handleRestorePrevious(const SkImageInfo& outputInfo, void* pixels,
353 size_t rowBytes) {
354 if (!mHandleRestorePrevious) {
355 return true;
356 }
357
358 switch (mRestoreState) {
359 case RestoreState::kFirstRPFrame:{
360 // This frame is marked kRestorePrevious. The prior frame should be in
361 // |pixels|, and it is what we'll restore after each consecutive
362 // kRestorePrevious frame. Cache it now.
363 if (!(mRestoreFrame = Bitmap::allocateHeapBitmap(outputInfo))) {
364 return false;
365 }
366
367 const uint8_t* srcRow = static_cast<uint8_t*>(pixels);
368 uint8_t* dstRow = static_cast<uint8_t*>(mRestoreFrame->pixels());
369 for (int y = 0; y < outputInfo.height(); y++) {
370 memcpy(dstRow, srcRow, outputInfo.minRowBytes());
371 srcRow += rowBytes;
372 dstRow += mRestoreFrame->rowBytes();
373 }
374 break;
375 }
376 case RestoreState::kRPFrame:
377 case RestoreState::kNeedsRestore:
378 // Restore the cached frame. It's possible that the client skipped decoding a frame, so
379 // we never cached it.
380 if (mRestoreFrame) {
381 const uint8_t* srcRow = static_cast<uint8_t*>(mRestoreFrame->pixels());
382 uint8_t* dstRow = static_cast<uint8_t*>(pixels);
383 for (int y = 0; y < outputInfo.height(); y++) {
384 memcpy(dstRow, srcRow, outputInfo.minRowBytes());
385 srcRow += mRestoreFrame->rowBytes();
386 dstRow += rowBytes;
387 }
388 }
389 break;
390 case RestoreState::kDoNothing:
391 break;
392 }
393 return true;
394 }
395
decode(void * pixels,size_t rowBytes)396 SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) {
397 // This was checked inside setTargetSize, but it's possible the first frame
398 // was opaque, so that method succeeded, but after calling advanceFrame, the
399 // current frame is not opaque.
400 if (mUnpremultipliedRequired && !opaque()) {
401 // Allow using a matrix to handle orientation, but not scaling.
402 if (requires_matrix_scaling(swapWidthHeight(), mDecodeSize, mTargetSize)) {
403 return SkCodec::kInvalidScale;
404 }
405 }
406
407 const auto outputInfo = getOutputInfo();
408 if (!handleRestorePrevious(outputInfo, pixels, rowBytes)) {
409 return SkCodec::kInternalError;
410 }
411
412 void* decodePixels = pixels;
413 size_t decodeRowBytes = rowBytes;
414 const auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, getOutAlphaType(),
415 getOutputColorSpace());
416 // Used if we need a temporary before scaling or subsetting.
417 // FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380.
418 SkBitmap tmp;
419 const bool scale = mDecodeSize != mTargetSize;
420 const auto origin = getOrigin();
421 const bool handleOrigin = origin != kDefault_SkEncodedOrigin;
422 SkMatrix outputMatrix;
423 if (scale || handleOrigin || mCropRect) {
424 if (mCropRect) {
425 outputMatrix.setTranslate(-mCropRect->fLeft, -mCropRect->fTop);
426 }
427
428 int targetWidth = mTargetSize.width();
429 int targetHeight = mTargetSize.height();
430 if (handleOrigin) {
431 outputMatrix.preConcat(SkEncodedOriginToMatrix(origin, targetWidth, targetHeight));
432 if (SkEncodedOriginSwapsWidthHeight(origin)) {
433 std::swap(targetWidth, targetHeight);
434 }
435 }
436 if (scale) {
437 float scaleX = (float) targetWidth / mDecodeSize.width();
438 float scaleY = (float) targetHeight / mDecodeSize.height();
439 outputMatrix.preScale(scaleX, scaleY);
440 }
441 // It's possible that this portion *does* have alpha, even if the
442 // composed frame does not. In that case, the SkBitmap needs to have
443 // alpha so it blends properly.
444 if (!tmp.setInfo(decodeInfo.makeAlphaType(mUnpremultipliedRequired ? kUnpremul_SkAlphaType
445 : kPremul_SkAlphaType)))
446 {
447 return SkCodec::kInternalError;
448 }
449 if (!Bitmap::allocateHeapBitmap(&tmp)) {
450 return SkCodec::kInternalError;
451 }
452 decodePixels = tmp.getPixels();
453 decodeRowBytes = tmp.rowBytes();
454
455 if (!mCurrentFrameIsIndependent) {
456 SkMatrix inverse;
457 if (outputMatrix.invert(&inverse)) {
458 SkCanvas canvas(tmp, SkCanvas::ColorBehavior::kLegacy);
459 canvas.setMatrix(inverse);
460 SkBitmap priorFrame;
461 priorFrame.installPixels(outputInfo, pixels, rowBytes);
462 priorFrame.setImmutable(); // Don't want asImage() to force a copy
463 canvas.drawImage(priorFrame.asImage(), 0, 0,
464 SkSamplingOptions(SkFilterMode::kLinear));
465 } else {
466 ALOGE("Failed to invert matrix!");
467 }
468 }
469
470 // Even if the client did not provide zero initialized memory, the
471 // memory we decode into is.
472 mOptions.fZeroInitialized = SkCodec::kYes_ZeroInitialized;
473 }
474
475 ATRACE_BEGIN("getAndroidPixels");
476 auto result = mCodec->getAndroidPixels(decodeInfo, decodePixels, decodeRowBytes, &mOptions);
477 ATRACE_END();
478
479 // The next call to decode() may not provide zero initialized memory.
480 mOptions.fZeroInitialized = SkCodec::kNo_ZeroInitialized;
481
482 if (scale || handleOrigin || mCropRect) {
483 ATRACE_NAME("Handling scale/origin/crop");
484 SkBitmap scaledBm;
485 if (!scaledBm.installPixels(outputInfo, pixels, rowBytes)) {
486 return SkCodec::kInternalError;
487 }
488
489 SkPaint paint;
490 paint.setBlendMode(SkBlendMode::kSrc);
491
492 SkCanvas canvas(scaledBm, SkCanvas::ColorBehavior::kLegacy);
493 canvas.setMatrix(outputMatrix);
494 tmp.setImmutable(); // Don't want asImage() to force copy
495 canvas.drawImage(tmp.asImage(), 0, 0, SkSamplingOptions(SkFilterMode::kLinear), &paint);
496 }
497
498 return result;
499 }
500
extractGainmap(Bitmap * destination,bool isShared)501 SkCodec::Result ImageDecoder::extractGainmap(Bitmap* destination, bool isShared) {
502 ATRACE_CALL();
503 SkGainmapInfo gainmapInfo;
504 std::unique_ptr<SkStream> gainmapStream;
505 {
506 ATRACE_NAME("getAndroidGainmap");
507 if (!mCodec->getAndroidGainmap(&gainmapInfo, &gainmapStream)) {
508 return SkCodec::kSuccess;
509 }
510 }
511 auto gainmapCodec = SkAndroidCodec::MakeFromStream(std::move(gainmapStream));
512 if (!gainmapCodec) {
513 ALOGW("Failed to create codec for gainmap stream");
514 return SkCodec::kInvalidInput;
515 }
516 ImageDecoder decoder{std::move(gainmapCodec)};
517 // Gainmap inherits the origin of the containing image
518 decoder.mOverrideOrigin.emplace(getOrigin());
519 // Update mDecodeSize / mTargetSize for the overridden origin
520 decoder.setTargetSize(decoder.width(), decoder.height());
521 if (decoder.gray()) {
522 decoder.setOutColorType(kGray_8_SkColorType);
523 }
524
525 const bool isScaled = width() != mTargetSize.width() || height() != mTargetSize.height();
526
527 if (isScaled) {
528 float scaleX = (float)mTargetSize.width() / width();
529 float scaleY = (float)mTargetSize.height() / height();
530 decoder.setTargetSize(decoder.width() * scaleX, decoder.height() * scaleY);
531 }
532
533 if (mCropRect) {
534 float sX = decoder.mTargetSize.width() / (float)mTargetSize.width();
535 float sY = decoder.mTargetSize.height() / (float)mTargetSize.height();
536 SkIRect crop = *mCropRect;
537 // TODO: Tweak rounding?
538 crop.fLeft *= sX;
539 crop.fRight *= sX;
540 crop.fTop *= sY;
541 crop.fBottom *= sY;
542 decoder.setCropRect(&crop);
543 }
544
545 SkImageInfo bitmapInfo = decoder.getOutputInfo();
546 if (bitmapInfo.colorType() == kGray_8_SkColorType) {
547 bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType);
548 }
549
550 SkBitmap bm;
551 if (!bm.setInfo(bitmapInfo)) {
552 ALOGE("Failed to setInfo properly");
553 return SkCodec::kInternalError;
554 }
555
556 sk_sp<Bitmap> nativeBitmap;
557 if (isShared) {
558 nativeBitmap = Bitmap::allocateAshmemBitmap(&bm);
559 } else {
560 nativeBitmap = Bitmap::allocateHeapBitmap(&bm);
561 }
562 if (!nativeBitmap) {
563 ALOGE("OOM allocating Bitmap with dimensions %i x %i", bitmapInfo.width(),
564 bitmapInfo.height());
565 return SkCodec::kInternalError;
566 }
567
568 SkCodec::Result result = decoder.decode(bm.getPixels(), bm.rowBytes());
569 bm.setImmutable();
570
571 if (result == SkCodec::kSuccess) {
572 auto gainmap = sp<uirenderer::Gainmap>::make();
573 gainmap->info = gainmapInfo;
574 gainmap->bitmap = std::move(nativeBitmap);
575 destination->setGainmap(std::move(gainmap));
576 }
577
578 return result;
579 }
580