diff options
author | 2023-07-06 10:40:31 -0400 | |
---|---|---|
committer | 2023-07-06 10:42:30 -0400 | |
commit | 9519757d99f5e709cb623b5abcd474e44bc084e1 (patch) | |
tree | d9d9a4339b8a11785f4e64fc15f05340083dd1ee | |
parent | dd337315841e1f9b85cecd5328a62958db130745 (diff) |
Fix inSampleSize != 1 gainmap decoding
When decoding with a sample size we cannot use the width/height of
the subset to allocate the gainmap bitmap as that will be scaled
by the sample size.
Instead split out the destination width/height from the decode
subset to avoid trying to pack too many meanings into a single rect
Fixes: 289103338
Test: manual inspection of inSampleSize 1, 2, and 3 with & without
inBitmap being specified
Change-Id: I0685579d6835a6a06d73ef50c59b08611ca80211
-rw-r--r-- | libs/hwui/jni/BitmapRegionDecoder.cpp | 35 |
1 files changed, 16 insertions, 19 deletions
diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp index 4c9a23d3fde0..740988f77270 100644 --- a/libs/hwui/jni/BitmapRegionDecoder.cpp +++ b/libs/hwui/jni/BitmapRegionDecoder.cpp @@ -90,8 +90,8 @@ public: requireUnpremul, prefColorSpace); } - bool decodeGainmapRegion(sp<uirenderer::Gainmap>* outGainmap, const SkIRect& desiredSubset, - int sampleSize, bool requireUnpremul) { + bool decodeGainmapRegion(sp<uirenderer::Gainmap>* outGainmap, int outWidth, int outHeight, + const SkIRect& desiredSubset, int sampleSize, bool requireUnpremul) { SkColorType decodeColorType = mGainmapBRD->computeOutputColorType(kN32_SkColorType); sk_sp<SkColorSpace> decodeColorSpace = mGainmapBRD->computeOutputColorSpace(decodeColorType, nullptr); @@ -109,9 +109,8 @@ public: // kPremul_SkAlphaType is used just as a placeholder as it doesn't change the underlying // allocation type. RecyclingClippingPixelAllocator will populate this with the // actual alpha type in either allocPixelRef() or copyIfNecessary() - sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap( - SkImageInfo::Make(desiredSubset.width(), desiredSubset.height(), decodeColorType, - kPremul_SkAlphaType, decodeColorSpace)); + sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(SkImageInfo::Make( + outWidth, outHeight, decodeColorType, kPremul_SkAlphaType, decodeColorSpace)); if (!nativeBitmap) { ALOGE("OOM allocating Bitmap for Gainmap"); return false; @@ -134,9 +133,12 @@ public: return true; } - SkIRect calculateGainmapRegion(const SkIRect& mainImageRegion) { + SkIRect calculateGainmapRegion(const SkIRect& mainImageRegion, int* inOutWidth, + int* inOutHeight) { const float scaleX = ((float)mGainmapBRD->width()) / mMainImageBRD->width(); const float scaleY = ((float)mGainmapBRD->height()) / mMainImageBRD->height(); + *inOutWidth *= scaleX; + *inOutHeight *= scaleY; // TODO: Account for rounding error? return SkIRect::MakeLTRB(mainImageRegion.left() * scaleX, mainImageRegion.top() * scaleY, mainImageRegion.right() * scaleX, @@ -328,21 +330,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in sp<uirenderer::Gainmap> gainmap; bool hasGainmap = brd->hasGainmap(); if (hasGainmap) { - SkIRect adjustedSubset{}; + int gainmapWidth = bitmap.width(); + int gainmapHeight = bitmap.height(); if (javaBitmap) { - // Clamp to the width/height of the recycled bitmap in case the reused bitmap - // was too small for the specified rectangle, in which case we need to clip - adjustedSubset = SkIRect::MakeXYWH(inputX, inputY, - std::min(subset.width(), recycledBitmap->width()), - std::min(subset.height(), recycledBitmap->height())); - } else { - // We are not recycling, so use the decoded width/height for calculating the gainmap - // subset instead to ensure the gainmap region proportionally matches - adjustedSubset = SkIRect::MakeXYWH(std::max(0, inputX), std::max(0, inputY), - bitmap.width(), bitmap.height()); + // If we are recycling we must match the inBitmap's relative dimensions + gainmapWidth = recycledBitmap->width(); + gainmapHeight = recycledBitmap->height(); } - SkIRect gainmapSubset = brd->calculateGainmapRegion(adjustedSubset); - if (!brd->decodeGainmapRegion(&gainmap, gainmapSubset, sampleSize, requireUnpremul)) { + SkIRect gainmapSubset = brd->calculateGainmapRegion(subset, &gainmapWidth, &gainmapHeight); + if (!brd->decodeGainmapRegion(&gainmap, gainmapWidth, gainmapHeight, gainmapSubset, + sampleSize, requireUnpremul)) { // If there is an error decoding Gainmap - we don't fail. We just don't provide Gainmap hasGainmap = false; } |