Merge "Add new RGBA_F16 bitmap config"
This commit is contained in:
committed by
Android (Google) Code Review
commit
cf4d807481
@@ -11769,6 +11769,8 @@ package android.graphics {
|
||||
method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
|
||||
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(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
|
||||
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);
|
||||
@@ -11833,6 +11835,7 @@ package android.graphics {
|
||||
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
|
||||
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
|
||||
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
|
||||
enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
|
||||
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
|
||||
}
|
||||
|
||||
@@ -12192,6 +12195,7 @@ package android.graphics {
|
||||
method public android.graphics.Bitmap render();
|
||||
method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
|
||||
method public android.graphics.ColorSpace.Renderer size(int);
|
||||
method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
|
||||
}
|
||||
|
||||
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
|
||||
@@ -12727,7 +12731,9 @@ package android.graphics {
|
||||
field public static final deprecated int RGBA_4444 = 7; // 0x7
|
||||
field public static final deprecated int RGBA_5551 = 6; // 0x6
|
||||
field public static final int RGBA_8888 = 1; // 0x1
|
||||
field public static final int RGBA_F16 = 22; // 0x16
|
||||
field public static final int RGBX_8888 = 2; // 0x2
|
||||
field public static final int RGBX_F16 = 23; // 0x17
|
||||
field public static final deprecated int RGB_332 = 11; // 0xb
|
||||
field public static final int RGB_565 = 4; // 0x4
|
||||
field public static final int RGB_888 = 3; // 0x3
|
||||
@@ -61421,31 +61427,31 @@ package java.util.concurrent {
|
||||
ctor public CopyOnWriteArrayList();
|
||||
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
|
||||
ctor public CopyOnWriteArrayList(E[]);
|
||||
method public synchronized boolean add(E);
|
||||
method public synchronized void add(int, E);
|
||||
method public synchronized boolean addAll(java.util.Collection<? extends E>);
|
||||
method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
|
||||
method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
|
||||
method public synchronized boolean addIfAbsent(E);
|
||||
method public synchronized void clear();
|
||||
method public boolean add(E);
|
||||
method public void add(int, E);
|
||||
method public boolean addAll(java.util.Collection<? extends E>);
|
||||
method public boolean addAll(int, java.util.Collection<? extends E>);
|
||||
method public int addAllAbsent(java.util.Collection<? extends E>);
|
||||
method public boolean addIfAbsent(E);
|
||||
method public void clear();
|
||||
method public java.lang.Object clone();
|
||||
method public boolean contains(java.lang.Object);
|
||||
method public boolean containsAll(java.util.Collection<?>);
|
||||
method public void forEach(java.util.function.Consumer<? super E>);
|
||||
method public E get(int);
|
||||
method public int indexOf(E, int);
|
||||
method public int indexOf(java.lang.Object);
|
||||
method public int indexOf(E, int);
|
||||
method public boolean isEmpty();
|
||||
method public java.util.Iterator<E> iterator();
|
||||
method public int lastIndexOf(E, int);
|
||||
method public int lastIndexOf(java.lang.Object);
|
||||
method public java.util.ListIterator<E> listIterator(int);
|
||||
method public int lastIndexOf(E, int);
|
||||
method public java.util.ListIterator<E> listIterator();
|
||||
method public synchronized E remove(int);
|
||||
method public synchronized boolean remove(java.lang.Object);
|
||||
method public synchronized boolean removeAll(java.util.Collection<?>);
|
||||
method public synchronized boolean retainAll(java.util.Collection<?>);
|
||||
method public synchronized E set(int, E);
|
||||
method public java.util.ListIterator<E> listIterator(int);
|
||||
method public E remove(int);
|
||||
method public boolean remove(java.lang.Object);
|
||||
method public boolean removeAll(java.util.Collection<?>);
|
||||
method public boolean retainAll(java.util.Collection<?>);
|
||||
method public E set(int, E);
|
||||
method public int size();
|
||||
method public java.util.List<E> subList(int, int);
|
||||
method public java.lang.Object[] toArray();
|
||||
|
||||
@@ -12262,6 +12262,8 @@ package android.graphics {
|
||||
method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
|
||||
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(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
|
||||
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);
|
||||
@@ -12326,6 +12328,7 @@ package android.graphics {
|
||||
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
|
||||
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
|
||||
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
|
||||
enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
|
||||
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
|
||||
}
|
||||
|
||||
@@ -12685,6 +12688,7 @@ package android.graphics {
|
||||
method public android.graphics.Bitmap render();
|
||||
method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
|
||||
method public android.graphics.ColorSpace.Renderer size(int);
|
||||
method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
|
||||
}
|
||||
|
||||
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
|
||||
@@ -13220,7 +13224,9 @@ package android.graphics {
|
||||
field public static final deprecated int RGBA_4444 = 7; // 0x7
|
||||
field public static final deprecated int RGBA_5551 = 6; // 0x6
|
||||
field public static final int RGBA_8888 = 1; // 0x1
|
||||
field public static final int RGBA_F16 = 22; // 0x16
|
||||
field public static final int RGBX_8888 = 2; // 0x2
|
||||
field public static final int RGBX_F16 = 23; // 0x17
|
||||
field public static final deprecated int RGB_332 = 11; // 0xb
|
||||
field public static final int RGB_565 = 4; // 0x4
|
||||
field public static final int RGB_888 = 3; // 0x3
|
||||
@@ -64944,31 +64950,31 @@ package java.util.concurrent {
|
||||
ctor public CopyOnWriteArrayList();
|
||||
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
|
||||
ctor public CopyOnWriteArrayList(E[]);
|
||||
method public synchronized boolean add(E);
|
||||
method public synchronized void add(int, E);
|
||||
method public synchronized boolean addAll(java.util.Collection<? extends E>);
|
||||
method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
|
||||
method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
|
||||
method public synchronized boolean addIfAbsent(E);
|
||||
method public synchronized void clear();
|
||||
method public boolean add(E);
|
||||
method public void add(int, E);
|
||||
method public boolean addAll(java.util.Collection<? extends E>);
|
||||
method public boolean addAll(int, java.util.Collection<? extends E>);
|
||||
method public int addAllAbsent(java.util.Collection<? extends E>);
|
||||
method public boolean addIfAbsent(E);
|
||||
method public void clear();
|
||||
method public java.lang.Object clone();
|
||||
method public boolean contains(java.lang.Object);
|
||||
method public boolean containsAll(java.util.Collection<?>);
|
||||
method public void forEach(java.util.function.Consumer<? super E>);
|
||||
method public E get(int);
|
||||
method public int indexOf(E, int);
|
||||
method public int indexOf(java.lang.Object);
|
||||
method public int indexOf(E, int);
|
||||
method public boolean isEmpty();
|
||||
method public java.util.Iterator<E> iterator();
|
||||
method public int lastIndexOf(E, int);
|
||||
method public int lastIndexOf(java.lang.Object);
|
||||
method public java.util.ListIterator<E> listIterator(int);
|
||||
method public int lastIndexOf(E, int);
|
||||
method public java.util.ListIterator<E> listIterator();
|
||||
method public synchronized E remove(int);
|
||||
method public synchronized boolean remove(java.lang.Object);
|
||||
method public synchronized boolean removeAll(java.util.Collection<?>);
|
||||
method public synchronized boolean retainAll(java.util.Collection<?>);
|
||||
method public synchronized E set(int, E);
|
||||
method public java.util.ListIterator<E> listIterator(int);
|
||||
method public E remove(int);
|
||||
method public boolean remove(java.lang.Object);
|
||||
method public boolean removeAll(java.util.Collection<?>);
|
||||
method public boolean retainAll(java.util.Collection<?>);
|
||||
method public E set(int, E);
|
||||
method public int size();
|
||||
method public java.util.List<E> subList(int, int);
|
||||
method public java.lang.Object[] toArray();
|
||||
|
||||
@@ -11800,6 +11800,8 @@ package android.graphics {
|
||||
method public static android.graphics.Bitmap createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean);
|
||||
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(android.util.DisplayMetrics, int, int, android.graphics.Bitmap.Config, boolean);
|
||||
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);
|
||||
@@ -11864,6 +11866,7 @@ package android.graphics {
|
||||
enum_constant public static final deprecated android.graphics.Bitmap.Config ARGB_4444;
|
||||
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
|
||||
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
|
||||
enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
|
||||
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
|
||||
}
|
||||
|
||||
@@ -12223,6 +12226,7 @@ package android.graphics {
|
||||
method public android.graphics.Bitmap render();
|
||||
method public android.graphics.ColorSpace.Renderer showWhitePoint(boolean);
|
||||
method public android.graphics.ColorSpace.Renderer size(int);
|
||||
method public android.graphics.ColorSpace.Renderer uniformChromaticityScale(boolean);
|
||||
}
|
||||
|
||||
public static class ColorSpace.Rgb extends android.graphics.ColorSpace {
|
||||
@@ -12758,7 +12762,9 @@ package android.graphics {
|
||||
field public static final deprecated int RGBA_4444 = 7; // 0x7
|
||||
field public static final deprecated int RGBA_5551 = 6; // 0x6
|
||||
field public static final int RGBA_8888 = 1; // 0x1
|
||||
field public static final int RGBA_F16 = 22; // 0x16
|
||||
field public static final int RGBX_8888 = 2; // 0x2
|
||||
field public static final int RGBX_F16 = 23; // 0x17
|
||||
field public static final deprecated int RGB_332 = 11; // 0xb
|
||||
field public static final int RGB_565 = 4; // 0x4
|
||||
field public static final int RGB_888 = 3; // 0x3
|
||||
@@ -61731,31 +61737,31 @@ package java.util.concurrent {
|
||||
ctor public CopyOnWriteArrayList();
|
||||
ctor public CopyOnWriteArrayList(java.util.Collection<? extends E>);
|
||||
ctor public CopyOnWriteArrayList(E[]);
|
||||
method public synchronized boolean add(E);
|
||||
method public synchronized void add(int, E);
|
||||
method public synchronized boolean addAll(java.util.Collection<? extends E>);
|
||||
method public synchronized boolean addAll(int, java.util.Collection<? extends E>);
|
||||
method public synchronized int addAllAbsent(java.util.Collection<? extends E>);
|
||||
method public synchronized boolean addIfAbsent(E);
|
||||
method public synchronized void clear();
|
||||
method public boolean add(E);
|
||||
method public void add(int, E);
|
||||
method public boolean addAll(java.util.Collection<? extends E>);
|
||||
method public boolean addAll(int, java.util.Collection<? extends E>);
|
||||
method public int addAllAbsent(java.util.Collection<? extends E>);
|
||||
method public boolean addIfAbsent(E);
|
||||
method public void clear();
|
||||
method public java.lang.Object clone();
|
||||
method public boolean contains(java.lang.Object);
|
||||
method public boolean containsAll(java.util.Collection<?>);
|
||||
method public void forEach(java.util.function.Consumer<? super E>);
|
||||
method public E get(int);
|
||||
method public int indexOf(E, int);
|
||||
method public int indexOf(java.lang.Object);
|
||||
method public int indexOf(E, int);
|
||||
method public boolean isEmpty();
|
||||
method public java.util.Iterator<E> iterator();
|
||||
method public int lastIndexOf(E, int);
|
||||
method public int lastIndexOf(java.lang.Object);
|
||||
method public java.util.ListIterator<E> listIterator(int);
|
||||
method public int lastIndexOf(E, int);
|
||||
method public java.util.ListIterator<E> listIterator();
|
||||
method public synchronized E remove(int);
|
||||
method public synchronized boolean remove(java.lang.Object);
|
||||
method public synchronized boolean removeAll(java.util.Collection<?>);
|
||||
method public synchronized boolean retainAll(java.util.Collection<?>);
|
||||
method public synchronized E set(int, E);
|
||||
method public java.util.ListIterator<E> listIterator(int);
|
||||
method public E remove(int);
|
||||
method public boolean remove(java.lang.Object);
|
||||
method public boolean removeAll(java.util.Collection<?>);
|
||||
method public boolean retainAll(java.util.Collection<?>);
|
||||
method public E set(int, E);
|
||||
method public int size();
|
||||
method public java.util.List<E> subList(int, int);
|
||||
method public java.lang.Object[] toArray();
|
||||
|
||||
@@ -5,7 +5,11 @@
|
||||
#include "SkPixelRef.h"
|
||||
#include "SkImageEncoder.h"
|
||||
#include "SkImageInfo.h"
|
||||
#include "SkColor.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkHalf.h"
|
||||
#include "SkPM4f.h"
|
||||
#include "SkPM4fPriv.h"
|
||||
#include "GraphicsJNI.h"
|
||||
#include "SkDither.h"
|
||||
#include "SkUnPreMultiply.h"
|
||||
@@ -232,6 +236,28 @@ using namespace android::bitmap;
|
||||
typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
|
||||
int x, int y);
|
||||
|
||||
static void FromColor_F16(void* dst, const SkColor src[], int width,
|
||||
int, int) {
|
||||
uint64_t* d = (uint64_t*)dst;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
*d++ = SkColor4f::FromColor(*src++).premul().toF16();
|
||||
}
|
||||
}
|
||||
|
||||
static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
|
||||
int, int) {
|
||||
uint64_t* d = (uint64_t*)dst;
|
||||
|
||||
for (int i = 0; i < width; i++) {
|
||||
const float* color = SkColor4f::FromColor(*src++).vec();
|
||||
uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
scratch[i] = SkFloatToHalf(color[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void FromColor_D32(void* dst, const SkColor src[], int width,
|
||||
int, int) {
|
||||
SkPMColor* d = (SkPMColor*)dst;
|
||||
@@ -321,6 +347,8 @@ static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
|
||||
return FromColor_D565;
|
||||
case kAlpha_8_SkColorType:
|
||||
return FromColor_DA8;
|
||||
case kRGBA_F16_SkColorType:
|
||||
return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -351,8 +379,7 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int
|
||||
|
||||
dstBitmap.notifyPixelsChanged();
|
||||
|
||||
env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array),
|
||||
JNI_ABORT);
|
||||
env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -361,6 +388,24 @@ bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int
|
||||
typedef void (*ToColorProc)(SkColor dst[], const void* src, int width,
|
||||
SkColorTable*);
|
||||
|
||||
static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width,
|
||||
SkColorTable*) {
|
||||
SkASSERT(width > 0);
|
||||
uint64_t* s = (uint64_t*)src;
|
||||
do {
|
||||
*dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
|
||||
} while (--width != 0);
|
||||
}
|
||||
|
||||
static void ToColor_F16_Raw(SkColor dst[], const void* src, int width,
|
||||
SkColorTable*) {
|
||||
SkASSERT(width > 0);
|
||||
uint64_t* s = (uint64_t*)src;
|
||||
do {
|
||||
*dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
|
||||
} while (--width != 0);
|
||||
}
|
||||
|
||||
static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width,
|
||||
SkColorTable*) {
|
||||
SkASSERT(width > 0);
|
||||
@@ -520,6 +565,17 @@ static ToColorProc ChooseToColorProc(const SkBitmap& src) {
|
||||
}
|
||||
case kAlpha_8_SkColorType:
|
||||
return ToColor_SA8;
|
||||
case kRGBA_F16_SkColorType:
|
||||
switch (src.alphaType()) {
|
||||
case kOpaque_SkAlphaType:
|
||||
return ToColor_F16_Raw;
|
||||
case kPremul_SkAlphaType:
|
||||
return ToColor_F16_Alpha;
|
||||
case kUnpremul_SkAlphaType:
|
||||
return ToColor_F16_Raw;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -554,7 +610,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
|
||||
|
||||
SkBitmap bitmap;
|
||||
bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType,
|
||||
GraphicsJNI::defaultColorSpace()));
|
||||
GraphicsJNI::colorSpaceForType(colorType)));
|
||||
|
||||
sk_sp<Bitmap> nativeBitmap = Bitmap::allocateHeapBitmap(&bitmap, NULL);
|
||||
if (!nativeBitmap) {
|
||||
@@ -562,8 +618,7 @@ static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
|
||||
}
|
||||
|
||||
if (jColors != NULL) {
|
||||
GraphicsJNI::SetPixels(env, jColors, offset, stride,
|
||||
0, 0, width, height, bitmap);
|
||||
GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
|
||||
}
|
||||
|
||||
return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
|
||||
@@ -790,6 +845,7 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
||||
const int density = p->readInt32();
|
||||
|
||||
if (kN32_SkColorType != colorType &&
|
||||
kRGBA_F16_SkColorType != colorType &&
|
||||
kRGB_565_SkColorType != colorType &&
|
||||
kARGB_4444_SkColorType != colorType &&
|
||||
kIndex_8_SkColorType != colorType &&
|
||||
@@ -800,8 +856,15 @@ static jobject Bitmap_createFromParcel(JNIEnv* env, jobject, jobject parcel) {
|
||||
|
||||
std::unique_ptr<SkBitmap> bitmap(new SkBitmap);
|
||||
|
||||
if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType,
|
||||
isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr), rowBytes)) {
|
||||
sk_sp<SkColorSpace> colorSpace;
|
||||
if (kRGBA_F16_SkColorType == colorType) {
|
||||
colorSpace = SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
|
||||
} else {
|
||||
colorSpace = isSRGB ? SkColorSpace::MakeNamed(SkColorSpace::kSRGB_Named) : nullptr;
|
||||
}
|
||||
|
||||
if (!bitmap->setInfo(SkImageInfo::Make(width, height, colorType, alphaType, colorSpace),
|
||||
rowBytes)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -283,8 +283,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
||||
|
||||
// Create the codec.
|
||||
NinePatchPeeker peeker;
|
||||
std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(streamDeleter.release(),
|
||||
&peeker));
|
||||
std::unique_ptr<SkAndroidCodec> codec(SkAndroidCodec::NewFromStream(
|
||||
streamDeleter.release(), &peeker));
|
||||
if (!codec.get()) {
|
||||
return nullObjectReturn("SkAndroidCodec::NewFromStream returned null");
|
||||
}
|
||||
@@ -399,7 +399,8 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
|
||||
|
||||
// We always decode to sRGB, but only mark the bitmap with a color space if linear
|
||||
// blending is enabled.
|
||||
SkImageInfo bitmapInfo = decodeInfo.makeColorSpace(GraphicsJNI::defaultColorSpace());
|
||||
SkImageInfo bitmapInfo = decodeInfo.makeColorSpace(
|
||||
GraphicsJNI::colorSpaceForType(decodeColorType));
|
||||
if (decodeColorType == kGray_8_SkColorType) {
|
||||
// The legacy implementation of BitmapFactory used kAlpha8 for
|
||||
// grayscale images (before kGray8 existed). While the codec
|
||||
|
||||
@@ -297,13 +297,16 @@ enum LegacyBitmapConfig {
|
||||
kRGB_565_LegacyBitmapConfig = 3,
|
||||
kARGB_4444_LegacyBitmapConfig = 4,
|
||||
kARGB_8888_LegacyBitmapConfig = 5,
|
||||
kHardware_LegacyBitmapConfig = 6,
|
||||
kRGBA_16F_LegacyBitmapConfig = 6,
|
||||
kHardware_LegacyBitmapConfig = 7,
|
||||
|
||||
kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
|
||||
};
|
||||
|
||||
jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
|
||||
switch (colorType) {
|
||||
case kRGBA_F16_SkColorType:
|
||||
return kRGBA_16F_LegacyBitmapConfig;
|
||||
case kN32_SkColorType:
|
||||
return kARGB_8888_LegacyBitmapConfig;
|
||||
case kARGB_4444_SkColorType:
|
||||
@@ -329,6 +332,7 @@ SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
|
||||
kRGB_565_SkColorType,
|
||||
kARGB_4444_SkColorType,
|
||||
kN32_SkColorType,
|
||||
kRGBA_F16_SkColorType,
|
||||
kN32_SkColorType
|
||||
};
|
||||
|
||||
@@ -458,6 +462,19 @@ sk_sp<SkColorSpace> GraphicsJNI::defaultColorSpace() {
|
||||
#endif
|
||||
}
|
||||
|
||||
sk_sp<SkColorSpace> GraphicsJNI::linearColorSpace() {
|
||||
return SkColorSpace::MakeNamed(SkColorSpace::kSRGBLinear_Named);
|
||||
}
|
||||
|
||||
sk_sp<SkColorSpace> GraphicsJNI::colorSpaceForType(SkColorType type) {
|
||||
switch (type) {
|
||||
case kRGBA_F16_SkColorType:
|
||||
return linearColorSpace();
|
||||
default:
|
||||
return defaultColorSpace();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
bool HeapAllocator::allocPixelRef(SkBitmap* bitmap, SkColorTable* ctable) {
|
||||
mStorage = android::Bitmap::allocateHeapBitmap(bitmap, ctable);
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
const SkBitmap& dstBitmap);
|
||||
|
||||
static sk_sp<SkColorSpace> defaultColorSpace();
|
||||
static sk_sp<SkColorSpace> linearColorSpace();
|
||||
static sk_sp<SkColorSpace> colorSpaceForType(SkColorType type);
|
||||
};
|
||||
|
||||
class HeapAllocator : public SkBRDAllocator {
|
||||
|
||||
@@ -142,6 +142,10 @@ static inline SkColorType convertPixelFormat(int32_t format) {
|
||||
return kN32_SkColorType;
|
||||
case PIXEL_FORMAT_RGBX_8888:
|
||||
return kN32_SkColorType;
|
||||
case PIXEL_FORMAT_RGBA_FP16:
|
||||
return kRGBA_F16_SkColorType;
|
||||
case PIXEL_FORMAT_RGBX_FP16:
|
||||
return kRGBA_F16_SkColorType;
|
||||
case PIXEL_FORMAT_RGB_565:
|
||||
return kRGB_565_SkColorType;
|
||||
default:
|
||||
|
||||
@@ -168,6 +168,8 @@ PublicFormat android_view_Surface_mapHalFormatDataspaceToPublicFormat(
|
||||
switch(format) {
|
||||
case HAL_PIXEL_FORMAT_RGBA_8888:
|
||||
case HAL_PIXEL_FORMAT_RGBX_8888:
|
||||
case HAL_PIXEL_FORMAT_RGBA_FP16:
|
||||
case HAL_PIXEL_FORMAT_RGBX_FP16:
|
||||
case HAL_PIXEL_FORMAT_RGB_888:
|
||||
case HAL_PIXEL_FORMAT_RGB_565:
|
||||
case HAL_PIXEL_FORMAT_Y8:
|
||||
@@ -283,6 +285,8 @@ static inline SkColorType convertPixelFormat(PixelFormat format) {
|
||||
switch (format) {
|
||||
case PIXEL_FORMAT_RGBX_8888: return kN32_SkColorType;
|
||||
case PIXEL_FORMAT_RGBA_8888: return kN32_SkColorType;
|
||||
case PIXEL_FORMAT_RGBX_FP16: return kRGBA_F16_SkColorType;
|
||||
case PIXEL_FORMAT_RGBA_FP16: return kRGBA_F16_SkColorType;
|
||||
case PIXEL_FORMAT_RGB_565: return kRGB_565_SkColorType;
|
||||
default: return kUnknown_SkColorType;
|
||||
}
|
||||
|
||||
@@ -164,6 +164,16 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
|
||||
alphaType = kPremul_SkAlphaType;
|
||||
break;
|
||||
}
|
||||
case PIXEL_FORMAT_RGBX_FP16: {
|
||||
colorType = kRGBA_F16_SkColorType;
|
||||
alphaType = kOpaque_SkAlphaType;
|
||||
break;
|
||||
}
|
||||
case PIXEL_FORMAT_RGBA_FP16: {
|
||||
colorType = kRGBA_F16_SkColorType;
|
||||
alphaType = kPremul_SkAlphaType;
|
||||
break;
|
||||
}
|
||||
case PIXEL_FORMAT_RGB_565: {
|
||||
colorType = kRGB_565_SkColorType;
|
||||
alphaType = kOpaque_SkAlphaType;
|
||||
|
||||
@@ -83,6 +83,14 @@ static inline SkImageInfo convertPixelFormat(const ANativeWindow_Buffer& buffer)
|
||||
colorType = kN32_SkColorType;
|
||||
alphaType = kOpaque_SkAlphaType;
|
||||
break;
|
||||
case WINDOW_FORMAT_RGBA_FP16:
|
||||
colorType = kRGBA_F16_SkColorType;
|
||||
alphaType = kPremul_SkAlphaType;
|
||||
break;
|
||||
case WINDOW_FORMAT_RGBX_FP16:
|
||||
colorType = kRGBA_F16_SkColorType;
|
||||
alphaType = kOpaque_SkAlphaType;
|
||||
break;
|
||||
case WINDOW_FORMAT_RGB_565:
|
||||
colorType = kRGB_565_SkColorType;
|
||||
alphaType = kOpaque_SkAlphaType;
|
||||
|
||||
BIN
docs/html/reference/images/graphics/colorspace_ucs.png
Normal file
BIN
docs/html/reference/images/graphics/colorspace_ucs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 284 KiB |
@@ -140,7 +140,7 @@ public final class Bitmap implements Parcelable {
|
||||
* Native bitmap has been reconfigured, so set premult and cached
|
||||
* width/height values
|
||||
*/
|
||||
// called from JNI
|
||||
@SuppressWarnings("unused") // called from JNI
|
||||
void reinit(int width, int height, boolean requestPremultiplied) {
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
@@ -465,6 +465,15 @@ public final class Bitmap implements Parcelable {
|
||||
*/
|
||||
ARGB_8888 (5),
|
||||
|
||||
/**
|
||||
* Each pixels is stored on 8 bytes. Each channel (RGB and alpha
|
||||
* for translucency) is stored as a
|
||||
* {@link android.util.Half half-precision floating point value}.
|
||||
*
|
||||
* This configuration is particularly suited for wide-gamut and
|
||||
* HDR content.
|
||||
*/
|
||||
RGBA_F16 (6),
|
||||
|
||||
/**
|
||||
* Special configuration, when bitmap is stored only in graphic memory.
|
||||
@@ -473,12 +482,12 @@ public final class Bitmap implements Parcelable {
|
||||
* It is optimal for cases, when the only operation with the bitmap is to draw it on a
|
||||
* screen.
|
||||
*/
|
||||
HARDWARE (6);
|
||||
HARDWARE (7);
|
||||
|
||||
final int nativeInt;
|
||||
|
||||
private static Config sConfigs[] = {
|
||||
null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, HARDWARE
|
||||
null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
|
||||
};
|
||||
|
||||
Config(int ni) {
|
||||
@@ -760,6 +769,9 @@ public final class Bitmap implements Parcelable {
|
||||
case ALPHA_8:
|
||||
newConfig = Config.ALPHA_8;
|
||||
break;
|
||||
case RGBA_F16:
|
||||
newConfig = Config.RGBA_F16;
|
||||
break;
|
||||
//noinspection deprecation
|
||||
case ARGB_4444:
|
||||
case ARGB_8888:
|
||||
@@ -781,8 +793,13 @@ public final class Bitmap implements Parcelable {
|
||||
neww = Math.round(deviceR.width());
|
||||
newh = Math.round(deviceR.height());
|
||||
|
||||
bitmap = createBitmap(neww, newh, transformed ? Config.ARGB_8888 : newConfig,
|
||||
transformed || source.hasAlpha());
|
||||
Config transformedConfig = newConfig;
|
||||
if (transformed) {
|
||||
if (transformedConfig != Config.ARGB_8888 && transformedConfig != Config.RGBA_F16) {
|
||||
transformedConfig = Config.ARGB_8888;
|
||||
}
|
||||
}
|
||||
bitmap = createBitmap(neww, newh, transformedConfig, transformed || source.hasAlpha());
|
||||
|
||||
canvas.translate(-deviceR.left, -deviceR.top);
|
||||
canvas.concat(m);
|
||||
@@ -845,14 +862,14 @@ public final class Bitmap implements Parcelable {
|
||||
* @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 this flag can be used to mark the
|
||||
* bitmap as opaque. Doing so will clear the bitmap in black
|
||||
* @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
|
||||
*/
|
||||
private static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
|
||||
public static Bitmap createBitmap(int width, int height, Config config, boolean hasAlpha) {
|
||||
return createBitmap(null, width, height, config, hasAlpha);
|
||||
}
|
||||
|
||||
@@ -865,14 +882,14 @@ public final class Bitmap implements Parcelable {
|
||||
* @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 this flag can be used to mark the
|
||||
* bitmap as opaque. Doing so will clear the bitmap in black
|
||||
* @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
|
||||
*/
|
||||
private static Bitmap createBitmap(DisplayMetrics display, int width, int height,
|
||||
public static Bitmap createBitmap(DisplayMetrics display, int width, int height,
|
||||
Config config, boolean hasAlpha) {
|
||||
if (width <= 0 || height <= 0) {
|
||||
throw new IllegalArgumentException("width and height must be > 0");
|
||||
@@ -885,7 +902,7 @@ public final class Bitmap implements Parcelable {
|
||||
bm.mDensity = display.densityDpi;
|
||||
}
|
||||
bm.setHasAlpha(hasAlpha);
|
||||
if (config == Config.ARGB_8888 && !hasAlpha) {
|
||||
if ((config == Config.ARGB_8888 || config == Config.RGBA_F16) && !hasAlpha) {
|
||||
nativeErase(bm.mNativePtr, 0xff000000);
|
||||
}
|
||||
// No need to initialize the bitmap to zeroes with other configs;
|
||||
@@ -1526,7 +1543,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 prepresenting a non-premultiplied ARGB
|
||||
* in the array is a packed int representing a non-premultiplied ARGB
|
||||
* {@link Color}.</p>
|
||||
*
|
||||
* @param pixels The colors to write to the bitmap
|
||||
|
||||
@@ -1670,6 +1670,28 @@ public abstract class ColorSpace {
|
||||
return new float[] { xyY[0] / xyY[1], 1.0f, (1 - xyY[0] - xyY[1]) / xyY[1] };
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts values from CIE xyY to CIE L*u*v*. Y is assumed to be 1 so the
|
||||
* input xyY array only contains the x and y components. After this method
|
||||
* returns, the xyY array contains the converted u and v components.
|
||||
*
|
||||
* @param xyY The xyY value to convert to XYZ, cannot be null,
|
||||
* length must be a multiple of 2
|
||||
*/
|
||||
private static void xyYToUv(@NonNull @Size(multiple = 2) float[] xyY) {
|
||||
for (int i = 0; i < xyY.length; i += 2) {
|
||||
float x = xyY[i];
|
||||
float y = xyY[i + 1];
|
||||
|
||||
float d = -2.0f * x + 12.0f * y + 3;
|
||||
float u = (4.0f * x) / d;
|
||||
float v = (9.0f * y) / d;
|
||||
|
||||
xyY[i] = u;
|
||||
xyY[i + 1] = v;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Computes the chromatic adaptation transform from the specified
|
||||
* source white point to the specified destination white point.</p>
|
||||
@@ -3162,10 +3184,10 @@ public abstract class ColorSpace {
|
||||
/**
|
||||
* <p>A color space renderer can be used to visualize and compare the gamut and
|
||||
* white point of one or more color spaces. The output is an sRGB {@link Bitmap}
|
||||
* showing a CIE 1931 xyY chromaticity diagram.</p>
|
||||
* showing a CIE 1931 xyY or a CIE 1976 UCS chromaticity diagram.</p>
|
||||
*
|
||||
* <p>The following code snippet shows how to compare the {@link Named#SRGB}
|
||||
* and {@link Named#DCI_P3} color spaces:</p>
|
||||
* and {@link Named#DCI_P3} color spaces in a CIE 1931 diagram:</p>
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* Bitmap bitmap = ColorSpace.createRenderer()
|
||||
@@ -3188,12 +3210,18 @@ public abstract class ColorSpace {
|
||||
*/
|
||||
public static class Renderer {
|
||||
private static final int NATIVE_SIZE = 1440;
|
||||
private static final float UCS_SCALE = 9.0f / 6.0f;
|
||||
|
||||
// Number of subdivision of the inside of the spectral locus
|
||||
private static final int CHROMATICITY_RESOLUTION = 32;
|
||||
private static final double ONE_THIRD = 1.0 / 3.0;
|
||||
|
||||
@IntRange(from = 128, to = Integer.MAX_VALUE)
|
||||
private int mSize = 1024;
|
||||
|
||||
private boolean mShowWhitePoint = true;
|
||||
private boolean mClip = false;
|
||||
private boolean mUcs = false;
|
||||
|
||||
private final List<Pair<ColorSpace, Integer>> mColorSpaces = new ArrayList<>(2);
|
||||
private final List<Point> mPoints = new ArrayList<>(0);
|
||||
@@ -3240,6 +3268,35 @@ public abstract class ColorSpace {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Defines whether the chromaticity diagram should use the uniform
|
||||
* chromaticity scale (CIE 1976 UCS). When the uniform chromaticity scale
|
||||
* is used, the distance between two points on the diagram is approximately
|
||||
* proportional to the perceived color difference.</p>
|
||||
*
|
||||
* <p>The following code snippet shows how to enable the uniform chromaticity
|
||||
* scale. The image below shows the result:</p>
|
||||
* <pre class="prettyprint">
|
||||
* Bitmap bitmap = ColorSpace.createRenderer()
|
||||
* .uniformChromaticityScale(true)
|
||||
* .add(ColorSpace.get(ColorSpace.Named.SRGB), 0xffffffff)
|
||||
* .add(ColorSpace.get(ColorSpace.Named.DCI_P3), 0xffffc845)
|
||||
* .render();
|
||||
* </pre>
|
||||
* <p>
|
||||
* <img src="{@docRoot}reference/android/images/graphics/colorspace_ucs.png" />
|
||||
* <figcaption style="text-align: center;">CIE 1976 UCS diagram</figcaption>
|
||||
* </p>
|
||||
*
|
||||
* @param ucs True to render the chromaticity diagram as the CIE 1976 UCS diagram
|
||||
* @return This instance of {@link Renderer}
|
||||
*/
|
||||
@NonNull
|
||||
public Renderer uniformChromaticityScale(boolean ucs) {
|
||||
mUcs = ucs;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dimensions (width and height) in pixels of the output bitmap.
|
||||
* The size must be at least 128px and defaults to 1024px.
|
||||
@@ -3302,7 +3359,7 @@ public abstract class ColorSpace {
|
||||
* </pre>
|
||||
* <p>
|
||||
* <img src="{@docRoot}reference/android/images/graphics/colorspace_comparison2.png" />
|
||||
* <figcaption style="text-align: center;">sRGB vs DCI-P3</figcaption>
|
||||
* <figcaption style="text-align: center;">sRGB, DCI-P3, ACES and scRGB</figcaption>
|
||||
* </p>
|
||||
*
|
||||
* @param colorSpace The color space whose gamut to render on the diagram
|
||||
@@ -3385,6 +3442,7 @@ public abstract class ColorSpace {
|
||||
|
||||
setTransform(canvas, width, height, primaries);
|
||||
drawBox(canvas, width, height, paint, path);
|
||||
setUcsTransform(canvas, height);
|
||||
drawLocus(canvas, width, height, paint, path, primaries);
|
||||
drawGamuts(canvas, width, height, paint, path, primaries, whitePoint);
|
||||
drawPoints(canvas, width, height, paint);
|
||||
@@ -3406,7 +3464,11 @@ public abstract class ColorSpace {
|
||||
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
|
||||
float radius = 4.0f / (mUcs ? UCS_SCALE : 1.0f);
|
||||
|
||||
float[] v = new float[3];
|
||||
float[] xy = new float[2];
|
||||
|
||||
for (final Point point : mPoints) {
|
||||
v[0] = point.mRgb[0];
|
||||
v[1] = point.mRgb[1];
|
||||
@@ -3415,10 +3477,13 @@ public abstract class ColorSpace {
|
||||
|
||||
paint.setColor(point.mColor);
|
||||
|
||||
// XYZ to xyY, assuming Y=1.0
|
||||
// XYZ to xyY, assuming Y=1.0, then to L*u*v* if needed
|
||||
float sum = v[0] + v[1] + v[2];
|
||||
canvas.drawCircle(width * v[0] / sum, height - height * v[1] / sum,
|
||||
4.0f, paint);
|
||||
xy[0] = v[0] / sum;
|
||||
xy[1] = v[1] / sum;
|
||||
if (mUcs) xyYToUv(xy);
|
||||
|
||||
canvas.drawCircle(width * xy[0], height - height * xy[1], radius, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3440,6 +3505,8 @@ public abstract class ColorSpace {
|
||||
@NonNull Paint paint, @NonNull Path path,
|
||||
@NonNull @Size(6) float[] primaries, @NonNull @Size(2) float[] whitePoint) {
|
||||
|
||||
float radius = 4.0f / (mUcs ? UCS_SCALE : 1.0f);
|
||||
|
||||
for (final Pair<ColorSpace, Integer> item : mColorSpaces) {
|
||||
ColorSpace colorSpace = item.first;
|
||||
int color = item.second;
|
||||
@@ -3447,7 +3514,7 @@ public abstract class ColorSpace {
|
||||
if (colorSpace.getModel() != Model.RGB) continue;
|
||||
|
||||
Rgb rgb = (Rgb) colorSpace;
|
||||
getPrimaries(rgb, primaries);
|
||||
getPrimaries(rgb, primaries, mUcs);
|
||||
|
||||
path.rewind();
|
||||
path.moveTo(width * primaries[0], height - height * primaries[1]);
|
||||
@@ -3462,11 +3529,12 @@ public abstract class ColorSpace {
|
||||
// Draw the white point
|
||||
if (mShowWhitePoint) {
|
||||
rgb.getWhitePoint(whitePoint);
|
||||
if (mUcs) xyYToUv(whitePoint);
|
||||
|
||||
paint.setStyle(Paint.Style.FILL);
|
||||
paint.setColor(color);
|
||||
canvas.drawCircle(width * whitePoint[0], height - height * whitePoint[1],
|
||||
4.0f, paint);
|
||||
canvas.drawCircle(
|
||||
width * whitePoint[0], height - height * whitePoint[1], radius, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3477,10 +3545,12 @@ public abstract class ColorSpace {
|
||||
*
|
||||
* @param rgb The color space whose primaries to extract
|
||||
* @param primaries A pre-allocated array of 6 floats that will hold the result
|
||||
* @param asUcs True if the primaries should be returned in Luv, false for xyY
|
||||
*/
|
||||
@NonNull
|
||||
@Size(6)
|
||||
private static float[] getPrimaries(@NonNull Rgb rgb, @NonNull @Size(6) float[] primaries) {
|
||||
private static float[] getPrimaries(@NonNull Rgb rgb,
|
||||
@NonNull @Size(6) float[] primaries, boolean asUcs) {
|
||||
// TODO: We should find a better way to handle these cases
|
||||
if (rgb.equals(ColorSpace.get(Named.EXTENDED_SRGB)) ||
|
||||
rgb.equals(ColorSpace.get(Named.LINEAR_EXTENDED_SRGB))) {
|
||||
@@ -3490,9 +3560,11 @@ public abstract class ColorSpace {
|
||||
primaries[3] = 1.24f;
|
||||
primaries[4] = -0.23f;
|
||||
primaries[5] = -0.57f;
|
||||
return primaries;
|
||||
} else {
|
||||
rgb.getPrimaries(primaries);
|
||||
}
|
||||
return rgb.getPrimaries(primaries);
|
||||
if (asUcs) xyYToUv(primaries);
|
||||
return primaries;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3513,7 +3585,13 @@ public abstract class ColorSpace {
|
||||
int vertexCount = SPECTRUM_LOCUS_X.length * CHROMATICITY_RESOLUTION * 6;
|
||||
float[] vertices = new float[vertexCount * 2];
|
||||
int[] colors = new int[vertices.length];
|
||||
computeChromaticityMesh(NATIVE_SIZE, NATIVE_SIZE, vertices, colors);
|
||||
computeChromaticityMesh(vertices, colors);
|
||||
|
||||
if (mUcs) xyYToUv(vertices);
|
||||
for (int i = 0; i < vertices.length; i += 2) {
|
||||
vertices[i] *= width;
|
||||
vertices[i + 1] = height - vertices[i + 1] * height;
|
||||
}
|
||||
|
||||
// Draw the spectral locus
|
||||
if (mClip && mColorSpaces.size() > 0) {
|
||||
@@ -3522,7 +3600,8 @@ public abstract class ColorSpace {
|
||||
if (colorSpace.getModel() != Model.RGB) continue;
|
||||
|
||||
Rgb rgb = (Rgb) colorSpace;
|
||||
getPrimaries(rgb, primaries);
|
||||
getPrimaries(rgb, primaries, mUcs);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3559,6 +3638,7 @@ public abstract class ColorSpace {
|
||||
}
|
||||
path.close();
|
||||
|
||||
paint.setStrokeWidth(4.0f / (mUcs ? UCS_SCALE : 1.0f));
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setColor(0xff000000);
|
||||
canvas.drawPath(path, paint);
|
||||
@@ -3576,25 +3656,38 @@ public abstract class ColorSpace {
|
||||
*/
|
||||
private void drawBox(@NonNull Canvas canvas, int width, int height, @NonNull Paint paint,
|
||||
@NonNull Path path) {
|
||||
|
||||
int lineCount = 10;
|
||||
float scale = 1.0f;
|
||||
if (mUcs) {
|
||||
lineCount = 7;
|
||||
scale = UCS_SCALE;
|
||||
}
|
||||
|
||||
// Draw the unit grid
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(2.0f);
|
||||
paint.setColor(0xffc0c0c0);
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
canvas.drawLine(0.0f, height - (height * i / 10.0f),
|
||||
0.9f * width, height - (height * i / 10.0f), paint);
|
||||
canvas.drawLine(width * i / 10.0f, height,
|
||||
width * i / 10.0f, 0.1f * height, paint);
|
||||
|
||||
for (int i = 1; i < lineCount - 1; i++) {
|
||||
float v = i / 10.0f;
|
||||
float x = (width * v) * scale;
|
||||
float y = height - (height * v) * scale;
|
||||
|
||||
canvas.drawLine(0.0f, y, 0.9f * width, y, paint);
|
||||
canvas.drawLine(x, height, x, 0.1f * height, paint);
|
||||
}
|
||||
|
||||
// Draw tick marks
|
||||
paint.setStrokeWidth(4.0f);
|
||||
paint.setColor(0xff000000);
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
canvas.drawLine(0.0f, height - (height * i / 10.0f),
|
||||
width / 100.0f, height - (height * i / 10.0f), paint);
|
||||
canvas.drawLine(width * i / 10.0f, height,
|
||||
width * i / 10.0f, height - (height / 100.0f), paint);
|
||||
for (int i = 1; i < lineCount - 1; i++) {
|
||||
float v = i / 10.0f;
|
||||
float x = (width * v) * scale;
|
||||
float y = height - (height * v) * scale;
|
||||
|
||||
canvas.drawLine(0.0f, y, width / 100.0f, y, paint);
|
||||
canvas.drawLine(x, height, x, height - (height / 100.0f), paint);
|
||||
}
|
||||
|
||||
// Draw the axis labels
|
||||
@@ -3603,14 +3696,15 @@ public abstract class ColorSpace {
|
||||
paint.setTypeface(Typeface.create("sans-serif-light", Typeface.NORMAL));
|
||||
|
||||
Rect bounds = new Rect();
|
||||
for (int i = 1; i < 9; i++) {
|
||||
for (int i = 1; i < lineCount - 1; i++) {
|
||||
String text = "0." + i;
|
||||
paint.getTextBounds(text, 0, text.length(), bounds);
|
||||
|
||||
float y = height - (height * i / 10.0f);
|
||||
canvas.drawText(text, -0.05f * width + 10, y + bounds.height() / 2.0f, paint);
|
||||
float v = i / 10.0f;
|
||||
float x = (width * v) * scale;
|
||||
float y = height - (height * v) * scale;
|
||||
|
||||
float x = width * i / 10.0f;
|
||||
canvas.drawText(text, -0.05f * width + 10, y + bounds.height() / 2.0f, paint);
|
||||
canvas.drawText(text, x - bounds.width() / 2.0f,
|
||||
height + bounds.height() + 16, paint);
|
||||
}
|
||||
@@ -3643,7 +3737,7 @@ public abstract class ColorSpace {
|
||||
if (colorSpace.getModel() != Model.RGB) continue;
|
||||
|
||||
Rgb rgb = (Rgb) colorSpace;
|
||||
getPrimaries(rgb, primaries);
|
||||
getPrimaries(rgb, primaries, mUcs);
|
||||
|
||||
primariesBounds.left = Math.min(primariesBounds.left, primaries[4]);
|
||||
primariesBounds.top = Math.min(primariesBounds.top, primaries[5]);
|
||||
@@ -3651,26 +3745,42 @@ public abstract class ColorSpace {
|
||||
primariesBounds.bottom = Math.max(primariesBounds.bottom, primaries[3]);
|
||||
}
|
||||
|
||||
float max = mUcs ? 0.6f : 0.9f;
|
||||
|
||||
primariesBounds.left = Math.min(0.0f, primariesBounds.left);
|
||||
primariesBounds.top = Math.min(0.0f, primariesBounds.top);
|
||||
primariesBounds.right = Math.max(0.9f, primariesBounds.right);
|
||||
primariesBounds.bottom = Math.max(0.9f, primariesBounds.bottom);
|
||||
primariesBounds.right = Math.max(max, primariesBounds.right);
|
||||
primariesBounds.bottom = Math.max(max, primariesBounds.bottom);
|
||||
|
||||
float scaleX = 0.9f / primariesBounds.width();
|
||||
float scaleY = 0.9f / primariesBounds.height();
|
||||
float scaleX = max / primariesBounds.width();
|
||||
float scaleY = max / primariesBounds.height();
|
||||
float scale = Math.min(scaleX, scaleY);
|
||||
|
||||
canvas.scale(mSize / (float) NATIVE_SIZE, mSize / (float) NATIVE_SIZE);
|
||||
canvas.scale(scale, scale);
|
||||
canvas.translate(
|
||||
(primariesBounds.width() - 0.9f) * width / 2.0f,
|
||||
(primariesBounds.height() - 0.9f) * height / 2.0f);
|
||||
(primariesBounds.width() - max) * width / 2.0f,
|
||||
(primariesBounds.height() - max) * height / 2.0f);
|
||||
|
||||
// The spectrum extends ~0.85 vertically and ~0.65 horizontally
|
||||
// We shift the canvas a little bit to get nicer margins
|
||||
canvas.translate(0.05f * width, -0.05f * height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and applies the Canvas transforms required to render the CIE
|
||||
* 197 UCS chromaticity diagram.
|
||||
*
|
||||
* @param canvas The canvas to transform
|
||||
* @param height Height in pixel of the final image
|
||||
*/
|
||||
private void setUcsTransform(@NonNull Canvas canvas, int height) {
|
||||
if (mUcs) {
|
||||
canvas.translate(0.0f, (height - height * UCS_SCALE));
|
||||
canvas.scale(UCS_SCALE, UCS_SCALE);
|
||||
}
|
||||
}
|
||||
|
||||
// X coordinates of the spectral locus in CIE 1931
|
||||
private static final float[] SPECTRUM_LOCUS_X = {
|
||||
0.175596f, 0.172787f, 0.170806f, 0.170085f, 0.160343f,
|
||||
@@ -3716,21 +3826,15 @@ public abstract class ColorSpace {
|
||||
0.037799f, 0.029673f, 0.021547f, 0.013421f, 0.005295f
|
||||
};
|
||||
|
||||
// Number of subdivision of the inside of the spectral locus
|
||||
private static final int CHROMATICITY_RESOLUTION = 32;
|
||||
private static final double ONE_THIRD = 1.0 / 3.0;
|
||||
|
||||
/**
|
||||
* Computes a 2D mesh representation of the CIE 1931 chromaticity
|
||||
* diagram.
|
||||
*
|
||||
* @param width Width in pixels of the mesh
|
||||
* @param height Height in pixels of the mesh
|
||||
* @param vertices Array of floats that will hold the mesh vertices
|
||||
* @param colors Array of floats that will hold the mesh colors
|
||||
*/
|
||||
private static void computeChromaticityMesh(int width, int height,
|
||||
@NonNull float[] vertices, @NonNull int[] colors) {
|
||||
private static void computeChromaticityMesh(@NonNull float[] vertices,
|
||||
@NonNull int[] colors) {
|
||||
|
||||
ColorSpace colorSpace = get(Named.SRGB);
|
||||
|
||||
@@ -3796,18 +3900,18 @@ public abstract class ColorSpace {
|
||||
colorIndex += 6;
|
||||
|
||||
// Flip the mesh upside down to match Canvas' coordinates system
|
||||
vertices[vertexIndex++] = v1x * width;
|
||||
vertices[vertexIndex++] = height - v1y * height;
|
||||
vertices[vertexIndex++] = v2x * width;
|
||||
vertices[vertexIndex++] = height - v2y * height;
|
||||
vertices[vertexIndex++] = v3x * width;
|
||||
vertices[vertexIndex++] = height - v3y * height;
|
||||
vertices[vertexIndex++] = v1x * width;
|
||||
vertices[vertexIndex++] = height - v1y * height;
|
||||
vertices[vertexIndex++] = v3x * width;
|
||||
vertices[vertexIndex++] = height - v3y * height;
|
||||
vertices[vertexIndex++] = v4x * width;
|
||||
vertices[vertexIndex++] = height - v4y * height;
|
||||
vertices[vertexIndex++] = v1x;
|
||||
vertices[vertexIndex++] = v1y;
|
||||
vertices[vertexIndex++] = v2x;
|
||||
vertices[vertexIndex++] = v2y;
|
||||
vertices[vertexIndex++] = v3x;
|
||||
vertices[vertexIndex++] = v3y;
|
||||
vertices[vertexIndex++] = v1x;
|
||||
vertices[vertexIndex++] = v1y;
|
||||
vertices[vertexIndex++] = v3x;
|
||||
vertices[vertexIndex++] = v3y;
|
||||
vertices[vertexIndex++] = v4x;
|
||||
vertices[vertexIndex++] = v4y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,13 +22,17 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
public class PixelFormat {
|
||||
|
||||
/** @hide */
|
||||
@IntDef({UNKNOWN, TRANSLUCENT, TRANSPARENT, OPAQUE})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Opacity {}
|
||||
|
||||
/* these constants need to match those in hardware/hardware.h */
|
||||
/** @hide */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef({RGBA_8888, RGBX_8888, RGBA_F16, RGBX_F16, RGB_888, RGB_565})
|
||||
public @interface Format { };
|
||||
|
||||
// NOTE: these constants must match the values from graphics/common/x.x/types.hal
|
||||
|
||||
public static final int UNKNOWN = 0;
|
||||
|
||||
@@ -62,7 +66,6 @@ public class PixelFormat {
|
||||
@Deprecated
|
||||
public static final int RGB_332 = 0xB;
|
||||
|
||||
|
||||
/**
|
||||
* @deprecated use {@link android.graphics.ImageFormat#NV16
|
||||
* ImageFormat.NV16} instead.
|
||||
@@ -84,6 +87,9 @@ public class PixelFormat {
|
||||
@Deprecated
|
||||
public static final int YCbCr_422_I = 0x14;
|
||||
|
||||
public static final int RGBA_F16 = 0x16;
|
||||
public static final int RGBX_F16 = 0x17;
|
||||
|
||||
/**
|
||||
* @deprecated use {@link android.graphics.ImageFormat#JPEG
|
||||
* ImageFormat.JPEG} instead.
|
||||
@@ -91,7 +97,10 @@ public class PixelFormat {
|
||||
@Deprecated
|
||||
public static final int JPEG = 0x100;
|
||||
|
||||
public static void getPixelFormatInfo(int format, PixelFormat info) {
|
||||
public int bytesPerPixel;
|
||||
public int bitsPerPixel;
|
||||
|
||||
public static void getPixelFormatInfo(@Format int format, PixelFormat info) {
|
||||
switch (format) {
|
||||
case RGBA_8888:
|
||||
case RGBX_8888:
|
||||
@@ -124,18 +133,24 @@ public class PixelFormat {
|
||||
info.bitsPerPixel = 12;
|
||||
info.bytesPerPixel = 1;
|
||||
break;
|
||||
case RGBA_F16:
|
||||
case RGBX_F16:
|
||||
info.bitsPerPixel = 64;
|
||||
info.bytesPerPixel = 8;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("unknown pixel format " + format);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean formatHasAlpha(int format) {
|
||||
public static boolean formatHasAlpha(@Format int format) {
|
||||
switch (format) {
|
||||
case PixelFormat.A_8:
|
||||
case PixelFormat.LA_88:
|
||||
case PixelFormat.RGBA_4444:
|
||||
case PixelFormat.RGBA_5551:
|
||||
case PixelFormat.RGBA_8888:
|
||||
case PixelFormat.RGBA_F16:
|
||||
case PixelFormat.TRANSLUCENT:
|
||||
case PixelFormat.TRANSPARENT:
|
||||
return true;
|
||||
@@ -143,9 +158,6 @@ public class PixelFormat {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int bytesPerPixel;
|
||||
public int bitsPerPixel;
|
||||
|
||||
/**
|
||||
* Determine whether or not this is a public-visible and non-deprecated {@code format}.
|
||||
*
|
||||
@@ -159,12 +171,14 @@ public class PixelFormat {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isPublicFormat(int format) {
|
||||
public static boolean isPublicFormat(@Format int format) {
|
||||
switch (format) {
|
||||
case RGBA_8888:
|
||||
case RGBX_8888:
|
||||
case RGB_888:
|
||||
case RGB_565:
|
||||
case RGBA_F16:
|
||||
case RGBX_F16:
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,6 +131,13 @@ inline CopyResult copyTextureInto(Caches& caches, RenderState& renderState,
|
||||
destWidth, destHeight, caches.maxTextureSize);
|
||||
return CopyResult::DestinationInvalid;
|
||||
}
|
||||
|
||||
// TODO: Add support for RGBA_F16 destinations
|
||||
if (bitmap->colorType() == kRGBA_F16_SkColorType) {
|
||||
ALOGW("Can't copy surface into bitmap, RGBA_F16 config is not supported");
|
||||
return CopyResult::DestinationInvalid;
|
||||
}
|
||||
|
||||
GLuint fbo = renderState.createFramebuffer();
|
||||
if (!fbo) {
|
||||
ALOGW("Could not obtain an FBO");
|
||||
|
||||
@@ -225,6 +225,12 @@ void Texture::colorTypeToGlFormatAndType(const Caches& caches, SkColorType color
|
||||
*outInternalFormat = GL_LUMINANCE;
|
||||
*outType = GL_UNSIGNED_BYTE;
|
||||
break;
|
||||
case kRGBA_F16_SkColorType:
|
||||
// This format is always linear
|
||||
*outFormat = GL_RGBA;
|
||||
*outInternalFormat = GL_RGBA16F;
|
||||
*outType = GL_HALF_FLOAT;
|
||||
break;
|
||||
default:
|
||||
LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType);
|
||||
break;
|
||||
|
||||
@@ -108,6 +108,8 @@ static PixelFormat internalFormatToPixelFormat(GLint internalFormat) {
|
||||
return PIXEL_FORMAT_RGBA_8888;
|
||||
case GL_RGB:
|
||||
return PIXEL_FORMAT_RGB_565;
|
||||
case GL_RGBA16F:
|
||||
return PIXEL_FORMAT_RGBA_FP16;
|
||||
default:
|
||||
LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", internalFormat);
|
||||
return PIXEL_FORMAT_UNKNOWN;
|
||||
@@ -306,7 +308,8 @@ sk_sp<Bitmap> Bitmap::createFrom(const SkImageInfo& info, SkPixelRef& pixelRef)
|
||||
|
||||
sk_sp<Bitmap> Bitmap::createFrom(sp<GraphicBuffer> graphicBuffer) {
|
||||
PixelFormat format = graphicBuffer->getPixelFormat();
|
||||
if (!graphicBuffer.get() || format != PIXEL_FORMAT_RGBA_8888) {
|
||||
if (!graphicBuffer.get() ||
|
||||
(format != PIXEL_FORMAT_RGBA_8888 && format != PIXEL_FORMAT_RGBA_FP16)) {
|
||||
return nullptr;
|
||||
}
|
||||
SkImageInfo info = SkImageInfo::Make(graphicBuffer->getWidth(), graphicBuffer->getHeight(),
|
||||
|
||||
Reference in New Issue
Block a user