jpegr: encode ICC
bug: b/264715926, b/263609305
test: recoverymap_test.cpp, check the ICC package in the encoded jpeg/r
image in a hex editor
Change-Id: I099eb9201c26fce046b7ca8ea4b5e7e8443adcb3
diff --git a/libs/jpegrecoverymap/Android.bp b/libs/jpegrecoverymap/Android.bp
index 01318dc..2c4b3bf 100644
--- a/libs/jpegrecoverymap/Android.bp
+++ b/libs/jpegrecoverymap/Android.bp
@@ -41,6 +41,8 @@
"libjpegdecoder",
"liblog",
],
+
+ static_libs: ["libskia"],
}
cc_library {
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
index 696be1b..1a4b679 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
@@ -34,6 +34,7 @@
JPEGR_TF_LINEAR = 0,
JPEGR_TF_HLG = 1,
JPEGR_TF_PQ = 2,
+ JPEGR_TF_SRGB = 3,
} jpegr_transfer_function;
struct jpegr_info_struct {
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h
index c36a363..8696851 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h
@@ -28,13 +28,6 @@
struct jpegr_metadata;
-// If the EXIF package doesn't exist in the input JPEG, we'll create one with one entry
-// where the length is represented by this value.
-const size_t PSEUDO_EXIF_PACKAGE_LENGTH = 28;
-// If the EXIF package exists in the input JPEG, we'll add an "JR" entry where the length is
-// represented by this value.
-const size_t EXIF_J_R_ENTRY_LENGTH = 12;
-
/*
* Helper function used for writing data to destination.
*
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 30aa846..7ca6094 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -26,7 +26,10 @@
#include <image_io/jpeg/jpeg_info_builder.h>
#include <image_io/base/data_segment_data_source.h>
#include <utils/Log.h>
+#include "SkColorSpace.h"
+#include "SkICC.h"
+#include <map>
#include <memory>
#include <sstream>
#include <string>
@@ -93,6 +96,20 @@
return cpuCoreCount;
}
+static const map<recoverymap::jpegr_color_gamut, skcms_Matrix3x3> jrGamut_to_skGamut {
+ {JPEGR_COLORGAMUT_BT709, SkNamedGamut::kSRGB},
+ {JPEGR_COLORGAMUT_P3, SkNamedGamut::kDisplayP3},
+ {JPEGR_COLORGAMUT_BT2100, SkNamedGamut::kRec2020},
+};
+
+static const map<
+ recoverymap::jpegr_transfer_function, skcms_TransferFunction> jrTransFunc_to_skTransFunc {
+ {JPEGR_TF_SRGB, SkNamedTransferFn::kSRGB},
+ {JPEGR_TF_LINEAR, SkNamedTransferFn::kLinear},
+ {JPEGR_TF_HLG, SkNamedTransferFn::kHLG},
+ {JPEGR_TF_PQ, SkNamedTransferFn::kPQ},
+};
+
/*
* Helper function copies the JPEG image from without EXIF.
*
@@ -164,11 +181,15 @@
compressed_map.data = compressed_map_data.get();
JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
+ sk_sp<SkData> icc = SkWriteICCProfile(
+ jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
+ jrGamut_to_skGamut.at(uncompressed_yuv_420_image.colorGamut));
+
JpegEncoder jpeg_encoder;
- // TODO: determine ICC data based on color gamut information
if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image.data,
uncompressed_yuv_420_image.width,
- uncompressed_yuv_420_image.height, quality, nullptr, 0)) {
+ uncompressed_yuv_420_image.height, quality,
+ icc.get()->data(), icc.get()->size())) {
return ERROR_JPEGR_ENCODE_ERROR;
}
jpegr_compressed_struct jpeg;
@@ -228,11 +249,15 @@
compressed_map.data = compressed_map_data.get();
JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map));
+ sk_sp<SkData> icc = SkWriteICCProfile(
+ jrTransFunc_to_skTransFunc.at(JPEGR_TF_SRGB),
+ jrGamut_to_skGamut.at(uncompressed_yuv_420_image->colorGamut));
+
JpegEncoder jpeg_encoder;
- // TODO: determine ICC data based on color gamut information
if (!jpeg_encoder.compressImage(uncompressed_yuv_420_image->data,
uncompressed_yuv_420_image->width,
- uncompressed_yuv_420_image->height, quality, nullptr, 0)) {
+ uncompressed_yuv_420_image->height, quality,
+ icc.get()->data(), icc.get()->size())) {
return ERROR_JPEGR_ENCODE_ERROR;
}
jpegr_compressed_struct jpeg;
@@ -574,7 +599,7 @@
#endif
hdr_white_nits = kPqMaxNits;
break;
- case JPEGR_TF_UNSPECIFIED:
+ default:
// Should be impossible to hit after input validation.
return ERROR_JPEGR_INVALID_TRANS_FUNC;
}
@@ -750,7 +775,7 @@
hdrOetf = pqOetf;
#endif
break;
- case JPEGR_TF_UNSPECIFIED:
+ default:
// Should be impossible to hit after input validation.
hdrOetf = identityConversion;
}
diff --git a/libs/jpegrecoverymap/tests/Android.bp b/libs/jpegrecoverymap/tests/Android.bp
index 39445f8..cad273e 100644
--- a/libs/jpegrecoverymap/tests/Android.bp
+++ b/libs/jpegrecoverymap/tests/Android.bp
@@ -30,15 +30,13 @@
],
shared_libs: [
"libjpeg",
+ "libjpegrecoverymap",
"libimage_io",
"liblog",
],
static_libs: [
"libgmock",
"libgtest",
- "libjpegdecoder",
- "libjpegencoder",
- "libjpegrecoverymap",
],
}
@@ -50,10 +48,10 @@
],
shared_libs: [
"libjpeg",
+ "libjpegencoder",
"liblog",
],
static_libs: [
- "libjpegencoder",
"libgtest",
],
}
@@ -66,10 +64,10 @@
],
shared_libs: [
"libjpeg",
+ "libjpegdecoder",
"liblog",
],
static_libs: [
- "libjpegdecoder",
"libgtest",
],
}