Loading core/jni/android/graphics/Bitmap.cpp +72 −15 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -29,6 +31,7 @@ #include "core_jni_helpers.h" #include <jni.h> #include <string.h> #include <memory> #include <string> Loading Loading @@ -448,12 +451,33 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int // reset to to actual choice from caller dst = dstBitmap.getAddr(x, y); 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(); Loading Loading @@ -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, Loading Loading @@ -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]); } Loading @@ -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; 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); } Loading @@ -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(); } Loading core/jni/android/graphics/Graphics.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -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); Loading core/jni/android/graphics/GraphicsJNI.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading graphics/java/android/graphics/Bitmap.java +10 −6 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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[] Loading Loading @@ -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) Loading @@ -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[] Loading Loading
core/jni/android/graphics/Bitmap.cpp +72 −15 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -29,6 +31,7 @@ #include "core_jni_helpers.h" #include <jni.h> #include <string.h> #include <memory> #include <string> Loading Loading @@ -448,12 +451,33 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int // reset to to actual choice from caller dst = dstBitmap.getAddr(x, y); 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(); Loading Loading @@ -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, Loading Loading @@ -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]); } Loading @@ -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; 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); } Loading @@ -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(); } Loading
core/jni/android/graphics/Graphics.cpp +9 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
core/jni/android/graphics/GraphicsJNI.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
graphics/java/android/graphics/Bitmap.java +10 −6 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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 Loading @@ -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[] Loading Loading @@ -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) Loading @@ -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[] Loading