Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -16999,6 +16999,7 @@ package android.graphics { ctor public YuvImage(@NonNull byte[], int, int, int, @Nullable int[], @NonNull android.graphics.ColorSpace); method public boolean compressToJpeg(android.graphics.Rect, int, java.io.OutputStream); method public boolean compressToJpegR(@NonNull android.graphics.YuvImage, int, @NonNull java.io.OutputStream); method @FlaggedApi("com.android.graphics.flags.yuv_image_compress_to_ultra_hdr") public boolean compressToJpegR(@NonNull android.graphics.YuvImage, int, @NonNull java.io.OutputStream, @NonNull byte[]); method @NonNull public android.graphics.ColorSpace getColorSpace(); method public int getHeight(); method public int[] getStrides(); graphics/java/android/framework_graphics.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -6,3 +6,10 @@ flag { description: "Add a function without unused exact param for computeBounds." bug: "304478551" } flag { name: "yuv_image_compress_to_ultra_hdr" namespace: "core_graphics" description: "Feature flag for YUV image compress to Ultra HDR." bug: "308978825" } No newline at end of file graphics/java/android/graphics/YuvImage.java +38 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.graphics; import com.android.graphics.flags.Flags; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import java.io.OutputStream; Loading Loading @@ -269,6 +272,38 @@ public class YuvImage { */ public boolean compressToJpegR(@NonNull YuvImage sdr, int quality, @NonNull OutputStream stream) { byte[] emptyExif = new byte[0]; return compressToJpegR(sdr, quality, stream, emptyExif); } /** * Compress the HDR image into JPEG/R format. * * Sample usage: * hdr_image.compressToJpegR(sdr_image, 90, stream); * * For the SDR image, only YUV_420_888 image format is supported, and the following * color spaces are supported: * ColorSpace.Named.SRGB, * ColorSpace.Named.DISPLAY_P3 * * For the HDR image, only YCBCR_P010 image format is supported, and the following * color spaces are supported: * ColorSpace.Named.BT2020_HLG, * ColorSpace.Named.BT2020_PQ * * @param sdr The SDR image, only ImageFormat.YUV_420_888 is supported. * @param quality Hint to the compressor, 0-100. 0 meaning compress for * small size, 100 meaning compress for max quality. * @param stream OutputStream to write the compressed data. * @param exif Exchangeable image file format. * @return True if the compression is successful. * @throws IllegalArgumentException if input images are invalid; quality is not within [0, * 100]; or stream is null. */ @FlaggedApi(Flags.FLAG_YUV_IMAGE_COMPRESS_TO_ULTRA_HDR) public boolean compressToJpegR(@NonNull YuvImage sdr, int quality, @NonNull OutputStream stream, @NonNull byte[] exif) { if (sdr == null) { throw new IllegalArgumentException("SDR input cannot be null"); } Loading Loading @@ -304,7 +339,7 @@ public class YuvImage { return nativeCompressToJpegR(mData, mColorSpace.getDataSpace(), sdr.getYuvData(), sdr.getColorSpace().getDataSpace(), mWidth, mHeight, quality, stream, new byte[WORKING_COMPRESS_STORAGE]); new byte[WORKING_COMPRESS_STORAGE], exif); } Loading Loading @@ -416,5 +451,5 @@ 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); OutputStream stream, byte[] tempStorage, byte[] exif); } libs/hwui/jni/YuvToJpegEncoder.cpp +12 −5 Original line number Diff line number Diff line Loading @@ -332,7 +332,7 @@ 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) { int width, int height, int jpegQuality, ScopedByteArrayRO* jExif) { // 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 Loading @@ -365,6 +365,10 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, yuv420.height = height; yuv420.colorGamut = sdrColorGamut; jpegr_exif_struct exif; exif.data = const_cast<void*>(reinterpret_cast<const void*>(jExif->get())); exif.length = jExif->size(); jpegr_compressed_struct jpegR; jpegR.maxLength = width * height * sizeof(uint8_t); Loading @@ -373,7 +377,8 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, if (int success = jpegREncoder.encodeJPEGR(&p010, &yuv420, hdrTransferFunction, &jpegR, jpegQuality, nullptr); success != android::OK) { &jpegR, jpegQuality, exif.length > 0 ? &exif : NULL); success != android::OK) { ALOGW("Encode JPEG/R failed, error code: %d.", success); return false; } Loading Loading @@ -415,15 +420,17 @@ 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 jstorage, jbyteArray jExif) { jbyte* hdr = env->GetByteArrayElements(inHdr, NULL); jbyte* sdr = env->GetByteArrayElements(inSdr, NULL); ScopedByteArrayRO exif(env, jExif); SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); P010Yuv420ToJpegREncoder encoder; jboolean result = JNI_FALSE; if (encoder.encode(env, strm, hdr, hdrColorSpace, sdr, sdrColorSpace, width, height, quality)) { width, height, quality, &exif)) { result = JNI_TRUE; } Loading @@ -437,7 +444,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)Z", { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B[B)Z", (void*)YuvImage_compressToJpegR } }; Loading libs/hwui/jni/YuvToJpegEncoder.h +3 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ #define _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_ #include <android/data_space.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <ultrahdr/jpegr.h> extern "C" { Loading Loading @@ -90,11 +91,12 @@ public: * @param width Width of the Yuv data in terms of pixels. * @param height Height of the Yuv data in terms of pixels. * @param jpegQuality Picture quality in [0, 100]. * @param exif Buffer holds EXIF package. * @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); int width, int height, int jpegQuality, ScopedByteArrayRO* exif); /** Map data space (defined in DataSpace.java and data_space.h) to the color gamut * used in JPEG/R Loading Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -16999,6 +16999,7 @@ package android.graphics { ctor public YuvImage(@NonNull byte[], int, int, int, @Nullable int[], @NonNull android.graphics.ColorSpace); method public boolean compressToJpeg(android.graphics.Rect, int, java.io.OutputStream); method public boolean compressToJpegR(@NonNull android.graphics.YuvImage, int, @NonNull java.io.OutputStream); method @FlaggedApi("com.android.graphics.flags.yuv_image_compress_to_ultra_hdr") public boolean compressToJpegR(@NonNull android.graphics.YuvImage, int, @NonNull java.io.OutputStream, @NonNull byte[]); method @NonNull public android.graphics.ColorSpace getColorSpace(); method public int getHeight(); method public int[] getStrides();
graphics/java/android/framework_graphics.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -6,3 +6,10 @@ flag { description: "Add a function without unused exact param for computeBounds." bug: "304478551" } flag { name: "yuv_image_compress_to_ultra_hdr" namespace: "core_graphics" description: "Feature flag for YUV image compress to Ultra HDR." bug: "308978825" } No newline at end of file
graphics/java/android/graphics/YuvImage.java +38 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.graphics; import com.android.graphics.flags.Flags; import android.annotation.FlaggedApi; import android.annotation.NonNull; import android.annotation.Nullable; import java.io.OutputStream; Loading Loading @@ -269,6 +272,38 @@ public class YuvImage { */ public boolean compressToJpegR(@NonNull YuvImage sdr, int quality, @NonNull OutputStream stream) { byte[] emptyExif = new byte[0]; return compressToJpegR(sdr, quality, stream, emptyExif); } /** * Compress the HDR image into JPEG/R format. * * Sample usage: * hdr_image.compressToJpegR(sdr_image, 90, stream); * * For the SDR image, only YUV_420_888 image format is supported, and the following * color spaces are supported: * ColorSpace.Named.SRGB, * ColorSpace.Named.DISPLAY_P3 * * For the HDR image, only YCBCR_P010 image format is supported, and the following * color spaces are supported: * ColorSpace.Named.BT2020_HLG, * ColorSpace.Named.BT2020_PQ * * @param sdr The SDR image, only ImageFormat.YUV_420_888 is supported. * @param quality Hint to the compressor, 0-100. 0 meaning compress for * small size, 100 meaning compress for max quality. * @param stream OutputStream to write the compressed data. * @param exif Exchangeable image file format. * @return True if the compression is successful. * @throws IllegalArgumentException if input images are invalid; quality is not within [0, * 100]; or stream is null. */ @FlaggedApi(Flags.FLAG_YUV_IMAGE_COMPRESS_TO_ULTRA_HDR) public boolean compressToJpegR(@NonNull YuvImage sdr, int quality, @NonNull OutputStream stream, @NonNull byte[] exif) { if (sdr == null) { throw new IllegalArgumentException("SDR input cannot be null"); } Loading Loading @@ -304,7 +339,7 @@ public class YuvImage { return nativeCompressToJpegR(mData, mColorSpace.getDataSpace(), sdr.getYuvData(), sdr.getColorSpace().getDataSpace(), mWidth, mHeight, quality, stream, new byte[WORKING_COMPRESS_STORAGE]); new byte[WORKING_COMPRESS_STORAGE], exif); } Loading Loading @@ -416,5 +451,5 @@ 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); OutputStream stream, byte[] tempStorage, byte[] exif); }
libs/hwui/jni/YuvToJpegEncoder.cpp +12 −5 Original line number Diff line number Diff line Loading @@ -332,7 +332,7 @@ 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) { int width, int height, int jpegQuality, ScopedByteArrayRO* jExif) { // 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 Loading @@ -365,6 +365,10 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, yuv420.height = height; yuv420.colorGamut = sdrColorGamut; jpegr_exif_struct exif; exif.data = const_cast<void*>(reinterpret_cast<const void*>(jExif->get())); exif.length = jExif->size(); jpegr_compressed_struct jpegR; jpegR.maxLength = width * height * sizeof(uint8_t); Loading @@ -373,7 +377,8 @@ bool P010Yuv420ToJpegREncoder::encode(JNIEnv* env, if (int success = jpegREncoder.encodeJPEGR(&p010, &yuv420, hdrTransferFunction, &jpegR, jpegQuality, nullptr); success != android::OK) { &jpegR, jpegQuality, exif.length > 0 ? &exif : NULL); success != android::OK) { ALOGW("Encode JPEG/R failed, error code: %d.", success); return false; } Loading Loading @@ -415,15 +420,17 @@ 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 jstorage, jbyteArray jExif) { jbyte* hdr = env->GetByteArrayElements(inHdr, NULL); jbyte* sdr = env->GetByteArrayElements(inSdr, NULL); ScopedByteArrayRO exif(env, jExif); SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage); P010Yuv420ToJpegREncoder encoder; jboolean result = JNI_FALSE; if (encoder.encode(env, strm, hdr, hdrColorSpace, sdr, sdrColorSpace, width, height, quality)) { width, height, quality, &exif)) { result = JNI_TRUE; } Loading @@ -437,7 +444,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)Z", { "nativeCompressToJpegR", "([BI[BIIIILjava/io/OutputStream;[B[B)Z", (void*)YuvImage_compressToJpegR } }; Loading
libs/hwui/jni/YuvToJpegEncoder.h +3 −1 Original line number Diff line number Diff line Loading @@ -2,6 +2,7 @@ #define _ANDROID_GRAPHICS_YUV_TO_JPEG_ENCODER_H_ #include <android/data_space.h> #include <nativehelper/ScopedPrimitiveArray.h> #include <ultrahdr/jpegr.h> extern "C" { Loading Loading @@ -90,11 +91,12 @@ public: * @param width Width of the Yuv data in terms of pixels. * @param height Height of the Yuv data in terms of pixels. * @param jpegQuality Picture quality in [0, 100]. * @param exif Buffer holds EXIF package. * @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); int width, int height, int jpegQuality, ScopedByteArrayRO* exif); /** Map data space (defined in DataSpace.java and data_space.h) to the color gamut * used in JPEG/R Loading