Merge "Add BitmapFactory.Options.inColorSpace" into oc-dev
This commit is contained in:
@ -12533,6 +12533,7 @@ package android.graphics {
|
||||
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;
|
||||
|
@ -13303,6 +13303,7 @@ package android.graphics {
|
||||
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;
|
||||
|
@ -12575,6 +12575,7 @@ package android.graphics {
|
||||
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;
|
||||
|
@ -44,14 +44,6 @@ static jmethodID gBitmap_constructorMethodID;
|
||||
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 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
|
||||
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 void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlon
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
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 @@ static const JNINativeMethod gBitmapMethods[] = {
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -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 @@ jmethodID gInsetStruct_constructorMethodID;
|
||||
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) {
|
||||
@ -243,70 +230,6 @@ static bool needsFineScale(const SkISize fullSize, const SkISize decodedSize,
|
||||
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
|
||||
@ -323,6 +246,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
||||
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) {
|
||||
@ -346,6 +270,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
||||
|
||||
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);
|
||||
@ -399,7 +325,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
||||
|
||||
// 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) {
|
||||
@ -427,7 +354,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
||||
env->SetObjectField(options, gOptions_outConfigFieldID, config);
|
||||
|
||||
env->SetObjectField(options, gOptions_outColorSpaceFieldID,
|
||||
getColorSpace(env, decodeColorSpace, decodeColorType));
|
||||
GraphicsJNI::getColorSpace(env, decodeColorSpace, decodeColorType));
|
||||
|
||||
if (onlyDecodeSize) {
|
||||
return nullptr;
|
||||
@ -795,6 +722,8 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
|
||||
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");
|
||||
@ -827,29 +756,6 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
|
||||
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));
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ extern jclass gOptions_class;
|
||||
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_preferQualityOverSpeedFieldID;
|
||||
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);
|
||||
|
@ -132,11 +132,14 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
|
||||
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 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
|
||||
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 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
|
||||
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 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
|
||||
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.
|
||||
|
@ -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 jclass gVMRuntime_class;
|
||||
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 @@ SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
|
||||
}
|
||||
|
||||
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 @@ bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) {
|
||||
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);
|
||||
@ -577,74 +725,97 @@ bool AshmemPixelAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable)
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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 @@ public:
|
||||
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 {
|
||||
|
@ -43,7 +43,6 @@ public class BitmapFactory {
|
||||
* the same result from the decoder as if null were passed.
|
||||
*/
|
||||
public Options() {
|
||||
inDither = false;
|
||||
inScaled = true;
|
||||
inPremultiplied = true;
|
||||
}
|
||||
@ -114,8 +113,8 @@ public class BitmapFactory {
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@ -143,6 +142,35 @@ public class BitmapFactory {
|
||||
*/
|
||||
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 @@ public class BitmapFactory {
|
||||
}
|
||||
|
||||
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 @@ public class BitmapFactory {
|
||||
* 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 @@ public class BitmapFactory {
|
||||
* 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 @@ public class BitmapFactory {
|
||||
* 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 @@ public class BitmapFactory {
|
||||
* 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 @@ public class BitmapFactory {
|
||||
* 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 @@ public class BitmapFactory {
|
||||
* @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);
|
||||
|
@ -180,7 +180,9 @@ public final class BitmapRegionDecoder {
|
||||
* 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);
|
||||
|
Reference in New Issue
Block a user