Merge "Merge "Add BitmapFactory.Options.inColorSpace" into oc-dev am: c99bcc69f7 am: f713a1960e"
diff --git a/api/current.txt b/api/current.txt
index d9ddc87..deacec3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -12536,6 +12536,7 @@
field public boolean inJustDecodeBounds;
field public boolean inMutable;
field public deprecated boolean inPreferQualityOverSpeed;
+ field public android.graphics.ColorSpace inPreferredColorSpace;
field public android.graphics.Bitmap.Config inPreferredConfig;
field public boolean inPremultiplied;
field public deprecated boolean inPurgeable;
diff --git a/api/system-current.txt b/api/system-current.txt
index bc1b9a8..4ca9c88 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -13308,6 +13308,7 @@
field public boolean inJustDecodeBounds;
field public boolean inMutable;
field public deprecated boolean inPreferQualityOverSpeed;
+ field public android.graphics.ColorSpace inPreferredColorSpace;
field public android.graphics.Bitmap.Config inPreferredConfig;
field public boolean inPremultiplied;
field public deprecated boolean inPurgeable;
diff --git a/api/test-current.txt b/api/test-current.txt
index 9ae543c..c038c43 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -12578,6 +12578,7 @@
field public boolean inJustDecodeBounds;
field public boolean inMutable;
field public deprecated boolean inPreferQualityOverSpeed;
+ field public android.graphics.ColorSpace inPreferredColorSpace;
field public android.graphics.Bitmap.Config inPreferredConfig;
field public boolean inPremultiplied;
field public deprecated boolean inPurgeable;
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 3a03af6..0e67d304 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -44,14 +44,6 @@
static jmethodID gBitmap_reinitMethodID;
static jmethodID gBitmap_getAllocationByteCountMethodID;
-static jfieldID gTransferParams_aFieldID;
-static jfieldID gTransferParams_bFieldID;
-static jfieldID gTransferParams_cFieldID;
-static jfieldID gTransferParams_dFieldID;
-static jfieldID gTransferParams_eFieldID;
-static jfieldID gTransferParams_fFieldID;
-static jfieldID gTransferParams_gFieldID;
-
namespace android {
class BitmapWrapper {
@@ -742,28 +734,8 @@
if (colorType != kN32_SkColorType || xyzD50 == nullptr || transferParameters == nullptr) {
colorSpace = GraphicsJNI::colorSpaceForType(colorType);
} else {
- SkColorSpaceTransferFn p;
- p.fA = (float) env->GetDoubleField(transferParameters, gTransferParams_aFieldID);
- p.fB = (float) env->GetDoubleField(transferParameters, gTransferParams_bFieldID);
- p.fC = (float) env->GetDoubleField(transferParameters, gTransferParams_cFieldID);
- p.fD = (float) env->GetDoubleField(transferParameters, gTransferParams_dFieldID);
- p.fE = (float) env->GetDoubleField(transferParameters, gTransferParams_eFieldID);
- p.fF = (float) env->GetDoubleField(transferParameters, gTransferParams_fFieldID);
- p.fG = (float) env->GetDoubleField(transferParameters, gTransferParams_gFieldID);
-
- SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor);
- jfloat* array = env->GetFloatArrayElements(xyzD50, NULL);
- xyzMatrix.setFloat(0, 0, array[0]);
- xyzMatrix.setFloat(1, 0, array[1]);
- xyzMatrix.setFloat(2, 0, array[2]);
- xyzMatrix.setFloat(0, 1, array[3]);
- xyzMatrix.setFloat(1, 1, array[4]);
- xyzMatrix.setFloat(2, 1, array[5]);
- xyzMatrix.setFloat(0, 2, array[6]);
- xyzMatrix.setFloat(1, 2, array[7]);
- xyzMatrix.setFloat(2, 2, array[8]);
- env->ReleaseFloatArrayElements(xyzD50, array, 0);
-
+ SkColorSpaceTransferFn p = GraphicsJNI::getNativeTransferParameters(env, transferParameters);
+ SkMatrix44 xyzMatrix = GraphicsJNI::getNativeXYZMatrix(env, xyzD50);
colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
}
@@ -1635,20 +1607,6 @@
}
///////////////////////////////////////////////////////////////////////////////
-static jclass make_globalref(JNIEnv* env, const char classname[])
-{
- jclass c = env->FindClass(classname);
- SkASSERT(c);
- return (jclass) env->NewGlobalRef(c);
-}
-
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
- const char fieldname[], const char type[])
-{
- jfieldID id = env->GetFieldID(clazz, fieldname, type);
- SkASSERT(id);
- return id;
-}
static const JNINativeMethod gBitmapMethods[] = {
{ "nativeCreate", "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
@@ -1706,20 +1664,11 @@
int register_android_graphics_Bitmap(JNIEnv* env)
{
- jclass transfer_params_class = FindClassOrDie(env, "android/graphics/ColorSpace$Rgb$TransferParameters");
- gTransferParams_aFieldID = GetFieldIDOrDie(env, transfer_params_class, "a", "D");
- gTransferParams_bFieldID = GetFieldIDOrDie(env, transfer_params_class, "b", "D");
- gTransferParams_cFieldID = GetFieldIDOrDie(env, transfer_params_class, "c", "D");
- gTransferParams_dFieldID = GetFieldIDOrDie(env, transfer_params_class, "d", "D");
- gTransferParams_eFieldID = GetFieldIDOrDie(env, transfer_params_class, "e", "D");
- gTransferParams_fFieldID = GetFieldIDOrDie(env, transfer_params_class, "f", "D");
- gTransferParams_gFieldID = GetFieldIDOrDie(env, transfer_params_class, "g", "D");
-
- gBitmap_class = make_globalref(env, "android/graphics/Bitmap");
- gBitmap_nativePtr = getFieldIDCheck(env, gBitmap_class, "mNativePtr", "J");
- gBitmap_constructorMethodID = env->GetMethodID(gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
- gBitmap_reinitMethodID = env->GetMethodID(gBitmap_class, "reinit", "(IIZ)V");
- gBitmap_getAllocationByteCountMethodID = env->GetMethodID(gBitmap_class, "getAllocationByteCount", "()I");
+ gBitmap_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap"));
+ gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
+ gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZZ[BLandroid/graphics/NinePatch$InsetStruct;)V");
+ gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
+ gBitmap_getAllocationByteCountMethodID = GetMethodIDOrDie(env, gBitmap_class, "getAllocationByteCount", "()I");
return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
NELEM(gBitmapMethods));
}
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index af0be7b..404c889 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -27,6 +27,7 @@
jfieldID gOptions_justBoundsFieldID;
jfieldID gOptions_sampleSizeFieldID;
jfieldID gOptions_configFieldID;
+jfieldID gOptions_colorSpaceFieldID;
jfieldID gOptions_premultipliedFieldID;
jfieldID gOptions_mutableFieldID;
jfieldID gOptions_ditherFieldID;
@@ -51,20 +52,6 @@
jclass gBitmapConfig_class;
jmethodID gBitmapConfig_nativeToConfigMethodID;
-jclass gColorSpace_class;
-jmethodID gColorSpace_getMethodID;
-jmethodID gColorSpace_matchMethodID;
-
-jclass gColorSpaceRGB_class;
-jmethodID gColorSpaceRGB_constructorMethodID;
-
-jclass gColorSpace_Named_class;
-jfieldID gColorSpace_Named_sRGBFieldID;
-jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
-
-jclass gTransferParameters_class;
-jmethodID gTransferParameters_constructorMethodID;
-
using namespace android;
jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) {
@@ -242,70 +229,6 @@
needsFineScale(fullSize.height(), decodedSize.height(), sampleSize);
}
-static jobject getColorSpace(JNIEnv* env,
- sk_sp<SkColorSpace>& decodeColorSpace, SkColorType decodeColorType) {
- jobject colorSpace = nullptr;
-
- // No need to match, we know what the output color space will be
- if (decodeColorType == kRGBA_F16_SkColorType) {
- jobject linearExtendedSRGB = env->GetStaticObjectField(
- gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
- colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
- gColorSpace_getMethodID, linearExtendedSRGB);
- } else {
- // Same here, no need to match
- if (decodeColorSpace->isSRGB()) {
- jobject sRGB = env->GetStaticObjectField(
- gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
- colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
- gColorSpace_getMethodID, sRGB);
- } else if (decodeColorSpace.get() != nullptr) {
- // Try to match against known RGB color spaces using the CIE XYZ D50
- // conversion matrix and numerical transfer function parameters
- SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
- LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
-
- SkColorSpaceTransferFn transferParams;
- // We can only handle numerical transfer functions at the moment
- LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
-
- jobject params = env->NewObject(gTransferParameters_class,
- gTransferParameters_constructorMethodID,
- transferParams.fA, transferParams.fB, transferParams.fC,
- transferParams.fD, transferParams.fE, transferParams.fF,
- transferParams.fG);
-
- jfloatArray xyzArray = env->NewFloatArray(9);
- jfloat xyz[9] = {
- xyzMatrix.getFloat(0, 0),
- xyzMatrix.getFloat(1, 0),
- xyzMatrix.getFloat(2, 0),
- xyzMatrix.getFloat(0, 1),
- xyzMatrix.getFloat(1, 1),
- xyzMatrix.getFloat(2, 1),
- xyzMatrix.getFloat(0, 2),
- xyzMatrix.getFloat(1, 2),
- xyzMatrix.getFloat(2, 2)
- };
- env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
-
- colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
- gColorSpace_matchMethodID, xyzArray, params);
-
- if (colorSpace == nullptr) {
- // We couldn't find an exact match, let's create a new color space
- // instance with the 3x3 conversion matrix and transfer function
- colorSpace = env->NewObject(gColorSpaceRGB_class,
- gColorSpaceRGB_constructorMethodID,
- env->NewStringUTF("Unknown"), xyzArray, params);
- }
-
- env->DeleteLocalRef(xyzArray);
- }
- }
- return colorSpace;
-}
-
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
@@ -322,6 +245,7 @@
float scale = 1.0f;
bool requireUnpremultiplied = false;
jobject javaBitmap = NULL;
+ sk_sp<SkColorSpace> prefColorSpace = nullptr;
// Update with options supplied by the client.
if (options != NULL) {
@@ -345,6 +269,8 @@
jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
prefColorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
+ jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID);
+ prefColorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace);
isHardware = GraphicsJNI::isHardwareConfig(env, jconfig);
isMutable = env->GetBooleanField(options, gOptions_mutableFieldID);
requireUnpremultiplied = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
@@ -398,7 +324,8 @@
// Set the decode colorType
SkColorType decodeColorType = codec->computeOutputColorType(prefColorType);
- sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(decodeColorType);
+ sk_sp<SkColorSpace> decodeColorSpace = codec->computeOutputColorSpace(
+ decodeColorType, prefColorSpace);
// Set the options and return if the client only wants the size.
if (options != NULL) {
@@ -426,7 +353,7 @@
env->SetObjectField(options, gOptions_outConfigFieldID, config);
env->SetObjectField(options, gOptions_outColorSpaceFieldID,
- getColorSpace(env, decodeColorSpace, decodeColorType));
+ GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
if (onlyDecodeSize) {
return nullptr;
@@ -794,6 +721,8 @@
gOptions_sampleSizeFieldID = GetFieldIDOrDie(env, options_class, "inSampleSize", "I");
gOptions_configFieldID = GetFieldIDOrDie(env, options_class, "inPreferredConfig",
"Landroid/graphics/Bitmap$Config;");
+ gOptions_colorSpaceFieldID = GetFieldIDOrDie(env, options_class, "inPreferredColorSpace",
+ "Landroid/graphics/ColorSpace;");
gOptions_premultipliedFieldID = GetFieldIDOrDie(env, options_class, "inPremultiplied", "Z");
gOptions_mutableFieldID = GetFieldIDOrDie(env, options_class, "inMutable", "Z");
gOptions_ditherFieldID = GetFieldIDOrDie(env, options_class, "inDither", "Z");
@@ -826,29 +755,6 @@
gBitmapConfig_nativeToConfigMethodID = GetStaticMethodIDOrDie(env, gBitmapConfig_class,
"nativeToConfig", "(I)Landroid/graphics/Bitmap$Config;");
- gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
- gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
- "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
- gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match",
- "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;");
-
- gColorSpaceRGB_class = MakeGlobalRefOrDie(env,
- FindClassOrDie(env, "android/graphics/ColorSpace$Rgb"));
- gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
- "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V");
-
- gColorSpace_Named_class = MakeGlobalRefOrDie(env,
- FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
- gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
- gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
- gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
- gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
-
- gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
- "android/graphics/ColorSpace$Rgb$TransferParameters"));
- gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
- "<init>", "(DDDDDDD)V");
-
return android::RegisterMethodsOrDie(env, "android/graphics/BitmapFactory",
gMethods, NELEM(gMethods));
}
diff --git a/core/jni/android/graphics/BitmapFactory.h b/core/jni/android/graphics/BitmapFactory.h
index 76db41d..1ee49fa 100644
--- a/core/jni/android/graphics/BitmapFactory.h
+++ b/core/jni/android/graphics/BitmapFactory.h
@@ -8,6 +8,7 @@
extern jfieldID gOptions_justBoundsFieldID;
extern jfieldID gOptions_sampleSizeFieldID;
extern jfieldID gOptions_configFieldID;
+extern jfieldID gOptions_colorSpaceFieldID;
extern jfieldID gOptions_premultipliedFieldID;
extern jfieldID gOptions_ditherFieldID;
extern jfieldID gOptions_purgeableFieldID;
@@ -17,9 +18,14 @@
extern jfieldID gOptions_widthFieldID;
extern jfieldID gOptions_heightFieldID;
extern jfieldID gOptions_mimeFieldID;
+extern jfieldID gOptions_outConfigFieldID;
+extern jfieldID gOptions_outColorSpaceFieldID;
extern jfieldID gOptions_mCancelID;
extern jfieldID gOptions_bitmapFieldID;
+extern jclass gBitmapConfig_class;
+extern jmethodID gBitmapConfig_nativeToConfigMethodID;
+
jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format);
jobject decodeBitmap(JNIEnv* env, void* data, size_t size);
diff --git a/core/jni/android/graphics/BitmapRegionDecoder.cpp b/core/jni/android/graphics/BitmapRegionDecoder.cpp
index 3247851..5022b22 100644
--- a/core/jni/android/graphics/BitmapRegionDecoder.cpp
+++ b/core/jni/android/graphics/BitmapRegionDecoder.cpp
@@ -132,11 +132,14 @@
bool requireUnpremul = false;
jobject javaBitmap = NULL;
bool isHardware = false;
+ sk_sp<SkColorSpace> colorSpace = nullptr;
// Update the default options with any options supplied by the client.
if (NULL != options) {
sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
jobject jconfig = env->GetObjectField(options, gOptions_configFieldID);
colorType = GraphicsJNI::getNativeBitmapColorType(env, jconfig);
+ jobject jcolorSpace = env->GetObjectField(options, gOptions_colorSpaceFieldID);
+ colorSpace = GraphicsJNI::getNativeColorSpace(env, jcolorSpace);
isHardware = GraphicsJNI::isHardwareConfig(env, jconfig);
requireUnpremul = !env->GetBooleanField(options, gOptions_premultipliedFieldID);
javaBitmap = env->GetObjectField(options, gOptions_bitmapFieldID);
@@ -148,8 +151,16 @@
env->SetIntField(options, gOptions_widthFieldID, -1);
env->SetIntField(options, gOptions_heightFieldID, -1);
env->SetObjectField(options, gOptions_mimeFieldID, 0);
+ env->SetObjectField(options, gOptions_outConfigFieldID, 0);
+ env->SetObjectField(options, gOptions_outColorSpaceFieldID, 0);
}
+ SkBitmapRegionDecoder* brd = reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle);
+
+ SkColorType decodeColorType = brd->computeOutputColorType(colorType);
+ sk_sp<SkColorSpace> decodeColorSpace = brd->computeOutputColorSpace(
+ decodeColorType, colorSpace);
+
// Recycle a bitmap if possible.
android::Bitmap* recycledBitmap = nullptr;
size_t recycledBytes = 0;
@@ -168,17 +179,16 @@
if (javaBitmap) {
allocator = &recycleAlloc;
// We are required to match the color type of the recycled bitmap.
- colorType = recycledBitmap->info().colorType();
+ decodeColorType = recycledBitmap->info().colorType();
} else {
allocator = &heapAlloc;
}
// Decode the region.
SkIRect subset = SkIRect::MakeXYWH(inputX, inputY, inputWidth, inputHeight);
- SkBitmapRegionDecoder* brd =
- reinterpret_cast<SkBitmapRegionDecoder*>(brdHandle);
SkBitmap bitmap;
- if (!brd->decodeRegion(&bitmap, allocator, subset, sampleSize, colorType, requireUnpremul)) {
+ if (!brd->decodeRegion(&bitmap, allocator, subset, sampleSize,
+ decodeColorType, requireUnpremul, decodeColorSpace)) {
return nullObjectReturn("Failed to decode region.");
}
@@ -186,11 +196,23 @@
if (NULL != options) {
env->SetIntField(options, gOptions_widthFieldID, bitmap.width());
env->SetIntField(options, gOptions_heightFieldID, bitmap.height());
+
env->SetObjectField(options, gOptions_mimeFieldID,
encodedFormatToString(env, (SkEncodedImageFormat)brd->getEncodedFormat()));
if (env->ExceptionCheck()) {
return nullObjectReturn("OOM in encodedFormatToString()");
}
+
+ jint configID = GraphicsJNI::colorTypeToLegacyBitmapConfig(decodeColorType);
+ if (isHardware) {
+ configID = GraphicsJNI::kHardware_LegacyBitmapConfig;
+ }
+ jobject config = env->CallStaticObjectMethod(gBitmapConfig_class,
+ gBitmapConfig_nativeToConfigMethodID, configID);
+ env->SetObjectField(options, gOptions_outConfigFieldID, config);
+
+ env->SetObjectField(options, gOptions_outColorSpaceFieldID,
+ GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
}
// If we may have reused a bitmap, we need to indicate that the pixels have changed.
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 113bc19..510d12e 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -6,6 +6,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include "GraphicsJNI.h"
+#include "core_jni_helpers.h"
#include "SkCanvas.h"
#include "SkMath.h"
@@ -17,6 +18,8 @@
#include <Caches.h>
#include <TextureCache.h>
+using namespace android;
+
void doThrowNPE(JNIEnv* env) {
jniThrowNullPointerException(env, NULL);
}
@@ -178,6 +181,32 @@
static jmethodID gVMRuntime_newNonMovableArray;
static jmethodID gVMRuntime_addressOf;
+static jfieldID gTransferParams_aFieldID;
+static jfieldID gTransferParams_bFieldID;
+static jfieldID gTransferParams_cFieldID;
+static jfieldID gTransferParams_dFieldID;
+static jfieldID gTransferParams_eFieldID;
+static jfieldID gTransferParams_fFieldID;
+static jfieldID gTransferParams_gFieldID;
+
+static jclass gColorSpace_class;
+static jfieldID gColorSpace_IlluminantD50FieldID;
+static jmethodID gColorSpace_adaptMethodID;
+static jmethodID gColorSpace_getMethodID;
+static jmethodID gColorSpace_matchMethodID;
+
+static jclass gColorSpaceRGB_class;
+static jmethodID gColorSpaceRGB_getTransferParametersMethodID;
+static jmethodID gColorSpaceRGB_getTransformMethodID;
+static jmethodID gColorSpaceRGB_constructorMethodID;
+
+static jclass gColorSpace_Named_class;
+static jfieldID gColorSpace_Named_sRGBFieldID;
+static jfieldID gColorSpace_Named_LinearExtendedSRGBFieldID;
+
+static jclass gTransferParameters_class;
+static jmethodID gTransferParameters_constructorMethodID;
+
///////////////////////////////////////////////////////////////////////////////
void GraphicsJNI::get_jrect(JNIEnv* env, jobject obj, int* L, int* T, int* R, int* B)
@@ -328,7 +357,7 @@
}
void GraphicsJNI::getSkBitmap(JNIEnv* env, jobject bitmap, SkBitmap* outBitmap) {
- android::bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
+ bitmap::toBitmap(env, bitmap).getSkBitmap(outBitmap);
}
SkPixelRef* GraphicsJNI::refSkPixelRef(JNIEnv* env, jobject jbitmap) {
@@ -464,6 +493,125 @@
return colorSpace == nullptr || colorSpace->isSRGB();
}
+SkColorSpaceTransferFn GraphicsJNI::getNativeTransferParameters(JNIEnv* env, jobject transferParams) {
+ SkColorSpaceTransferFn p;
+ p.fA = (float) env->GetDoubleField(transferParams, gTransferParams_aFieldID);
+ p.fB = (float) env->GetDoubleField(transferParams, gTransferParams_bFieldID);
+ p.fC = (float) env->GetDoubleField(transferParams, gTransferParams_cFieldID);
+ p.fD = (float) env->GetDoubleField(transferParams, gTransferParams_dFieldID);
+ p.fE = (float) env->GetDoubleField(transferParams, gTransferParams_eFieldID);
+ p.fF = (float) env->GetDoubleField(transferParams, gTransferParams_fFieldID);
+ p.fG = (float) env->GetDoubleField(transferParams, gTransferParams_gFieldID);
+ return p;
+}
+
+SkMatrix44 GraphicsJNI::getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50) {
+ SkMatrix44 xyzMatrix(SkMatrix44::kIdentity_Constructor);
+ jfloat* array = env->GetFloatArrayElements(xyzD50, NULL);
+ xyzMatrix.setFloat(0, 0, array[0]);
+ xyzMatrix.setFloat(1, 0, array[1]);
+ xyzMatrix.setFloat(2, 0, array[2]);
+ xyzMatrix.setFloat(0, 1, array[3]);
+ xyzMatrix.setFloat(1, 1, array[4]);
+ xyzMatrix.setFloat(2, 1, array[5]);
+ xyzMatrix.setFloat(0, 2, array[6]);
+ xyzMatrix.setFloat(1, 2, array[7]);
+ xyzMatrix.setFloat(2, 2, array[8]);
+ env->ReleaseFloatArrayElements(xyzD50, array, 0);
+ return xyzMatrix;
+}
+
+sk_sp<SkColorSpace> GraphicsJNI::getNativeColorSpace(JNIEnv* env, jobject colorSpace) {
+ if (colorSpace == nullptr) return nullptr;
+ if (!env->IsInstanceOf(colorSpace, gColorSpaceRGB_class)) {
+ doThrowIAE(env, "The color space must be an RGB color space");
+ }
+
+ jobject transferParams = env->CallObjectMethod(colorSpace,
+ gColorSpaceRGB_getTransferParametersMethodID);
+ if (transferParams == nullptr) {
+ doThrowIAE(env, "The color space must use an ICC parametric transfer function");
+ }
+
+ jfloatArray illuminantD50 = (jfloatArray) env->GetStaticObjectField(gColorSpace_class,
+ gColorSpace_IlluminantD50FieldID);
+ jobject colorSpaceD50 = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_adaptMethodID, colorSpace, illuminantD50);
+
+ jfloatArray xyzD50 = (jfloatArray) env->CallObjectMethod(colorSpaceD50,
+ gColorSpaceRGB_getTransformMethodID);
+
+ SkMatrix44 xyzMatrix = getNativeXYZMatrix(env, xyzD50);
+ SkColorSpaceTransferFn transferFunction = getNativeTransferParameters(env, transferParams);
+
+ return SkColorSpace::MakeRGB(transferFunction, xyzMatrix);
+}
+
+
+jobject GraphicsJNI::getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
+ SkColorType decodeColorType) {
+ jobject colorSpace = nullptr;
+
+ // No need to match, we know what the output color space will be
+ if (decodeColorType == kRGBA_F16_SkColorType) {
+ jobject linearExtendedSRGB = env->GetStaticObjectField(
+ gColorSpace_Named_class, gColorSpace_Named_LinearExtendedSRGBFieldID);
+ colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_getMethodID, linearExtendedSRGB);
+ } else {
+ // Same here, no need to match
+ if (decodeColorSpace->isSRGB()) {
+ jobject sRGB = env->GetStaticObjectField(
+ gColorSpace_Named_class, gColorSpace_Named_sRGBFieldID);
+ colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_getMethodID, sRGB);
+ } else if (decodeColorSpace.get() != nullptr) {
+ // Try to match against known RGB color spaces using the CIE XYZ D50
+ // conversion matrix and numerical transfer function parameters
+ SkMatrix44 xyzMatrix(SkMatrix44::kUninitialized_Constructor);
+ LOG_ALWAYS_FATAL_IF(!decodeColorSpace->toXYZD50(&xyzMatrix));
+
+ SkColorSpaceTransferFn transferParams;
+ // We can only handle numerical transfer functions at the moment
+ LOG_ALWAYS_FATAL_IF(!decodeColorSpace->isNumericalTransferFn(&transferParams));
+
+ jobject params = env->NewObject(gTransferParameters_class,
+ gTransferParameters_constructorMethodID,
+ transferParams.fA, transferParams.fB, transferParams.fC,
+ transferParams.fD, transferParams.fE, transferParams.fF,
+ transferParams.fG);
+
+ jfloatArray xyzArray = env->NewFloatArray(9);
+ jfloat xyz[9] = {
+ xyzMatrix.getFloat(0, 0),
+ xyzMatrix.getFloat(1, 0),
+ xyzMatrix.getFloat(2, 0),
+ xyzMatrix.getFloat(0, 1),
+ xyzMatrix.getFloat(1, 1),
+ xyzMatrix.getFloat(2, 1),
+ xyzMatrix.getFloat(0, 2),
+ xyzMatrix.getFloat(1, 2),
+ xyzMatrix.getFloat(2, 2)
+ };
+ env->SetFloatArrayRegion(xyzArray, 0, 9, xyz);
+
+ colorSpace = env->CallStaticObjectMethod(gColorSpace_class,
+ gColorSpace_matchMethodID, xyzArray, params);
+
+ if (colorSpace == nullptr) {
+ // We couldn't find an exact match, let's create a new color space
+ // instance with the 3x3 conversion matrix and transfer function
+ colorSpace = env->NewObject(gColorSpaceRGB_class,
+ gColorSpaceRGB_constructorMethodID,
+ env->NewStringUTF("Unknown"), xyzArray, params);
+ }
+
+ env->DeleteLocalRef(xyzArray);
+ }
+ }
+ return colorSpace;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
@@ -576,74 +724,97 @@
////////////////////////////////////////////////////////////////////////////////
-static jclass make_globalref(JNIEnv* env, const char classname[])
-{
- jclass c = env->FindClass(classname);
- SkASSERT(c);
- return (jclass) env->NewGlobalRef(c);
-}
-
-static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
- const char fieldname[], const char type[])
-{
- jfieldID id = env->GetFieldID(clazz, fieldname, type);
- SkASSERT(id);
- return id;
-}
-
int register_android_graphics_Graphics(JNIEnv* env)
{
jmethodID m;
jclass c;
- gRect_class = make_globalref(env, "android/graphics/Rect");
- gRect_leftFieldID = getFieldIDCheck(env, gRect_class, "left", "I");
- gRect_topFieldID = getFieldIDCheck(env, gRect_class, "top", "I");
- gRect_rightFieldID = getFieldIDCheck(env, gRect_class, "right", "I");
- gRect_bottomFieldID = getFieldIDCheck(env, gRect_class, "bottom", "I");
+ gRect_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Rect"));
+ gRect_leftFieldID = GetFieldIDOrDie(env, gRect_class, "left", "I");
+ gRect_topFieldID = GetFieldIDOrDie(env, gRect_class, "top", "I");
+ gRect_rightFieldID = GetFieldIDOrDie(env, gRect_class, "right", "I");
+ gRect_bottomFieldID = GetFieldIDOrDie(env, gRect_class, "bottom", "I");
- gRectF_class = make_globalref(env, "android/graphics/RectF");
- gRectF_leftFieldID = getFieldIDCheck(env, gRectF_class, "left", "F");
- gRectF_topFieldID = getFieldIDCheck(env, gRectF_class, "top", "F");
- gRectF_rightFieldID = getFieldIDCheck(env, gRectF_class, "right", "F");
- gRectF_bottomFieldID = getFieldIDCheck(env, gRectF_class, "bottom", "F");
+ gRectF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/RectF"));
+ gRectF_leftFieldID = GetFieldIDOrDie(env, gRectF_class, "left", "F");
+ gRectF_topFieldID = GetFieldIDOrDie(env, gRectF_class, "top", "F");
+ gRectF_rightFieldID = GetFieldIDOrDie(env, gRectF_class, "right", "F");
+ gRectF_bottomFieldID = GetFieldIDOrDie(env, gRectF_class, "bottom", "F");
- gPoint_class = make_globalref(env, "android/graphics/Point");
- gPoint_xFieldID = getFieldIDCheck(env, gPoint_class, "x", "I");
- gPoint_yFieldID = getFieldIDCheck(env, gPoint_class, "y", "I");
+ gPoint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Point"));
+ gPoint_xFieldID = GetFieldIDOrDie(env, gPoint_class, "x", "I");
+ gPoint_yFieldID = GetFieldIDOrDie(env, gPoint_class, "y", "I");
- gPointF_class = make_globalref(env, "android/graphics/PointF");
- gPointF_xFieldID = getFieldIDCheck(env, gPointF_class, "x", "F");
- gPointF_yFieldID = getFieldIDCheck(env, gPointF_class, "y", "F");
+ gPointF_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/PointF"));
+ gPointF_xFieldID = GetFieldIDOrDie(env, gPointF_class, "x", "F");
+ gPointF_yFieldID = GetFieldIDOrDie(env, gPointF_class, "y", "F");
- gBitmapRegionDecoder_class = make_globalref(env, "android/graphics/BitmapRegionDecoder");
- gBitmapRegionDecoder_constructorMethodID = env->GetMethodID(gBitmapRegionDecoder_class, "<init>", "(J)V");
+ gBitmapRegionDecoder_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/BitmapRegionDecoder"));
+ gBitmapRegionDecoder_constructorMethodID = GetMethodIDOrDie(env, gBitmapRegionDecoder_class, "<init>", "(J)V");
- gBitmapConfig_class = make_globalref(env, "android/graphics/Bitmap$Config");
- gBitmapConfig_nativeInstanceID = getFieldIDCheck(env, gBitmapConfig_class,
- "nativeInt", "I");
+ gBitmapConfig_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Bitmap$Config"));
+ gBitmapConfig_nativeInstanceID = GetFieldIDOrDie(env, gBitmapConfig_class, "nativeInt", "I");
- gCanvas_class = make_globalref(env, "android/graphics/Canvas");
- gCanvas_nativeInstanceID = getFieldIDCheck(env, gCanvas_class, "mNativeCanvasWrapper", "J");
+ gCanvas_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Canvas"));
+ gCanvas_nativeInstanceID = GetFieldIDOrDie(env, gCanvas_class, "mNativeCanvasWrapper", "J");
- gPicture_class = make_globalref(env, "android/graphics/Picture");
- gPicture_nativeInstanceID = getFieldIDCheck(env, gPicture_class, "mNativePicture", "J");
+ gPicture_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Picture"));
+ gPicture_nativeInstanceID = GetFieldIDOrDie(env, gPicture_class, "mNativePicture", "J");
- gRegion_class = make_globalref(env, "android/graphics/Region");
- gRegion_nativeInstanceID = getFieldIDCheck(env, gRegion_class, "mNativeRegion", "J");
- gRegion_constructorMethodID = env->GetMethodID(gRegion_class, "<init>",
- "(JI)V");
+ gRegion_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Region"));
+ gRegion_nativeInstanceID = GetFieldIDOrDie(env, gRegion_class, "mNativeRegion", "J");
+ gRegion_constructorMethodID = GetMethodIDOrDie(env, gRegion_class, "<init>", "(JI)V");
c = env->FindClass("java/lang/Byte");
gByte_class = (jclass) env->NewGlobalRef(
env->GetStaticObjectField(c, env->GetStaticFieldID(c, "TYPE", "Ljava/lang/Class;")));
- gVMRuntime_class = make_globalref(env, "dalvik/system/VMRuntime");
+ gVMRuntime_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "dalvik/system/VMRuntime"));
m = env->GetStaticMethodID(gVMRuntime_class, "getRuntime", "()Ldalvik/system/VMRuntime;");
gVMRuntime = env->NewGlobalRef(env->CallStaticObjectMethod(gVMRuntime_class, m));
- gVMRuntime_newNonMovableArray = env->GetMethodID(gVMRuntime_class, "newNonMovableArray",
+ gVMRuntime_newNonMovableArray = GetMethodIDOrDie(env, gVMRuntime_class, "newNonMovableArray",
"(Ljava/lang/Class;I)Ljava/lang/Object;");
- gVMRuntime_addressOf = env->GetMethodID(gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J");
+ gVMRuntime_addressOf = GetMethodIDOrDie(env, gVMRuntime_class, "addressOf", "(Ljava/lang/Object;)J");
+
+ jclass transfer_params_class = FindClassOrDie(env, "android/graphics/ColorSpace$Rgb$TransferParameters");
+ gTransferParams_aFieldID = GetFieldIDOrDie(env, transfer_params_class, "a", "D");
+ gTransferParams_bFieldID = GetFieldIDOrDie(env, transfer_params_class, "b", "D");
+ gTransferParams_cFieldID = GetFieldIDOrDie(env, transfer_params_class, "c", "D");
+ gTransferParams_dFieldID = GetFieldIDOrDie(env, transfer_params_class, "d", "D");
+ gTransferParams_eFieldID = GetFieldIDOrDie(env, transfer_params_class, "e", "D");
+ gTransferParams_fFieldID = GetFieldIDOrDie(env, transfer_params_class, "f", "D");
+ gTransferParams_gFieldID = GetFieldIDOrDie(env, transfer_params_class, "g", "D");
+
+ gColorSpace_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/ColorSpace"));
+ gColorSpace_IlluminantD50FieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_class, "ILLUMINANT_D50", "[F");
+ gColorSpace_adaptMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "adapt",
+ "(Landroid/graphics/ColorSpace;[F)Landroid/graphics/ColorSpace;");
+ gColorSpace_getMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class,
+ "get", "(Landroid/graphics/ColorSpace$Named;)Landroid/graphics/ColorSpace;");
+ gColorSpace_matchMethodID = GetStaticMethodIDOrDie(env, gColorSpace_class, "match",
+ "([FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/ColorSpace;");
+
+ gColorSpaceRGB_class = MakeGlobalRefOrDie(env,
+ FindClassOrDie(env, "android/graphics/ColorSpace$Rgb"));
+ gColorSpaceRGB_constructorMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+ "<init>", "(Ljava/lang/String;[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)V");
+ gColorSpaceRGB_getTransferParametersMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+ "getTransferParameters", "()Landroid/graphics/ColorSpace$Rgb$TransferParameters;");
+ gColorSpaceRGB_getTransformMethodID = GetMethodIDOrDie(env, gColorSpaceRGB_class,
+ "getTransform", "()[F");
+
+ gColorSpace_Named_class = MakeGlobalRefOrDie(env,
+ FindClassOrDie(env, "android/graphics/ColorSpace$Named"));
+ gColorSpace_Named_sRGBFieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_Named_class, "SRGB", "Landroid/graphics/ColorSpace$Named;");
+ gColorSpace_Named_LinearExtendedSRGBFieldID = GetStaticFieldIDOrDie(env,
+ gColorSpace_Named_class, "LINEAR_EXTENDED_SRGB", "Landroid/graphics/ColorSpace$Named;");
+
+ gTransferParameters_class = MakeGlobalRefOrDie(env, FindClassOrDie(env,
+ "android/graphics/ColorSpace$Rgb$TransferParameters"));
+ gTransferParameters_constructorMethodID = GetMethodIDOrDie(env, gTransferParameters_class,
+ "<init>", "(DDDDDDD)V");
return 0;
}
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 7d7c881..7fbea25 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -10,6 +10,7 @@
#include "SkPoint.h"
#include "SkRect.h"
#include "SkColorSpace.h"
+#include "SkMatrix44.h"
#include <jni.h>
#include <hwui/Canvas.h>
#include <hwui/Bitmap.h>
@@ -112,6 +113,13 @@
static sk_sp<SkColorSpace> linearColorSpace();
static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
+
+ static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
+ static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
+ static sk_sp<SkColorSpace> getNativeColorSpace(JNIEnv* env, jobject colorSpace);
+
+ static jobject getColorSpace(JNIEnv* env, sk_sp<SkColorSpace>& decodeColorSpace,
+ SkColorType decodeColorType);
};
class HeapAllocator : public SkBRDAllocator {
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index ceedc1f..3b272c8 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -43,7 +43,6 @@
* the same result from the decoder as if null were passed.
*/
public Options() {
- inDither = false;
inScaled = true;
inPremultiplied = true;
}
@@ -114,8 +113,8 @@
/**
* If set to true, the decoder will return null (no bitmap), but
- * the out... fields will still be set, allowing the caller to query
- * the bitmap without having to allocate the memory for its pixels.
+ * the <code>out...</code> fields will still be set, allowing the caller to
+ * query the bitmap without having to allocate the memory for its pixels.
*/
public boolean inJustDecodeBounds;
@@ -144,6 +143,35 @@
public Bitmap.Config inPreferredConfig = Bitmap.Config.ARGB_8888;
/**
+ * <p>If this is non-null, the decoder will try to decode into this
+ * color space. If it is null, or the request cannot be met,
+ * the decoder will pick either the color space embedded in the image
+ * or the color space best suited for the requested image configuration
+ * (for instance {@link ColorSpace.Named#SRGB sRGB} for
+ * the {@link Bitmap.Config#ARGB_8888} configuration).</p>
+ *
+ * <p>{@link Bitmap.Config#RGBA_F16} always uses the
+ * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB scRGB} color space).
+ * Bitmaps in other configurations without an embedded color space are
+ * assumed to be in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
+ *
+ * <p class="note">Only {@link ColorSpace.Model#RGB} color spaces are
+ * currently supported. An <code>IllegalArgumentException</code> will
+ * be thrown by the decode methods when setting a non-RGB color space
+ * such as {@link ColorSpace.Named#CIE_LAB Lab}.</p>
+ *
+ * <p class="note">The specified color space's transfer function must be
+ * an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}. An
+ * <code>IllegalArgumentException</code> will be thrown by the decode methods
+ * if calling {@link ColorSpace.Rgb#getTransferParameters()} on the
+ * specified color space returns null.</p>
+ *
+ * <p>After decode, the bitmap's color space is stored in
+ * {@link #outColorSpace}.</p>
+ */
+ public ColorSpace inPreferredColorSpace = null;
+
+ /**
* If true (which is the default), the resulting bitmap will have its
* color channels pre-multipled by the alpha channel.
*
@@ -403,9 +431,22 @@
}
static void validate(Options opts) {
- if (opts != null && opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
+ if (opts == null) return;
+
+ if (opts.inMutable && opts.inPreferredConfig == Bitmap.Config.HARDWARE) {
throw new IllegalArgumentException("Bitmaps with Config.HARWARE are always immutable");
}
+
+ if (opts.inPreferredColorSpace != null) {
+ if (!(opts.inPreferredColorSpace instanceof ColorSpace.Rgb)) {
+ throw new IllegalArgumentException("The destination color space must use the " +
+ "RGB color model");
+ }
+ if (((ColorSpace.Rgb) opts.inPreferredColorSpace).getTransferParameters() == null) {
+ throw new IllegalArgumentException("The destination color space must use an " +
+ "ICC parametric transfer function");
+ }
+ }
}
}
@@ -421,7 +462,9 @@
* size be returned (in opts.outWidth and opts.outHeight)
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public static Bitmap decodeFile(String pathName, Options opts) {
validate(opts);
@@ -463,7 +506,9 @@
* resources, which we pass to be able to scale the bitmap accordingly.
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public static Bitmap decodeResourceStream(Resources res, TypedValue value,
InputStream is, Rect pad, Options opts) {
@@ -501,7 +546,9 @@
* size be returned (in opts.outWidth and opts.outHeight)
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public static Bitmap decodeResource(Resources res, int id, Options opts) {
validate(opts);
@@ -559,7 +606,9 @@
* size be returned (in opts.outWidth and opts.outHeight)
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
if ((offset | length) < 0 || data.length < offset + length) {
@@ -641,7 +690,9 @@
* size be returned (in opts.outWidth and opts.outHeight)
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*
* <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT},
* if {@link InputStream#markSupported is.markSupported()} returns true,
@@ -720,7 +771,9 @@
* @return the decoded bitmap, or null
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
validate(opts);
diff --git a/graphics/java/android/graphics/BitmapRegionDecoder.java b/graphics/java/android/graphics/BitmapRegionDecoder.java
index 04abca1..2da27c7 100644
--- a/graphics/java/android/graphics/BitmapRegionDecoder.java
+++ b/graphics/java/android/graphics/BitmapRegionDecoder.java
@@ -180,7 +180,9 @@
* decoded.
* @throws IllegalArgumentException if {@link BitmapFactory.Options#inPreferredConfig}
* is {@link android.graphics.Bitmap.Config#HARDWARE}
- * and {@link BitmapFactory.Options#inMutable} is set.
+ * and {@link BitmapFactory.Options#inMutable} is set, if the specified color space
+ * is not {@link ColorSpace.Model#RGB RGB}, or if the specified color space's transfer
+ * function is not an {@link ColorSpace.Rgb.TransferParameters ICC parametric curve}
*/
public Bitmap decodeRegion(Rect rect, BitmapFactory.Options options) {
BitmapFactory.Options.validate(options);