Loading graphics/java/android/graphics/YuvImage.java +4 −2 Original line number Diff line number Diff line Loading @@ -339,7 +339,8 @@ public class YuvImage { return nativeCompressToJpegR(mData, mColorSpace.getDataSpace(), sdr.getYuvData(), sdr.getColorSpace().getDataSpace(), mWidth, mHeight, quality, stream, new byte[WORKING_COMPRESS_STORAGE], exif); new byte[WORKING_COMPRESS_STORAGE], exif, mStrides, sdr.getStrides()); } Loading Loading @@ -451,5 +452,6 @@ public class YuvImage { private static native boolean nativeCompressToJpegR(byte[] hdr, int hdrColorSpaceId, byte[] sdr, int sdrColorSpaceId, int width, int height, int quality, OutputStream stream, byte[] tempStorage, byte[] exif); OutputStream stream, byte[] tempStorage, byte[] exif, int[] hdrStrides, int[] sdrStrides); } libs/hwui/jni/YuvToJpegEncoder.cpp +31 −4 Original line number Diff line number Diff line Loading @@ -332,7 +332,8 @@ ultrahdr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNI bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace, int width, int height, int jpegQuality, ScopedByteArrayRO* jExif) { int width, int height, int jpegQuality, ScopedByteArrayRO* jExif, ScopedIntArrayRO* jHdrStrides, ScopedIntArrayRO* jSdrStrides) { // Check SDR color space. Now we only support SRGB transfer function if ((sdrColorSpace & ADataSpace::TRANSFER_MASK) != ADataSpace::TRANSFER_SRGB) { jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException"); Loading @@ -340,6 +341,19 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, "The requested SDR color space is not supported. Transfer function must be SRGB"); return false; } // Check HDR and SDR strides length. // HDR is YCBCR_P010 color format, and its strides length must be 2 (Y, chroma (Cb, Cr)). // SDR is YUV_420_888 color format, and its strides length must be 3 (Y, Cb, Cr). if (jHdrStrides->size() != 2) { jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException"); env->ThrowNew(IllegalArgumentException, "HDR stride length must be 2."); return false; } if (jSdrStrides->size() != 3) { jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException"); env->ThrowNew(IllegalArgumentException, "SDR stride length must be 3."); return false; } ultrahdr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace); ultrahdr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace); Loading @@ -351,18 +365,26 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, return false; } const int* hdrStrides = reinterpret_cast<const int*>(jHdrStrides->get()); const int* sdrStrides = reinterpret_cast<const int*>(jSdrStrides->get()); JpegR jpegREncoder; jpegr_uncompressed_struct p010; p010.data = hdr; p010.width = width; p010.height = height; // Divided by 2 because unit in libultrader is pixel and in YuvImage it is byte. p010.luma_stride = (hdrStrides[0] + 1) / 2; p010.chroma_stride = (hdrStrides[1] + 1) / 2; p010.colorGamut = hdrColorGamut; jpegr_uncompressed_struct yuv420; yuv420.data = sdr; yuv420.width = width; yuv420.height = height; yuv420.luma_stride = sdrStrides[0]; yuv420.chroma_stride = sdrStrides[1]; yuv420.colorGamut = sdrColorGamut; jpegr_exif_struct exif; Loading Loading @@ -420,22 +442,27 @@ static jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv, static jboolean YuvImage_compressToJpegR(JNIEnv* env, jobject, jbyteArray inHdr, jint hdrColorSpace, jbyteArray inSdr, jint sdrColorSpace, jint width, jint height, jint quality, jobject jstream, jbyteArray jstorage, jbyteArray jExif) { jbyteArray jstorage, jbyteArray jExif, jintArray jHdrStrides, jintArray jSdrStrides) { jbyte* hdr = env->GetByteArrayElements(inHdr, NULL); jbyte* sdr = env->GetByteArrayElements(inSdr, NULL); ScopedByteArrayRO exif(env, jExif); ScopedIntArrayRO hdrStrides(env, jHdrStrides); ScopedIntArrayRO sdrStrides(env, jSdrStrides); SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); P010Yuv420ToJpegREncoder encoder; jboolean result = JNI_FALSE; if (encoder.encode(env, strm, hdr, hdrColorSpace, sdr, sdrColorSpace, width, height, quality, &exif)) { width, height, quality, &exif, &hdrStrides, &sdrStrides)) { result = JNI_TRUE; } env->ReleaseByteArrayElements(inHdr, hdr, 0); env->ReleaseByteArrayElements(inSdr, sdr, 0); delete strm; return result; } Loading @@ -444,7 +471,7 @@ static jboolean YuvImage_compressToJpegR(JNIEnv* env, jobject, jbyteArray inHdr, static const JNINativeMethod gYuvImageMethods[] = { { "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z", (void*)YuvImage_compressToJpeg }, { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B[B)Z", { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B[B[I[I)Z", (void*)YuvImage_compressToJpegR } }; Loading libs/hwui/jni/YuvToJpegEncoder.h +4 −1 Original line number Diff line number Diff line Loading @@ -92,11 +92,14 @@ public: * @param height Height of the Yuv data in terms of pixels. * @param jpegQuality Picture quality in [0, 100]. * @param exif Buffer holds EXIF package. * @param hdrStrides The number of row bytes in each image plane of the HDR input. * @param sdrStrides The number of row bytes in each image plane of the SDR input. * @return true if successfully compressed the stream. */ bool encode(JNIEnv* env, SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace, int width, int height, int jpegQuality, ScopedByteArrayRO* exif); int width, int height, int jpegQuality, ScopedByteArrayRO* exif, ScopedIntArrayRO* hdrStrides, ScopedIntArrayRO* sdrStrides); /** Map data space (defined in DataSpace.java and data_space.h) to the color gamut * used in JPEG/R Loading Loading
graphics/java/android/graphics/YuvImage.java +4 −2 Original line number Diff line number Diff line Loading @@ -339,7 +339,8 @@ public class YuvImage { return nativeCompressToJpegR(mData, mColorSpace.getDataSpace(), sdr.getYuvData(), sdr.getColorSpace().getDataSpace(), mWidth, mHeight, quality, stream, new byte[WORKING_COMPRESS_STORAGE], exif); new byte[WORKING_COMPRESS_STORAGE], exif, mStrides, sdr.getStrides()); } Loading Loading @@ -451,5 +452,6 @@ public class YuvImage { private static native boolean nativeCompressToJpegR(byte[] hdr, int hdrColorSpaceId, byte[] sdr, int sdrColorSpaceId, int width, int height, int quality, OutputStream stream, byte[] tempStorage, byte[] exif); OutputStream stream, byte[] tempStorage, byte[] exif, int[] hdrStrides, int[] sdrStrides); }
libs/hwui/jni/YuvToJpegEncoder.cpp +31 −4 Original line number Diff line number Diff line Loading @@ -332,7 +332,8 @@ ultrahdr_transfer_function P010Yuv420ToJpegREncoder::findHdrTransferFunction(JNI bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace, int width, int height, int jpegQuality, ScopedByteArrayRO* jExif) { int width, int height, int jpegQuality, ScopedByteArrayRO* jExif, ScopedIntArrayRO* jHdrStrides, ScopedIntArrayRO* jSdrStrides) { // Check SDR color space. Now we only support SRGB transfer function if ((sdrColorSpace & ADataSpace::TRANSFER_MASK) != ADataSpace::TRANSFER_SRGB) { jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException"); Loading @@ -340,6 +341,19 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, "The requested SDR color space is not supported. Transfer function must be SRGB"); return false; } // Check HDR and SDR strides length. // HDR is YCBCR_P010 color format, and its strides length must be 2 (Y, chroma (Cb, Cr)). // SDR is YUV_420_888 color format, and its strides length must be 3 (Y, Cb, Cr). if (jHdrStrides->size() != 2) { jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException"); env->ThrowNew(IllegalArgumentException, "HDR stride length must be 2."); return false; } if (jSdrStrides->size() != 3) { jclass IllegalArgumentException = env->FindClass("java/lang/IllegalArgumentException"); env->ThrowNew(IllegalArgumentException, "SDR stride length must be 3."); return false; } ultrahdr_color_gamut hdrColorGamut = findColorGamut(env, hdrColorSpace); ultrahdr_color_gamut sdrColorGamut = findColorGamut(env, sdrColorSpace); Loading @@ -351,18 +365,26 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, return false; } const int* hdrStrides = reinterpret_cast<const int*>(jHdrStrides->get()); const int* sdrStrides = reinterpret_cast<const int*>(jSdrStrides->get()); JpegR jpegREncoder; jpegr_uncompressed_struct p010; p010.data = hdr; p010.width = width; p010.height = height; // Divided by 2 because unit in libultrader is pixel and in YuvImage it is byte. p010.luma_stride = (hdrStrides[0] + 1) / 2; p010.chroma_stride = (hdrStrides[1] + 1) / 2; p010.colorGamut = hdrColorGamut; jpegr_uncompressed_struct yuv420; yuv420.data = sdr; yuv420.width = width; yuv420.height = height; yuv420.luma_stride = sdrStrides[0]; yuv420.chroma_stride = sdrStrides[1]; yuv420.colorGamut = sdrColorGamut; jpegr_exif_struct exif; Loading Loading @@ -420,22 +442,27 @@ static jboolean YuvImage_compressToJpeg(JNIEnv* env, jobject, jbyteArray inYuv, static jboolean YuvImage_compressToJpegR(JNIEnv* env, jobject, jbyteArray inHdr, jint hdrColorSpace, jbyteArray inSdr, jint sdrColorSpace, jint width, jint height, jint quality, jobject jstream, jbyteArray jstorage, jbyteArray jExif) { jbyteArray jstorage, jbyteArray jExif, jintArray jHdrStrides, jintArray jSdrStrides) { jbyte* hdr = env->GetByteArrayElements(inHdr, NULL); jbyte* sdr = env->GetByteArrayElements(inSdr, NULL); ScopedByteArrayRO exif(env, jExif); ScopedIntArrayRO hdrStrides(env, jHdrStrides); ScopedIntArrayRO sdrStrides(env, jSdrStrides); SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); P010Yuv420ToJpegREncoder encoder; jboolean result = JNI_FALSE; if (encoder.encode(env, strm, hdr, hdrColorSpace, sdr, sdrColorSpace, width, height, quality, &exif)) { width, height, quality, &exif, &hdrStrides, &sdrStrides)) { result = JNI_TRUE; } env->ReleaseByteArrayElements(inHdr, hdr, 0); env->ReleaseByteArrayElements(inSdr, sdr, 0); delete strm; return result; } Loading @@ -444,7 +471,7 @@ static jboolean YuvImage_compressToJpegR(JNIEnv* env, jobject, jbyteArray inHdr, static const JNINativeMethod gYuvImageMethods[] = { { "nativeCompressToJpeg", "([BIII[I[IILjava/io/OutputStream;[B)Z", (void*)YuvImage_compressToJpeg }, { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B[B)Z", { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B[B[I[I)Z", (void*)YuvImage_compressToJpegR } }; Loading
libs/hwui/jni/YuvToJpegEncoder.h +4 −1 Original line number Diff line number Diff line Loading @@ -92,11 +92,14 @@ public: * @param height Height of the Yuv data in terms of pixels. * @param jpegQuality Picture quality in [0, 100]. * @param exif Buffer holds EXIF package. * @param hdrStrides The number of row bytes in each image plane of the HDR input. * @param sdrStrides The number of row bytes in each image plane of the SDR input. * @return true if successfully compressed the stream. */ bool encode(JNIEnv* env, SkWStream* stream, void* hdr, int hdrColorSpace, void* sdr, int sdrColorSpace, int width, int height, int jpegQuality, ScopedByteArrayRO* exif); int width, int height, int jpegQuality, ScopedByteArrayRO* exif, ScopedIntArrayRO* hdrStrides, ScopedIntArrayRO* sdrStrides); /** Map data space (defined in DataSpace.java and data_space.h) to the color gamut * used in JPEG/R Loading