Loading core/jni/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ LOCAL_C_INCLUDES += \ external/skia/src/effects \ external/skia/src/image \ external/skia/src/images \ external/skia/src/utils \ external/sqlite/dist \ external/sqlite/android \ external/tremor/Tremor \ Loading core/jni/android/graphics/BitmapFactory.cpp +49 −3 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "SkBRDAllocator.h" #include "SkFrontBufferedStream.h" #include "SkMath.h" #include "SkOpts.h" #include "SkPixelRef.h" #include "SkStream.h" #include "SkUtils.h" Loading Loading @@ -224,6 +225,45 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize, needsFineScale(fullSize.height(), decodedSize.height(), sampleSize); } static inline SkAlphaType computeDecodeAlphaType(SkColorType colorType, SkAlphaType alphaType) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING // Skia premultiplies linearly. Until the framework enables linear blending, // it expects a legacy premultiply. if (kPremul_SkAlphaType == alphaType && kRGBA_F16_SkColorType != colorType) { return kUnpremul_SkAlphaType; } #endif return alphaType; } static inline void premultiplyIfNecessary(SkBitmap* bitmap, SkPMColor* colorPtr, int* colorCount, SkAlphaType alphaType, bool requireUnpremultiplied) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING if (kUnpremul_SkAlphaType != alphaType || requireUnpremultiplied) { return; } switch (bitmap->colorType()) { case kN32_SkColorType: for (int y = 0; y < bitmap->height(); y++) { SkOpts::RGBA_to_rgbA(bitmap->getAddr32(0, y), bitmap->getAddr32(0, y), bitmap->width()); } return; case kIndex_8_SkColorType: SkOpts::RGBA_to_rgbA(colorPtr, colorPtr, *colorCount); return; default: // kRGBA_F16 will be premultiplied by the codec if necessary. // kGray_8 (alias kAlpha_8) and k565 are opaque. LOG_ALWAYS_FATAL("Should be unreachable - no need for legacy premultiply."); return; } #endif } static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) { // This function takes ownership of the input stream. Since the SkAndroidCodec // will take ownership of the stream, we don't necessarily need to take ownership Loading Loading @@ -391,13 +431,17 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding colorCount = &maxColors; } // Set the alpha type for the decode. SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied); SkAlphaType decodeAlphaType = computeDecodeAlphaType(decodeColorType, alphaType); const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(), decodeColorType, alphaType, GraphicsJNI::colorSpaceForType(decodeColorType)); decodeColorType, decodeAlphaType, codec->computeOutputColorSpace(decodeColorType)); // When supported by the colorType, we will decode to sRGB (or linear sRGB). However, // we only want to mark the bitmap as sRGB when linear blending is enabled. SkImageInfo bitmapInfo = decodeInfo.makeAlphaType(alphaType) .makeColorSpace(GraphicsJNI::colorSpaceForType(decodeColorType)); SkImageInfo bitmapInfo = decodeInfo; if (decodeColorType == kGray_8_SkColorType) { // The legacy implementation of BitmapFactory used kAlpha8 for // grayscale images (before kGray8 existed). While the codec Loading Loading @@ -433,6 +477,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding default: return nullObjectReturn("codec->getAndroidPixels() failed."); } premultiplyIfNecessary(&decodingBitmap, colorPtr, colorCount, decodeAlphaType, requireUnpremultiplied); jbyteArray ninePatchChunk = NULL; if (peeker.mPatch != NULL) { Loading Loading
core/jni/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -215,6 +215,7 @@ LOCAL_C_INCLUDES += \ external/skia/src/effects \ external/skia/src/image \ external/skia/src/images \ external/skia/src/utils \ external/sqlite/dist \ external/sqlite/android \ external/tremor/Tremor \ Loading
core/jni/android/graphics/BitmapFactory.cpp +49 −3 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ #include "SkBRDAllocator.h" #include "SkFrontBufferedStream.h" #include "SkMath.h" #include "SkOpts.h" #include "SkPixelRef.h" #include "SkStream.h" #include "SkUtils.h" Loading Loading @@ -224,6 +225,45 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize, needsFineScale(fullSize.height(), decodedSize.height(), sampleSize); } static inline SkAlphaType computeDecodeAlphaType(SkColorType colorType, SkAlphaType alphaType) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING // Skia premultiplies linearly. Until the framework enables linear blending, // it expects a legacy premultiply. if (kPremul_SkAlphaType == alphaType && kRGBA_F16_SkColorType != colorType) { return kUnpremul_SkAlphaType; } #endif return alphaType; } static inline void premultiplyIfNecessary(SkBitmap* bitmap, SkPMColor* colorPtr, int* colorCount, SkAlphaType alphaType, bool requireUnpremultiplied) { #ifndef ANDROID_ENABLE_LINEAR_BLENDING if (kUnpremul_SkAlphaType != alphaType || requireUnpremultiplied) { return; } switch (bitmap->colorType()) { case kN32_SkColorType: for (int y = 0; y < bitmap->height(); y++) { SkOpts::RGBA_to_rgbA(bitmap->getAddr32(0, y), bitmap->getAddr32(0, y), bitmap->width()); } return; case kIndex_8_SkColorType: SkOpts::RGBA_to_rgbA(colorPtr, colorPtr, *colorCount); return; default: // kRGBA_F16 will be premultiplied by the codec if necessary. // kGray_8 (alias kAlpha_8) and k565 are opaque. LOG_ALWAYS_FATAL("Should be unreachable - no need for legacy premultiply."); return; } #endif } static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding, jobject options) { // This function takes ownership of the input stream. Since the SkAndroidCodec // will take ownership of the stream, we don't necessarily need to take ownership Loading Loading @@ -391,13 +431,17 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding colorCount = &maxColors; } // Set the alpha type for the decode. SkAlphaType alphaType = codec->computeOutputAlphaType(requireUnpremultiplied); SkAlphaType decodeAlphaType = computeDecodeAlphaType(decodeColorType, alphaType); const SkImageInfo decodeInfo = SkImageInfo::Make(size.width(), size.height(), decodeColorType, alphaType, GraphicsJNI::colorSpaceForType(decodeColorType)); decodeColorType, decodeAlphaType, codec->computeOutputColorSpace(decodeColorType)); // When supported by the colorType, we will decode to sRGB (or linear sRGB). However, // we only want to mark the bitmap as sRGB when linear blending is enabled. SkImageInfo bitmapInfo = decodeInfo.makeAlphaType(alphaType) .makeColorSpace(GraphicsJNI::colorSpaceForType(decodeColorType)); SkImageInfo bitmapInfo = decodeInfo; if (decodeColorType == kGray_8_SkColorType) { // The legacy implementation of BitmapFactory used kAlpha8 for // grayscale images (before kGray8 existed). While the codec Loading Loading @@ -433,6 +477,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding default: return nullObjectReturn("codec->getAndroidPixels() failed."); } premultiplyIfNecessary(&decodingBitmap, colorPtr, colorCount, decodeAlphaType, requireUnpremultiplied); jbyteArray ninePatchChunk = NULL; if (peeker.mPatch != NULL) { Loading