summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp52
2 files changed, 50 insertions, 3 deletions
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index a13ebaf55cf4..252f168040df 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -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 \
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 1165a45c1535..19d4848e1656 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -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"
@@ -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
@@ -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
@@ -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) {