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