Merge "Color management, the missing pieces" into oc-dev

This commit is contained in:
TreeHugger Robot
2017-04-07 18:34:34 +00:00
committed by Android (Google) Code Review
8 changed files with 249 additions and 70 deletions

View File

@@ -12429,7 +12429,9 @@ package android.graphics {
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean, android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean, android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);

View File

@@ -13192,7 +13192,9 @@ package android.graphics {
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean, android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean, android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);

View File

@@ -12479,7 +12479,9 @@ package android.graphics {
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(int, int, android.graphics.Bitmap.Config, boolean, android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean, android.graphics.ColorSpace);
method public static android.graphics.Bitmap createBitmap(int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(android.util.DisplayMetrics, int[], int, int, int, int, android.graphics.Bitmap.Config);
method public static android.graphics.Bitmap createBitmap(int[], int, int, android.graphics.Bitmap.Config);

View File

@@ -44,6 +44,14 @@ 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 {
@@ -685,6 +693,22 @@ static ToColorProc ChooseToColorProc(const SkBitmap& src) {
return NULL;
}
static void ToF16_SA8(void* dst, const void* src, int width) {
SkASSERT(width > 0);
uint64_t* d = (uint64_t*)dst;
const uint8_t* s = (const uint8_t*)src;
for (int i = 0; i < width; i++) {
uint8_t c = *s++;
SkPM4f a;
a.fVec[SkPM4f::R] = 0.0f;
a.fVec[SkPM4f::G] = 0.0f;
a.fVec[SkPM4f::B] = 0.0f;
a.fVec[SkPM4f::A] = c / 255.0f;
*d++ = a.toF16();
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
@@ -696,7 +720,8 @@ static int getPremulBitmapCreateFlags(bool isMutable) {
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
jint offset, jint stride, jint width, jint height,
jint configHandle, jboolean isMutable) {
jint configHandle, jboolean isMutable,
jfloatArray xyzD50, jobject transferParameters) {
SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
if (NULL != jColors) {
size_t n = env->GetArrayLength(jColors);
@@ -712,8 +737,37 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
}
SkBitmap bitmap;
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
GraphicsJNI::colorSpaceForType(colorType)));
sk_sp<SkColorSpace> colorSpace;
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);
colorSpace = SkColorSpace::MakeRGB(p, xyzMatrix);
}
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType, colorSpace));
sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
if (!nativeBitmap) {
@@ -739,6 +793,9 @@ static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
SkPixmap srcPixmap = srcUnlocker.pixmap();
SkImageInfo dstInfo = src.info().makeColorType(dstCT);
if (dstCT == kRGBA_F16_SkColorType) {
dstInfo = dstInfo.makeColorSpace(SkColorSpace::MakeSRGBLinear());
}
if (!dst->setInfo(dstInfo)) {
return false;
}
@@ -763,6 +820,14 @@ static bool bitmapCopyTo(SkBitmap* dst, SkColorType dstCT, const SkBitmap& src,
}
return true;
}
case kRGBA_F16_SkColorType: {
for (int y = 0; y < src.height(); y++) {
const uint8_t* srcRow = srcPixmap.addr8(0, y);
void* dstRow = dst->getAddr(0, y);
ToF16_SA8(dstRow, srcRow, src.width());
}
return true;
}
default:
return false;
}
@@ -1562,6 +1627,13 @@ static jobject Bitmap_createGraphicBufferHandle(JNIEnv* env, jobject, jlong bitm
return createJavaGraphicBuffer(env, buffer);
}
static void Bitmap_copyColorSpace(JNIEnv* env, jobject, jlong srcBitmapPtr, jlong dstBitmapPtr) {
LocalScopedBitmap srcBitmapHandle(srcBitmapPtr);
LocalScopedBitmap dstBitmapHandle(dstBitmapPtr);
dstBitmapHandle->bitmap().setColorSpace(srcBitmapHandle->bitmap().info().refColorSpace());
}
///////////////////////////////////////////////////////////////////////////////
static jclass make_globalref(JNIEnv* env, const char classname[])
{
@@ -1579,7 +1651,7 @@ static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
}
static const JNINativeMethod gBitmapMethods[] = {
{ "nativeCreate", "([IIIIIIZ)Landroid/graphics/Bitmap;",
{ "nativeCreate", "([IIIIIIZ[FLandroid/graphics/ColorSpace$Rgb$TransferParameters;)Landroid/graphics/Bitmap;",
(void*)Bitmap_creator },
{ "nativeCopy", "(JIZ)Landroid/graphics/Bitmap;",
(void*)Bitmap_copy },
@@ -1628,10 +1700,21 @@ static const JNINativeMethod gBitmapMethods[] = {
(void*) Bitmap_createGraphicBufferHandle },
{ "nativeGetColorSpace", "(J[F[F)Z", (void*)Bitmap_getColorSpace },
{ "nativeIsSRGB", "(J)Z", (void*)Bitmap_isSRGB },
{ "nativeCopyColorSpace", "(JJ)V",
(void*)Bitmap_copyColorSpace },
};
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");

View File

@@ -20,6 +20,7 @@ import android.annotation.CheckResult;
import android.annotation.ColorInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Size;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Trace;
@@ -78,8 +79,6 @@ public final class Bitmap implements Parcelable {
/** @hide */
public int mDensity = getDefaultDensity();
private static volatile Matrix sScaleMatrix;
private static volatile int sDefaultDensity = -1;
/**
@@ -606,7 +605,7 @@ public final class Bitmap implements Parcelable {
* setting the new bitmap's config to the one specified, and then copying
* this bitmap's pixels into the new bitmap. If the conversion is not
* supported, or the allocator fails, then this returns NULL. The returned
* bitmap initially has the same density as the original.
* bitmap has the same density and color space as the original.
*
* @param config The desired config for the resulting bitmap
* @param isMutable True if the resulting bitmap should be mutable (i.e.
@@ -629,7 +628,8 @@ public final class Bitmap implements Parcelable {
/**
* Creates a new immutable bitmap backed by ashmem which can efficiently
* be passed between processes.
* be passed between processes. The bitmap is assumed to be in the sRGB
* color space.
*
* @hide
*/
@@ -645,7 +645,8 @@ public final class Bitmap implements Parcelable {
/**
* Creates a new immutable bitmap backed by ashmem which can efficiently
* be passed between processes.
* be passed between processes. The bitmap is assumed to be in the sRGB
* color space.
*
* @hide
*/
@@ -666,7 +667,7 @@ public final class Bitmap implements Parcelable {
* currently PIXEL_FORMAT_RGBA_8888 is the only supported format
* @hide
*/
public static Bitmap createHardwareBitmap(GraphicBuffer graphicBuffer) {
public static Bitmap createHardwareBitmap(@NonNull GraphicBuffer graphicBuffer) {
return nativeCreateHardwareBitmap(graphicBuffer);
}
@@ -683,50 +684,34 @@ public final class Bitmap implements Parcelable {
* @return The new scaled bitmap or the source bitmap if no scaling is required.
* @throws IllegalArgumentException if width is <= 0, or height is <= 0
*/
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight,
public static Bitmap createScaledBitmap(@NonNull Bitmap src, int dstWidth, int dstHeight,
boolean filter) {
Matrix m;
synchronized (Bitmap.class) {
// small pool of just 1 matrix
m = sScaleMatrix;
sScaleMatrix = null;
}
if (m == null) {
m = new Matrix();
}
Matrix m = new Matrix();
final int width = src.getWidth();
final int height = src.getHeight();
final float sx = dstWidth / (float)width;
final float sy = dstHeight / (float)height;
m.setScale(sx, sy);
Bitmap b = Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
synchronized (Bitmap.class) {
// do we need to check for null? why not just assign everytime?
if (sScaleMatrix == null) {
sScaleMatrix = m;
}
if (width != dstWidth || height != dstHeight) {
final float sx = dstWidth / (float) width;
final float sy = dstHeight / (float) height;
m.setScale(sx, sy);
}
return b;
return Bitmap.createBitmap(src, 0, 0, width, height, m, filter);
}
/**
* Returns an immutable bitmap from the source bitmap. The new bitmap may
* be the same object as source, or a copy may have been made. It is
* initialized with the same density as the original bitmap.
* initialized with the same density and color space as the original bitmap.
*/
public static Bitmap createBitmap(Bitmap src) {
public static Bitmap createBitmap(@NonNull Bitmap src) {
return createBitmap(src, 0, 0, src.getWidth(), src.getHeight());
}
/**
* Returns an immutable bitmap from the specified subset of the source
* bitmap. The new bitmap may be the same object as source, or a copy may
* have been made. It is initialized with the same density as the original
* bitmap.
* have been made. It is initialized with the same density and color space
* as the original bitmap.
*
* @param source The bitmap we are subsetting
* @param x The x coordinate of the first pixel in source
@@ -738,7 +723,7 @@ public final class Bitmap implements Parcelable {
* outside of the dimensions of the source bitmap, or width is <= 0,
* or height is <= 0
*/
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) {
public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height) {
return createBitmap(source, x, y, width, height, null, false);
}
@@ -746,7 +731,8 @@ public final class Bitmap implements Parcelable {
* Returns an immutable bitmap from subset of the source bitmap,
* transformed by the optional matrix. The new bitmap may be the
* same object as source, or a copy may have been made. It is
* initialized with the same density as the original bitmap.
* initialized with the same density and color space as the original
* bitmap.
*
* If the source bitmap is immutable and the requested subset is the
* same as the source bitmap itself, then the source bitmap is
@@ -766,8 +752,8 @@ public final class Bitmap implements Parcelable {
* outside of the dimensions of the source bitmap, or width is <= 0,
* or height is <= 0
*/
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
Matrix m, boolean filter) {
public static Bitmap createBitmap(@NonNull Bitmap source, int x, int y, int width, int height,
@Nullable Matrix m, boolean filter) {
checkXYSign(x, y);
checkWidthHeight(width, height);
@@ -847,6 +833,8 @@ public final class Bitmap implements Parcelable {
}
}
nativeCopyColorSpace(source.mNativePtr, bitmap.mNativePtr);
// The new bitmap was created from a known bitmap source so assume that
// they use the same density
bitmap.mDensity = source.mDensity;
@@ -866,7 +854,8 @@ public final class Bitmap implements Parcelable {
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is as per {@link #getDensity}.
* initial density is as per {@link #getDensity}. The newly created
* bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param width The width of the bitmap
* @param height The height of the bitmap
@@ -874,13 +863,15 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
public static Bitmap createBitmap(int width, int height, Config config) {
public static Bitmap createBitmap(int width, int height, @NonNull Config config) {
return createBitmap(width, height, config, true);
}
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is determined from the given {@link DisplayMetrics}.
* The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
* color space.
*
* @param display Display metrics for the display this bitmap will be
* drawn on.
@@ -890,11 +881,31 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
public static Bitmap createBitmap(DisplayMetrics display, int width,
int height, Config config) {
public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width,
int height, @NonNull Config config) {
return createBitmap(display, width, height, config, true);
}
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is as per {@link #getDensity}. The newly created
* bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
public static Bitmap createBitmap(int width, int height,
@NonNull Config config, boolean hasAlpha) {
return createBitmap(null, width, height, config, hasAlpha);
}
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is as per {@link #getDensity}.
@@ -905,17 +916,26 @@ public final class Bitmap implements Parcelable {
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
* @param colorSpace The color space of the bitmap. If null,
* {@link ColorSpace.Named#SRGB sRGB} is assumed. This argument is
* ignored if the config is not {@link Config#ARGB_8888}.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
* @throws IllegalArgumentException if the width or height are <= 0, if
* Config is Config.HARDWARE (because hardware bitmaps are always
* immutable), 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 createBitmap(int width, int height, Config config, boolean hasAlpha) {
return createBitmap(null, width, height, config, hasAlpha);
public static Bitmap createBitmap(int width, int height, @NonNull Config config,
boolean hasAlpha, @Nullable ColorSpace colorSpace) {
return createBitmap(null, width, height, config, hasAlpha, colorSpace);
}
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is determined from the given {@link DisplayMetrics}.
* The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
* color space.
*
* @param display Display metrics for the display this bitmap will be
* drawn on.
@@ -929,15 +949,63 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* Config is Config.HARDWARE, because hardware bitmaps are always immutable
*/
public static Bitmap createBitmap(DisplayMetrics display, int width, int height,
Config config, boolean hasAlpha) {
public static Bitmap createBitmap(@Nullable DisplayMetrics display, int width, int height,
@NonNull Config config, boolean hasAlpha) {
return createBitmap(display, width, height, config, hasAlpha, null);
}
/**
* Returns a mutable bitmap with the specified width and height. Its
* initial density is determined from the given {@link DisplayMetrics}.
* The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
* color space.
*
* @param display Display metrics for the display this bitmap will be
* drawn on.
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
* @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
* mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
* @param colorSpace The color space of the bitmap. If null,
* {@link ColorSpace.Named#SRGB sRGB} is assumed. This argument is
* ignored if the config is not {@link Config#ARGB_8888}.
*
* @throws IllegalArgumentException if the width or height are <= 0, if
* Config is Config.HARDWARE (because hardware bitmaps are always
* immutable), 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 createBitmap(@Nullable DisplayMetrics display, int width, int height,
@NonNull Config config, boolean hasAlpha, @Nullable ColorSpace colorSpace) {
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("width and height must be > 0");
}
if (config == Config.HARDWARE) {
throw new IllegalArgumentException("can't create mutable bitmap with Config.HARDWARE");
}
Bitmap bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true);
Bitmap bm;
if (colorSpace == null || config != Config.ARGB_8888) {
bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true, null, null);
} else {
if (!(colorSpace instanceof ColorSpace.Rgb)) {
throw new IllegalArgumentException("colorSpace must be an RGB color space");
}
ColorSpace.Rgb rgb = (ColorSpace.Rgb) colorSpace;
ColorSpace.Rgb.TransferParameters parameters = rgb.getTransferParameters();
if (parameters == null) {
throw new IllegalArgumentException("colorSpace must use an ICC "
+ "parametric transfer function");
}
ColorSpace.Rgb d50 = (ColorSpace.Rgb) ColorSpace.adapt(rgb, ColorSpace.ILLUMINANT_D50);
bm = nativeCreate(null, 0, width, width, height, config.nativeInt, true,
d50.getTransform(), parameters);
}
if (display != null) {
bm.mDensity = display.densityDpi;
}
@@ -954,9 +1022,10 @@ public final class Bitmap implements Parcelable {
/**
* Returns a immutable bitmap with the specified width and height, with each
* pixel value set to the corresponding value in the colors array. Its
* initial density is as per {@link #getDensity}.
* initial density is as per {@link #getDensity}. The newly created
* bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param colors Array of {@link Color} used to initialize the pixels.
* @param colors Array of sRGB {@link Color colors} used to initialize the pixels.
* @param offset Number of values to skip before the first color in the
* array of colors.
* @param stride Number of colors in the array between rows (must be >=
@@ -969,8 +1038,8 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* the color array's length is less than the number of pixels.
*/
public static Bitmap createBitmap(int colors[], int offset, int stride,
int width, int height, Config config) {
public static Bitmap createBitmap(@NonNull @ColorInt int[] colors, int offset, int stride,
int width, int height, @NonNull Config config) {
return createBitmap(null, colors, offset, stride, width, height, config);
}
@@ -978,10 +1047,12 @@ public final class Bitmap implements Parcelable {
* Returns a immutable bitmap with the specified width and height, with each
* pixel value set to the corresponding value in the colors array. Its
* initial density is determined from the given {@link DisplayMetrics}.
* The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
* color space.
*
* @param display Display metrics for the display this bitmap will be
* drawn on.
* @param colors Array of {@link Color} used to initialize the pixels.
* @param colors Array of sRGB {@link Color colors} used to initialize the pixels.
* @param offset Number of values to skip before the first color in the
* array of colors.
* @param stride Number of colors in the array between rows (must be >=
@@ -994,8 +1065,9 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* the color array's length is less than the number of pixels.
*/
public static Bitmap createBitmap(DisplayMetrics display, int colors[],
int offset, int stride, int width, int height, Config config) {
public static Bitmap createBitmap(@NonNull DisplayMetrics display,
@NonNull @ColorInt int[] colors, int offset, int stride,
int width, int height, @NonNull Config config) {
checkWidthHeight(width, height);
if (Math.abs(stride) < width) {
@@ -1011,7 +1083,7 @@ public final class Bitmap implements Parcelable {
throw new IllegalArgumentException("width and height must be > 0");
}
Bitmap bm = nativeCreate(colors, offset, stride, width, height,
config.nativeInt, false);
config.nativeInt, false, null, null);
if (display != null) {
bm.mDensity = display.densityDpi;
}
@@ -1021,9 +1093,10 @@ public final class Bitmap implements Parcelable {
/**
* Returns a immutable bitmap with the specified width and height, with each
* pixel value set to the corresponding value in the colors array. Its
* initial density is as per {@link #getDensity}.
* initial density is as per {@link #getDensity}. The newly created
* bitmap is in the {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param colors Array of {@link Color} used to initialize the pixels.
* @param colors Array of sRGB {@link Color colors} used to initialize the pixels.
* This array must be at least as large as width * height.
* @param width The width of the bitmap
* @param height The height of the bitmap
@@ -1033,7 +1106,8 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* the color array's length is less than the number of pixels.
*/
public static Bitmap createBitmap(int colors[], int width, int height, Config config) {
public static Bitmap createBitmap(@NonNull @ColorInt int[] colors,
int width, int height, Config config) {
return createBitmap(null, colors, 0, width, width, height, config);
}
@@ -1041,10 +1115,12 @@ public final class Bitmap implements Parcelable {
* Returns a immutable bitmap with the specified width and height, with each
* pixel value set to the corresponding value in the colors array. Its
* initial density is determined from the given {@link DisplayMetrics}.
* The newly created bitmap is in the {@link ColorSpace.Named#SRGB sRGB}
* color space.
*
* @param display Display metrics for the display this bitmap will be
* drawn on.
* @param colors Array of {@link Color} used to initialize the pixels.
* @param colors Array of sRGB {@link Color colors} used to initialize the pixels.
* This array must be at least as large as width * height.
* @param width The width of the bitmap
* @param height The height of the bitmap
@@ -1054,8 +1130,8 @@ public final class Bitmap implements Parcelable {
* @throws IllegalArgumentException if the width or height are <= 0, or if
* the color array's length is less than the number of pixels.
*/
public static Bitmap createBitmap(DisplayMetrics display, int colors[],
int width, int height, Config config) {
public static Bitmap createBitmap(@Nullable DisplayMetrics display,
@NonNull @ColorInt int colors[], int width, int height, @NonNull Config config) {
return createBitmap(display, colors, 0, width, width, height, config);
}
@@ -1806,7 +1882,9 @@ public final class Bitmap implements Parcelable {
private static native Bitmap nativeCreate(int[] colors, int offset,
int stride, int width, int height,
int nativeConfig, boolean mutable);
int nativeConfig, boolean mutable,
@Nullable @Size(9) float[] xyzD50,
@Nullable ColorSpace.Rgb.TransferParameters p);
private static native Bitmap nativeCopy(long nativeSrcBitmap, int nativeConfig,
boolean isMutable);
private static native Bitmap nativeCopyAshmem(long nativeSrcBitmap);
@@ -1865,4 +1943,5 @@ public final class Bitmap implements Parcelable {
private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
private static native boolean nativeGetColorSpace(long nativePtr, float[] xyz, float[] params);
private static native boolean nativeIsSRGB(long nativePtr);
private static native void nativeCopyColorSpace(long srcBitmap, long dstBitmap);
}

View File

@@ -58,8 +58,10 @@ SkiaCanvas::SkiaCanvas(SkCanvas* canvas, XformToSRGB xformToSRGB)
}
SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
mCanvasOwned = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(), SkColorSpace::MakeSRGB());
mCanvasWrapper = SkCreateColorSpaceXformCanvas(mCanvasOwned.get(),
cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
mCanvas = mCanvasWrapper.get();
}
@@ -97,9 +99,10 @@ private:
};
void SkiaCanvas::setBitmap(const SkBitmap& bitmap) {
sk_sp<SkColorSpace> cs = bitmap.refColorSpace();
std::unique_ptr<SkCanvas> newCanvas = std::unique_ptr<SkCanvas>(new SkCanvas(bitmap));
std::unique_ptr<SkCanvas> newCanvasWrapper =
SkCreateColorSpaceXformCanvas(newCanvas.get(), SkColorSpace::MakeSRGB());
std::unique_ptr<SkCanvas> newCanvasWrapper = SkCreateColorSpaceXformCanvas(newCanvas.get(),
cs == nullptr ? SkColorSpace::MakeSRGB() : std::move(cs));
if (!bitmap.isNull()) {
// Copy the canvas matrix & clip state.

View File

@@ -322,6 +322,12 @@ sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
return sk_sp<Bitmap>(new Bitmap(graphicBuffer.get(), info));
}
void Bitmap::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
// TODO: See todo in reconfigure() below
SkImageInfo* myInfo = const_cast<SkImageInfo*>(&this->info());
*myInfo = info().makeColorSpace(std::move(colorSpace));
}
void Bitmap::reconfigure(const SkImageInfo& newInfo, size_t rowBytes, SkColorTable* ctable) {
if (kIndex_8_SkColorType != newInfo.colorType()) {
ctable = nullptr;

View File

@@ -16,6 +16,7 @@
#pragma once
#include <SkBitmap.h>
#include <SkColorSpace.h>
#include <SkColorTable.h>
#include <SkImageInfo.h>
#include <SkPixelRef.h>
@@ -82,6 +83,7 @@ public:
void reconfigure(const SkImageInfo& info, size_t rowBytes, SkColorTable* ctable);
void reconfigure(const SkImageInfo& info);
void setColorSpace(sk_sp<SkColorSpace> colorSpace);
void setAlphaType(SkAlphaType alphaType);
void getSkBitmap(SkBitmap* outBitmap);