summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp87
-rw-r--r--core/jni/android/graphics/Graphics.cpp9
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h1
-rw-r--r--graphics/java/android/graphics/Bitmap.java16
4 files changed, 92 insertions, 21 deletions
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index e4493b1f489a..f85219453212 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -8,6 +8,8 @@
#include "SkImageInfo.h"
#include "SkColor.h"
#include "SkColorPriv.h"
+#include "SkColorSpace.h"
+#include "SkColorSpaceXform.h"
#include "SkHalf.h"
#include "SkMatrix44.h"
#include "SkPM4f.h"
@@ -29,6 +31,7 @@
#include "core_jni_helpers.h"
#include <jni.h>
+#include <string.h>
#include <memory>
#include <string>
@@ -448,11 +451,32 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int
// reset to to actual choice from caller
dst = dstBitmap.getAddr(x, y);
- // now copy/convert each scanline
- for (int y = 0; y < height; y++) {
- proc(dst, src, width, x, y);
- src += srcStride;
- dst = (char*)dst + dstBitmap.rowBytes();
+
+ SkColorSpace* colorSpace = dstBitmap.colorSpace();
+ if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ // now copy/convert each scanline
+ for (int y = 0; y < height; y++) {
+ proc(dst, src, width, x, y);
+ src += srcStride;
+ dst = (char*)dst + dstBitmap.rowBytes();
+ }
+ } else {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+
+ std::unique_ptr<SkColor[]> row(new SkColor[width]);
+
+ // now copy/convert each scanline
+ for (int y = 0; y < height; y++) {
+ memcpy(row.get(), src, sizeof(SkColor) * width);
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
+ SkAlphaType::kUnpremul_SkAlphaType);
+
+ proc(dst, row.get(), width, x, y);
+ src += srcStride;
+ dst = (char*)dst + dstBitmap.rowBytes();
+ }
}
dstBitmap.notifyPixelsChanged();
@@ -1179,12 +1203,7 @@ static jboolean Bitmap_isSRGB(JNIEnv* env, jobject, jlong bitmapHandle) {
if (!bitmapHolder.valid()) return JNI_TRUE;
SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
- return colorSpace == nullptr ||
- colorSpace == SkColorSpace::MakeSRGB().get() ||
- colorSpace == SkColorSpace::MakeRGB(
- SkColorSpace::kSRGB_RenderTargetGamma,
- SkColorSpace::kSRGB_Gamut,
- SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+ return GraphicsJNI::isColorSpaceSRGB(colorSpace);
}
static jboolean Bitmap_getColorSpace(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1246,6 +1265,16 @@ static jint Bitmap_getPixel(JNIEnv* env, jobject, jlong bitmapHandle,
SkColor dst[1];
proc(dst, src, 1, bitmap.getColorTable());
+
+ SkColorSpace* colorSpace = bitmap.colorSpace();
+ if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
+ SkAlphaType::kUnpremul_SkAlphaType);
+ }
+
return static_cast<jint>(dst[0]);
}
@@ -1268,11 +1297,30 @@ static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
SkColorTable* ctable = bitmap.getColorTable();
jint* dst = env->GetIntArrayElements(pixelArray, NULL);
SkColor* d = (SkColor*)dst + offset;
- while (--height >= 0) {
- proc(d, src, width, ctable);
- d += stride;
- src = (void*)((const char*)src + bitmap.rowBytes());
+
+ SkColorSpace* colorSpace = bitmap.colorSpace();
+ if (GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ while (--height >= 0) {
+ proc(d, src, width, ctable);
+ d += stride;
+ src = (void*)((const char*)src + bitmap.rowBytes());
+ }
+ } else {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
+
+ while (--height >= 0) {
+ proc(d, src, width, ctable);
+
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
+ SkAlphaType::kUnpremul_SkAlphaType);
+
+ d += stride;
+ src = (void*)((const char*)src + bitmap.rowBytes());
+ }
}
+
env->ReleaseIntArrayElements(pixelArray, dst, 0);
}
@@ -1293,6 +1341,15 @@ static void Bitmap_setPixel(JNIEnv* env, jobject, jlong bitmapHandle,
return;
}
+ SkColorSpace* colorSpace = bitmap.colorSpace();
+ if (!GraphicsJNI::isColorSpaceSRGB(colorSpace)) {
+ auto sRGB = SkColorSpace::MakeSRGB();
+ auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
+ xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
+ SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
+ SkAlphaType::kUnpremul_SkAlphaType);
+ }
+
proc(bitmap.getAddr(x, y), &color, 1, x, y);
bitmap.notifyPixelsChanged();
}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 5d7310167b7c..7c56c7bf4158 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -460,6 +460,15 @@ sk_sp<SkColorSpace> GraphicsJNI::colorSpaceForType(SkColorType type) {
}
}
+bool GraphicsJNI::isColorSpaceSRGB(SkColorSpace* colorSpace) {
+ return colorSpace == nullptr
+ || colorSpace == SkColorSpace::MakeSRGB().get()
+ || colorSpace == SkColorSpace::MakeRGB(
+ SkColorSpace::kSRGB_RenderTargetGamma,
+ SkColorSpace::kSRGB_Gamut,
+ SkColorSpace::kNonLinearBlending_ColorSpaceFlag).get();
+}
+
///////////////////////////////////////////////////////////////////////////////
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 8a1ef6ee5d34..7d7c88159a55 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -111,6 +111,7 @@ public:
static sk_sp<SkColorSpace> defaultColorSpace();
static sk_sp<SkColorSpace> linearColorSpace();
static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
+ static bool isColorSpaceSRGB(SkColorSpace* colorSpace);
};
class HeapAllocator : public SkBRDAllocator {
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 6bb8a2cac430..3d5ba7938b31 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -522,7 +522,7 @@ public final class Bitmap implements Parcelable {
* <p>The content of the bitmap is copied into the buffer as-is. This means
* that if this bitmap stores its pixels pre-multiplied
* (see {@link #isPremultiplied()}, the values in the buffer will also be
- * pre-multiplied.</p>
+ * pre-multiplied. The pixels remain in the color space of the bitmap.</p>
* <p>After this method returns, the current position of the buffer is
* updated: the position is incremented by the number of elements written
* in the buffer.</p>
@@ -562,7 +562,8 @@ public final class Bitmap implements Parcelable {
* <p>Copy the pixels from the buffer, beginning at the current position,
* overwriting the bitmap's pixels. The data in the buffer is not changed
* in any way (unlike setPixels(), which converts from unpremultipled 32bit
- * to whatever the bitmap's native format is.</p>
+ * to whatever the bitmap's native format is. The pixels in the source
+ * buffer are assumed to be in the bitmap's color space.</p>
* <p>After this method returns, the current position of the buffer is
* updated: the position is incremented by the number of elements read from
* the buffer. If you need to read the bitmap from the buffer again you must
@@ -1495,7 +1496,8 @@ public final class Bitmap implements Parcelable {
/**
* Returns the {@link Color} at the specified location. Throws an exception
* if x or y are out of bounds (negative or >= to the width or height
- * respectively). The returned color is a non-premultiplied ARGB value.
+ * respectively). The returned color is a non-premultiplied ARGB value in
+ * the {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param x The x coordinate (0...width-1) of the pixel to return
* @param y The y coordinate (0...height-1) of the pixel to return
@@ -1517,7 +1519,8 @@ public final class Bitmap implements Parcelable {
* a packed int representing a {@link Color}. The stride parameter allows
* the caller to allow for gaps in the returned pixels array between
* rows. For normal packed results, just pass width for the stride value.
- * The returned colors are non-premultiplied ARGB values.
+ * The returned colors are non-premultiplied ARGB values in the
+ * {@link ColorSpace.Named#SRGB sRGB} color space.
*
* @param pixels The array to receive the bitmap's colors
* @param offset The first index to write into pixels[]
@@ -1610,7 +1613,8 @@ public final class Bitmap implements Parcelable {
/**
* <p>Write the specified {@link Color} into the bitmap (assuming it is
* mutable) at the x,y coordinate. The color must be a
- * non-premultiplied ARGB value.</p>
+ * non-premultiplied ARGB value in the {@link ColorSpace.Named#SRGB sRGB}
+ * color space.</p>
*
* @param x The x coordinate of the pixel to replace (0...width-1)
* @param y The y coordinate of the pixel to replace (0...height-1)
@@ -1632,7 +1636,7 @@ public final class Bitmap implements Parcelable {
/**
* <p>Replace pixels in the bitmap with the colors in the array. Each element
* in the array is a packed int representing a non-premultiplied ARGB
- * {@link Color}.</p>
+ * {@link Color} in the {@link ColorSpace.Named#SRGB sRGB} color space.</p>
*
* @param pixels The colors to write to the bitmap
* @param offset The index of the first color to read from pixels[]