Loading core/jni/android/graphics/ImageDecoder.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -241,7 +241,7 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong doThrowISE(env, "Could not scale to target size!"); return nullptr; } if (requireUnpremul && !decoder->setOutAlphaType(kUnpremul_SkAlphaType)) { if (requireUnpremul && !decoder->setUnpremultipliedRequired(true)) { doThrowISE(env, "Cannot scale unpremultiplied pixels!"); return nullptr; } Loading Loading @@ -301,11 +301,15 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong } } SkBitmap bm; SkImageInfo bitmapInfo = decoder->getOutputInfo(); if (decoder->opaque()) { bitmapInfo = bitmapInfo.makeAlphaType(kOpaque_SkAlphaType); } if (asAlphaMask && colorType == kGray_8_SkColorType) { bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType); } SkBitmap bm; if (!bm.setInfo(bitmapInfo)) { doThrowIOE(env, "Failed to setInfo properly"); return nullptr; Loading libs/hwui/hwui/ImageDecoder.cpp +18 −29 Original line number Diff line number Diff line Loading @@ -30,19 +30,25 @@ ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChu , mTargetSize(mCodec->getInfo().dimensions()) , mDecodeSize(mTargetSize) , mOutColorType(mCodec->computeOutputColorType(kN32_SkColorType)) , mOutAlphaType(mCodec->getInfo().isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType) , mUnpremultipliedRequired(false) , mOutColorSpace(mCodec->getInfo().refColorSpace()) , mSampleSize(1) { } SkAlphaType ImageDecoder::getOutAlphaType() const { // While an SkBitmap may want to use kOpaque_SkAlphaType for a performance // optimization, this class just outputs raw pixels. Using either // premultiplication choice has no effect on decoding an opaque encoded image. return mUnpremultipliedRequired ? kUnpremul_SkAlphaType : kPremul_SkAlphaType; } bool ImageDecoder::setTargetSize(int width, int height) { if (width <= 0 || height <= 0) { return false; } auto info = SkImageInfo::Make(width, height, mOutColorType, mOutAlphaType); auto info = SkImageInfo::Make(width, height, mOutColorType, getOutAlphaType()); size_t rowBytes = info.minRowBytes(); if (rowBytes == 0) { // This would have overflowed. Loading @@ -63,7 +69,7 @@ bool ImageDecoder::setTargetSize(int width, int height) { SkISize targetSize = { width, height }, decodeSize = targetSize; int sampleSize = mCodec->computeSampleSize(&decodeSize); if (decodeSize != targetSize && mOutAlphaType == kUnpremul_SkAlphaType if (decodeSize != targetSize && mUnpremultipliedRequired && !mCodec->getInfo().isOpaque()) { return false; } Loading Loading @@ -119,29 +125,11 @@ bool ImageDecoder::setOutColorType(SkColorType colorType) { return true; } bool ImageDecoder::setOutAlphaType(SkAlphaType alpha) { switch (alpha) { case kOpaque_SkAlphaType: return opaque(); case kPremul_SkAlphaType: if (opaque()) { // Opaque can be treated as premul. return true; } break; case kUnpremul_SkAlphaType: if (opaque()) { // Opaque can be treated as unpremul. return true; } if (mDecodeSize != mTargetSize) { return false; } break; default: bool ImageDecoder::setUnpremultipliedRequired(bool required) { if (required && !opaque() && mDecodeSize != mTargetSize) { return false; } mOutAlphaType = alpha; mUnpremultipliedRequired = required; return true; } Loading @@ -151,11 +139,11 @@ void ImageDecoder::setOutColorSpace(sk_sp<SkColorSpace> colorSpace) { SkImageInfo ImageDecoder::getOutputInfo() const { SkISize size = mCropRect ? mCropRect->size() : mTargetSize; return SkImageInfo::Make(size, mOutColorType, mOutAlphaType, mOutColorSpace); return SkImageInfo::Make(size, mOutColorType, getOutAlphaType(), mOutColorSpace); } bool ImageDecoder::opaque() const { return mOutAlphaType == kOpaque_SkAlphaType; return mCodec->getInfo().alphaType() == kOpaque_SkAlphaType; } bool ImageDecoder::gray() const { Loading @@ -165,7 +153,8 @@ bool ImageDecoder::gray() const { SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) { void* decodePixels = pixels; size_t decodeRowBytes = rowBytes; auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, mOutAlphaType, mOutColorSpace); auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, getOutAlphaType(), mOutColorSpace); // Used if we need a temporary before scaling or subsetting. // FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380. SkBitmap tmp; Loading libs/hwui/hwui/ImageDecoder.h +4 −4 Original line number Diff line number Diff line Loading @@ -41,14 +41,12 @@ public: bool setOutColorType(SkColorType outColorType); bool setOutAlphaType(SkAlphaType outAlphaType); bool setUnpremultipliedRequired(bool unpremultipliedRequired); void setOutColorSpace(sk_sp<SkColorSpace> cs); // The size is the final size after scaling and cropping. SkImageInfo getOutputInfo() const; SkColorType getOutColorType() const { return mOutColorType; } SkAlphaType getOutAlphaType() const { return mOutAlphaType; } bool opaque() const; bool gray() const; Loading @@ -59,13 +57,15 @@ private: SkISize mTargetSize; SkISize mDecodeSize; SkColorType mOutColorType; SkAlphaType mOutAlphaType; bool mUnpremultipliedRequired; sk_sp<SkColorSpace> mOutColorSpace; int mSampleSize; std::optional<SkIRect> mCropRect; ImageDecoder(const ImageDecoder&) = delete; ImageDecoder& operator=(const ImageDecoder&) = delete; SkAlphaType getOutAlphaType() const; }; } // namespace android native/graphics/jni/imagedecoder.cpp +3 −17 Original line number Diff line number Diff line Loading @@ -241,26 +241,12 @@ int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) { } } SkAlphaType toAlphaType(int androidBitmapFlags) { switch (androidBitmapFlags) { case ANDROID_BITMAP_FLAGS_ALPHA_PREMUL: return kPremul_SkAlphaType; case ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL: return kUnpremul_SkAlphaType; case ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE: return kOpaque_SkAlphaType; default: return kUnknown_SkAlphaType; } } int AImageDecoder_setAlphaFlags(AImageDecoder* decoder, int alphaFlag) { if (!decoder || alphaFlag < ANDROID_BITMAP_FLAGS_ALPHA_PREMUL || alphaFlag > ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL) { int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) { if (!decoder) { return ANDROID_IMAGE_DECODER_BAD_PARAMETER; } return toDecoder(decoder)->setOutAlphaType(toAlphaType(alphaFlag)) return toDecoder(decoder)->setUnpremultipliedRequired(required) ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION; } Loading native/graphics/jni/libjnigraphics.map.txt +17 −17 Original line number Diff line number Diff line LIBJNIGRAPHICS { global: AImageDecoder_createFromAAsset; AImageDecoder_createFromFd; AImageDecoder_createFromBuffer; AImageDecoder_delete; AImageDecoder_setAndroidBitmapFormat; AImageDecoder_setAlphaFlags; AImageDecoder_getHeaderInfo; AImageDecoder_getMinimumStride; AImageDecoder_decodeImage; AImageDecoder_setTargetSize; AImageDecoder_setCrop; AImageDecoderHeaderInfo_getWidth; AImageDecoderHeaderInfo_getHeight; AImageDecoderHeaderInfo_getMimeType; AImageDecoderHeaderInfo_getAlphaFlags; AImageDecoderHeaderInfo_isAnimated; AImageDecoderHeaderInfo_getAndroidBitmapFormat; AImageDecoder_createFromAAsset; # introduced=30 AImageDecoder_createFromFd; # introduced=30 AImageDecoder_createFromBuffer; # introduced=30 AImageDecoder_delete; # introduced=30 AImageDecoder_setAndroidBitmapFormat; # introduced=30 AImageDecoder_setUnpremultipliedRequired; # introduced=30 AImageDecoder_getHeaderInfo; # introduced=30 AImageDecoder_getMinimumStride; # introduced=30 AImageDecoder_decodeImage; # introduced=30 AImageDecoder_setTargetSize; # introduced=30 AImageDecoder_setCrop; # introduced=30 AImageDecoderHeaderInfo_getWidth; # introduced=30 AImageDecoderHeaderInfo_getHeight; # introduced=30 AImageDecoderHeaderInfo_getMimeType; # introduced=30 AImageDecoderHeaderInfo_getAlphaFlags; # introduced=30 AImageDecoderHeaderInfo_isAnimated; # introduced=30 AImageDecoderHeaderInfo_getAndroidBitmapFormat; # introduced=30 AndroidBitmap_getInfo; AndroidBitmap_getDataSpace; AndroidBitmap_lockPixels; Loading Loading
core/jni/android/graphics/ImageDecoder.cpp +6 −2 Original line number Diff line number Diff line Loading @@ -241,7 +241,7 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong doThrowISE(env, "Could not scale to target size!"); return nullptr; } if (requireUnpremul && !decoder->setOutAlphaType(kUnpremul_SkAlphaType)) { if (requireUnpremul && !decoder->setUnpremultipliedRequired(true)) { doThrowISE(env, "Cannot scale unpremultiplied pixels!"); return nullptr; } Loading Loading @@ -301,11 +301,15 @@ static jobject ImageDecoder_nDecodeBitmap(JNIEnv* env, jobject /*clazz*/, jlong } } SkBitmap bm; SkImageInfo bitmapInfo = decoder->getOutputInfo(); if (decoder->opaque()) { bitmapInfo = bitmapInfo.makeAlphaType(kOpaque_SkAlphaType); } if (asAlphaMask && colorType == kGray_8_SkColorType) { bitmapInfo = bitmapInfo.makeColorType(kAlpha_8_SkColorType); } SkBitmap bm; if (!bm.setInfo(bitmapInfo)) { doThrowIOE(env, "Failed to setInfo properly"); return nullptr; Loading
libs/hwui/hwui/ImageDecoder.cpp +18 −29 Original line number Diff line number Diff line Loading @@ -30,19 +30,25 @@ ImageDecoder::ImageDecoder(std::unique_ptr<SkAndroidCodec> codec, sk_sp<SkPngChu , mTargetSize(mCodec->getInfo().dimensions()) , mDecodeSize(mTargetSize) , mOutColorType(mCodec->computeOutputColorType(kN32_SkColorType)) , mOutAlphaType(mCodec->getInfo().isOpaque() ? kOpaque_SkAlphaType : kPremul_SkAlphaType) , mUnpremultipliedRequired(false) , mOutColorSpace(mCodec->getInfo().refColorSpace()) , mSampleSize(1) { } SkAlphaType ImageDecoder::getOutAlphaType() const { // While an SkBitmap may want to use kOpaque_SkAlphaType for a performance // optimization, this class just outputs raw pixels. Using either // premultiplication choice has no effect on decoding an opaque encoded image. return mUnpremultipliedRequired ? kUnpremul_SkAlphaType : kPremul_SkAlphaType; } bool ImageDecoder::setTargetSize(int width, int height) { if (width <= 0 || height <= 0) { return false; } auto info = SkImageInfo::Make(width, height, mOutColorType, mOutAlphaType); auto info = SkImageInfo::Make(width, height, mOutColorType, getOutAlphaType()); size_t rowBytes = info.minRowBytes(); if (rowBytes == 0) { // This would have overflowed. Loading @@ -63,7 +69,7 @@ bool ImageDecoder::setTargetSize(int width, int height) { SkISize targetSize = { width, height }, decodeSize = targetSize; int sampleSize = mCodec->computeSampleSize(&decodeSize); if (decodeSize != targetSize && mOutAlphaType == kUnpremul_SkAlphaType if (decodeSize != targetSize && mUnpremultipliedRequired && !mCodec->getInfo().isOpaque()) { return false; } Loading Loading @@ -119,29 +125,11 @@ bool ImageDecoder::setOutColorType(SkColorType colorType) { return true; } bool ImageDecoder::setOutAlphaType(SkAlphaType alpha) { switch (alpha) { case kOpaque_SkAlphaType: return opaque(); case kPremul_SkAlphaType: if (opaque()) { // Opaque can be treated as premul. return true; } break; case kUnpremul_SkAlphaType: if (opaque()) { // Opaque can be treated as unpremul. return true; } if (mDecodeSize != mTargetSize) { return false; } break; default: bool ImageDecoder::setUnpremultipliedRequired(bool required) { if (required && !opaque() && mDecodeSize != mTargetSize) { return false; } mOutAlphaType = alpha; mUnpremultipliedRequired = required; return true; } Loading @@ -151,11 +139,11 @@ void ImageDecoder::setOutColorSpace(sk_sp<SkColorSpace> colorSpace) { SkImageInfo ImageDecoder::getOutputInfo() const { SkISize size = mCropRect ? mCropRect->size() : mTargetSize; return SkImageInfo::Make(size, mOutColorType, mOutAlphaType, mOutColorSpace); return SkImageInfo::Make(size, mOutColorType, getOutAlphaType(), mOutColorSpace); } bool ImageDecoder::opaque() const { return mOutAlphaType == kOpaque_SkAlphaType; return mCodec->getInfo().alphaType() == kOpaque_SkAlphaType; } bool ImageDecoder::gray() const { Loading @@ -165,7 +153,8 @@ bool ImageDecoder::gray() const { SkCodec::Result ImageDecoder::decode(void* pixels, size_t rowBytes) { void* decodePixels = pixels; size_t decodeRowBytes = rowBytes; auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, mOutAlphaType, mOutColorSpace); auto decodeInfo = SkImageInfo::Make(mDecodeSize, mOutColorType, getOutAlphaType(), mOutColorSpace); // Used if we need a temporary before scaling or subsetting. // FIXME: Use scanline decoding on only a couple lines to save memory. b/70709380. SkBitmap tmp; Loading
libs/hwui/hwui/ImageDecoder.h +4 −4 Original line number Diff line number Diff line Loading @@ -41,14 +41,12 @@ public: bool setOutColorType(SkColorType outColorType); bool setOutAlphaType(SkAlphaType outAlphaType); bool setUnpremultipliedRequired(bool unpremultipliedRequired); void setOutColorSpace(sk_sp<SkColorSpace> cs); // The size is the final size after scaling and cropping. SkImageInfo getOutputInfo() const; SkColorType getOutColorType() const { return mOutColorType; } SkAlphaType getOutAlphaType() const { return mOutAlphaType; } bool opaque() const; bool gray() const; Loading @@ -59,13 +57,15 @@ private: SkISize mTargetSize; SkISize mDecodeSize; SkColorType mOutColorType; SkAlphaType mOutAlphaType; bool mUnpremultipliedRequired; sk_sp<SkColorSpace> mOutColorSpace; int mSampleSize; std::optional<SkIRect> mCropRect; ImageDecoder(const ImageDecoder&) = delete; ImageDecoder& operator=(const ImageDecoder&) = delete; SkAlphaType getOutAlphaType() const; }; } // namespace android
native/graphics/jni/imagedecoder.cpp +3 −17 Original line number Diff line number Diff line Loading @@ -241,26 +241,12 @@ int AImageDecoderHeaderInfo_getAlphaFlags(const AImageDecoderHeaderInfo* info) { } } SkAlphaType toAlphaType(int androidBitmapFlags) { switch (androidBitmapFlags) { case ANDROID_BITMAP_FLAGS_ALPHA_PREMUL: return kPremul_SkAlphaType; case ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL: return kUnpremul_SkAlphaType; case ANDROID_BITMAP_FLAGS_ALPHA_OPAQUE: return kOpaque_SkAlphaType; default: return kUnknown_SkAlphaType; } } int AImageDecoder_setAlphaFlags(AImageDecoder* decoder, int alphaFlag) { if (!decoder || alphaFlag < ANDROID_BITMAP_FLAGS_ALPHA_PREMUL || alphaFlag > ANDROID_BITMAP_FLAGS_ALPHA_UNPREMUL) { int AImageDecoder_setUnpremultipliedRequired(AImageDecoder* decoder, bool required) { if (!decoder) { return ANDROID_IMAGE_DECODER_BAD_PARAMETER; } return toDecoder(decoder)->setOutAlphaType(toAlphaType(alphaFlag)) return toDecoder(decoder)->setUnpremultipliedRequired(required) ? ANDROID_IMAGE_DECODER_SUCCESS : ANDROID_IMAGE_DECODER_INVALID_CONVERSION; } Loading
native/graphics/jni/libjnigraphics.map.txt +17 −17 Original line number Diff line number Diff line LIBJNIGRAPHICS { global: AImageDecoder_createFromAAsset; AImageDecoder_createFromFd; AImageDecoder_createFromBuffer; AImageDecoder_delete; AImageDecoder_setAndroidBitmapFormat; AImageDecoder_setAlphaFlags; AImageDecoder_getHeaderInfo; AImageDecoder_getMinimumStride; AImageDecoder_decodeImage; AImageDecoder_setTargetSize; AImageDecoder_setCrop; AImageDecoderHeaderInfo_getWidth; AImageDecoderHeaderInfo_getHeight; AImageDecoderHeaderInfo_getMimeType; AImageDecoderHeaderInfo_getAlphaFlags; AImageDecoderHeaderInfo_isAnimated; AImageDecoderHeaderInfo_getAndroidBitmapFormat; AImageDecoder_createFromAAsset; # introduced=30 AImageDecoder_createFromFd; # introduced=30 AImageDecoder_createFromBuffer; # introduced=30 AImageDecoder_delete; # introduced=30 AImageDecoder_setAndroidBitmapFormat; # introduced=30 AImageDecoder_setUnpremultipliedRequired; # introduced=30 AImageDecoder_getHeaderInfo; # introduced=30 AImageDecoder_getMinimumStride; # introduced=30 AImageDecoder_decodeImage; # introduced=30 AImageDecoder_setTargetSize; # introduced=30 AImageDecoder_setCrop; # introduced=30 AImageDecoderHeaderInfo_getWidth; # introduced=30 AImageDecoderHeaderInfo_getHeight; # introduced=30 AImageDecoderHeaderInfo_getMimeType; # introduced=30 AImageDecoderHeaderInfo_getAlphaFlags; # introduced=30 AImageDecoderHeaderInfo_isAnimated; # introduced=30 AImageDecoderHeaderInfo_getAndroidBitmapFormat; # introduced=30 AndroidBitmap_getInfo; AndroidBitmap_getDataSpace; AndroidBitmap_lockPixels; Loading