aboutsummaryrefslogtreecommitdiff
path: root/examples/ultrahdr_app.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/ultrahdr_app.cpp')
-rw-r--r--examples/ultrahdr_app.cpp902
1 files changed, 573 insertions, 329 deletions
diff --git a/examples/ultrahdr_app.cpp b/examples/ultrahdr_app.cpp
index 20b9329..cc87d5b 100644
--- a/examples/ultrahdr_app.cpp
+++ b/examples/ultrahdr_app.cpp
@@ -24,14 +24,12 @@
#include <algorithm>
#include <cmath>
+#include <cstdint>
#include <fstream>
#include <iostream>
+#include <sstream>
-#include "ultrahdr/ultrahdrcommon.h"
-#include "ultrahdr/gainmapmath.h"
-#include "ultrahdr/jpegr.h"
-
-using namespace ultrahdr;
+#include "ultrahdr_api.h"
const float BT601YUVtoRGBMatrix[9] = {
1, 0, 1.402, 1, (-0.202008 / 0.587), (-0.419198 / 0.587), 1.0, 1.772, 0.0};
@@ -62,6 +60,10 @@ const float BT2020RGBtoYUVMatrix[9] = {0.2627,
(-0.6780 / 1.4746),
(-0.0593 / 1.4746)};
+// remove these once introduced in ultrahdr_api.h
+const int UHDR_IMG_FMT_24bppYCbCr444 = 100;
+const int UHDR_IMG_FMT_48bppYCbCr444 = 101;
+
int optind_s = 1;
int optopt_s = 0;
char* optarg_s = nullptr;
@@ -158,6 +160,27 @@ static bool loadFile(const char* filename, void*& result, int length) {
return false;
}
+static bool loadFile(const char* filename, uhdr_raw_image_t* handle) {
+ std::ifstream ifd(filename, std::ios::binary);
+ if (ifd.good()) {
+ if (handle->fmt == UHDR_IMG_FMT_24bppYCbCrP010) {
+ const int bpp = 2;
+ ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_Y]), handle->w * handle->h * bpp);
+ ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_UV]),
+ (handle->w / 2) * (handle->h / 2) * bpp * 2);
+ return true;
+ } else if (handle->fmt == UHDR_IMG_FMT_12bppYCbCr420) {
+ ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_Y]), handle->w * handle->h);
+ ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_U]), (handle->w / 2) * (handle->h / 2));
+ ifd.read(static_cast<char*>(handle->planes[UHDR_PLANE_V]), (handle->w / 2) * (handle->h / 2));
+ return true;
+ }
+ return false;
+ }
+ std::cerr << "unable to open file : " << filename << std::endl;
+ return false;
+}
+
static bool writeFile(const char* filename, void*& result, int length) {
std::ofstream ofd(filename, std::ios::binary);
if (ofd.is_open()) {
@@ -168,54 +191,115 @@ static bool writeFile(const char* filename, void*& result, int length) {
return false;
}
+static bool writeFile(const char* filename, uhdr_raw_image_t* img) {
+ std::ofstream ofd(filename, std::ios::binary);
+ if (ofd.is_open()) {
+ if (img->fmt == UHDR_IMG_FMT_32bppRGBA8888 || img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ||
+ img->fmt == UHDR_IMG_FMT_32bppRGBA1010102) {
+ char* data = static_cast<char*>(img->planes[UHDR_PLANE_PACKED]);
+ int bpp = img->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat ? 8 : 4;
+ const size_t stride = img->stride[UHDR_PLANE_PACKED] * bpp;
+ const size_t length = img->w * bpp;
+ for (unsigned i = 0; i < img->h; i++, data += stride) {
+ ofd.write(data, length);
+ }
+ return true;
+ } else if ((int)img->fmt == UHDR_IMG_FMT_24bppYCbCr444 ||
+ (int)img->fmt == UHDR_IMG_FMT_48bppYCbCr444) {
+ char* data = static_cast<char*>(img->planes[UHDR_PLANE_Y]);
+ int bpp = (int)img->fmt == UHDR_IMG_FMT_48bppYCbCr444 ? 2 : 1;
+ size_t stride = img->stride[UHDR_PLANE_Y] * bpp;
+ size_t length = img->w * bpp;
+ for (unsigned i = 0; i < img->h; i++, data += stride) {
+ ofd.write(data, length);
+ }
+ data = static_cast<char*>(img->planes[UHDR_PLANE_U]);
+ stride = img->stride[UHDR_PLANE_U] * bpp;
+ for (unsigned i = 0; i < img->h; i++, data += stride) {
+ ofd.write(data, length);
+ }
+ data = static_cast<char*>(img->planes[UHDR_PLANE_V]);
+ stride = img->stride[UHDR_PLANE_V] * bpp;
+ for (unsigned i = 0; i < img->h; i++, data += stride) {
+ ofd.write(data, length);
+ }
+ return true;
+ }
+ return false;
+ }
+ std::cerr << "unable to write to file : " << filename << std::endl;
+ return false;
+}
+
class UltraHdrAppInput {
public:
UltraHdrAppInput(const char* p010File, const char* yuv420File, const char* yuv420JpegFile,
- size_t width, size_t height,
- ultrahdr_color_gamut p010Cg = ULTRAHDR_COLORGAMUT_BT709,
- ultrahdr_color_gamut yuv420Cg = ULTRAHDR_COLORGAMUT_BT709,
- ultrahdr_transfer_function tf = ULTRAHDR_TF_HLG, int quality = 100,
- ultrahdr_output_format of = ULTRAHDR_OUTPUT_HDR_HLG)
+ const char* gainmapJpegFile, const char* gainmapMetadataCfgFile, size_t width,
+ size_t height, uhdr_color_gamut_t p010Cg = UHDR_CG_BT_709,
+ uhdr_color_gamut_t yuv420Cg = UHDR_CG_BT_709,
+ uhdr_color_transfer_t p010Tf = UHDR_CT_HLG, int quality = 100,
+ uhdr_color_transfer_t oTf = UHDR_CT_HLG,
+ uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102)
: mP010File(p010File),
mYuv420File(yuv420File),
mYuv420JpegFile(yuv420JpegFile),
+ mGainMapJpegFile(gainmapJpegFile),
+ mGainMapMetadataCfgFile(gainmapMetadataCfgFile),
mJpegRFile(nullptr),
mWidth(width),
mHeight(height),
mP010Cg(p010Cg),
mYuv420Cg(yuv420Cg),
- mTf(tf),
+ mP010Tf(p010Tf),
mQuality(quality),
- mOf(of),
+ mOTf(oTf),
+ mOfmt(oFmt),
mMode(0){};
- UltraHdrAppInput(const char* jpegRFile, ultrahdr_output_format of = ULTRAHDR_OUTPUT_HDR_HLG)
+ UltraHdrAppInput(const char* jpegRFile, uhdr_color_transfer_t oTf = UHDR_CT_HLG,
+ uhdr_img_fmt_t oFmt = UHDR_IMG_FMT_32bppRGBA1010102)
: mP010File(nullptr),
mYuv420File(nullptr),
mJpegRFile(jpegRFile),
mWidth(0),
mHeight(0),
- mP010Cg(ULTRAHDR_COLORGAMUT_UNSPECIFIED),
- mYuv420Cg(ULTRAHDR_COLORGAMUT_UNSPECIFIED),
- mTf(ULTRAHDR_TF_UNSPECIFIED),
+ mP010Cg(UHDR_CG_UNSPECIFIED),
+ mYuv420Cg(UHDR_CG_UNSPECIFIED),
+ mP010Tf(UHDR_CT_UNSPECIFIED),
mQuality(100),
- mOf(of),
+ mOTf(oTf),
+ mOfmt(oFmt),
mMode(1){};
~UltraHdrAppInput() {
- if (mRawP010Image.data) free(mRawP010Image.data);
- if (mRawP010Image.chroma_data) free(mRawP010Image.chroma_data);
- if (mRawRgba1010102Image.data) free(mRawRgba1010102Image.data);
- if (mRawRgba1010102Image.chroma_data) free(mRawRgba1010102Image.chroma_data);
- if (mRawYuv420Image.data) free(mRawYuv420Image.data);
- if (mRawYuv420Image.chroma_data) free(mRawYuv420Image.chroma_data);
- if (mRawRgba8888Image.data) free(mRawRgba8888Image.data);
- if (mRawRgba8888Image.chroma_data) free(mRawRgba8888Image.chroma_data);
+ int count = sizeof mRawP010Image.planes / sizeof mRawP010Image.planes[UHDR_PLANE_Y];
+ for (int i = 0; i < count; i++) {
+ if (mRawP010Image.planes[i]) {
+ free(mRawP010Image.planes[i]);
+ mRawP010Image.planes[i] = nullptr;
+ }
+ if (mRawRgba1010102Image.planes[i]) {
+ free(mRawRgba1010102Image.planes[i]);
+ mRawRgba1010102Image.planes[i] = nullptr;
+ }
+ if (mRawYuv420Image.planes[i]) {
+ free(mRawYuv420Image.planes[i]);
+ mRawYuv420Image.planes[i] = nullptr;
+ }
+ if (mRawRgba8888Image.planes[i]) {
+ free(mRawRgba8888Image.planes[i]);
+ mRawRgba8888Image.planes[i] = nullptr;
+ }
+ if (mDestImage.planes[i]) {
+ free(mDestImage.planes[i]);
+ mDestImage.planes[i] = nullptr;
+ }
+ if (mDestYUV444Image.planes[i]) {
+ free(mDestYUV444Image.planes[i]);
+ mDestYUV444Image.planes[i] = nullptr;
+ }
+ }
if (mJpegImgR.data) free(mJpegImgR.data);
- if (mDestImage.data) free(mDestImage.data);
- if (mDestImage.chroma_data) free(mDestImage.chroma_data);
- if (mDestYUV444Image.data) free(mDestYUV444Image.data);
- if (mDestYUV444Image.chroma_data) free(mDestYUV444Image.chroma_data);
}
bool fillJpegRImageHandle();
@@ -223,6 +307,8 @@ class UltraHdrAppInput {
bool convertP010ToRGBImage();
bool fillYuv420ImageHandle();
bool fillYuv420JpegImageHandle();
+ bool fillGainMapJpegImageHandle();
+ bool fillGainMapMetadataDescriptor();
bool convertYuv420ToRGBImage();
bool convertRgba8888ToYUV444Image();
bool convertRgba1010102ToYUV444Image();
@@ -236,65 +322,145 @@ class UltraHdrAppInput {
const char* mP010File;
const char* mYuv420File;
const char* mYuv420JpegFile;
+ const char *mGainMapJpegFile;
+ const char *mGainMapMetadataCfgFile;
const char* mJpegRFile;
const int mWidth;
const int mHeight;
- const ultrahdr_color_gamut mP010Cg;
- const ultrahdr_color_gamut mYuv420Cg;
- const ultrahdr_transfer_function mTf;
+ const uhdr_color_gamut_t mP010Cg;
+ const uhdr_color_gamut_t mYuv420Cg;
+ const uhdr_color_transfer_t mP010Tf;
const int mQuality;
- const ultrahdr_output_format mOf;
+ const uhdr_color_transfer_t mOTf;
+ const uhdr_img_fmt mOfmt;
const int mMode;
- jpegr_uncompressed_struct mRawP010Image{};
- jpegr_uncompressed_struct mRawRgba1010102Image{};
- jpegr_uncompressed_struct mRawYuv420Image{};
- jpegr_compressed_struct mYuv420JpegImage{};
- jpegr_uncompressed_struct mRawRgba8888Image{};
- jpegr_compressed_struct mJpegImgR{};
- jpegr_uncompressed_struct mDestImage{};
- jpegr_uncompressed_struct mDestYUV444Image{};
+
+ uhdr_raw_image_t mRawP010Image{};
+ uhdr_raw_image_t mRawRgba1010102Image{};
+ uhdr_raw_image_t mRawYuv420Image{};
+ uhdr_compressed_image_t mYuv420JpegImage{};
+ uhdr_compressed_image_t mGainMapJpegImage{};
+ uhdr_gainmap_metadata mMetadata{};
+ uhdr_raw_image_t mRawRgba8888Image{};
+ uhdr_compressed_image_t mJpegImgR{};
+ uhdr_raw_image_t mDestImage{};
+ uhdr_raw_image_t mDestYUV444Image{};
double mPsnr[3]{};
};
bool UltraHdrAppInput::fillP010ImageHandle() {
const int bpp = 2;
int p010Size = mWidth * mHeight * bpp * 1.5;
- mRawP010Image.width = mWidth;
- mRawP010Image.height = mHeight;
- mRawP010Image.colorGamut = mP010Cg;
- return loadFile(mP010File, mRawP010Image.data, p010Size);
+ mRawP010Image.fmt = UHDR_IMG_FMT_24bppYCbCrP010;
+ mRawP010Image.cg = mP010Cg;
+ mRawP010Image.ct = mP010Tf;
+ mRawP010Image.range = UHDR_CR_LIMITED_RANGE;
+ mRawP010Image.w = mWidth;
+ mRawP010Image.h = mHeight;
+ mRawP010Image.planes[UHDR_PLANE_Y] = malloc(mWidth * mHeight * bpp);
+ mRawP010Image.planes[UHDR_PLANE_UV] = malloc((mWidth / 2) * (mHeight / 2) * bpp * 2);
+ mRawP010Image.planes[UHDR_PLANE_V] = nullptr;
+ mRawP010Image.stride[UHDR_PLANE_Y] = mWidth;
+ mRawP010Image.stride[UHDR_PLANE_UV] = mWidth;
+ mRawP010Image.stride[UHDR_PLANE_V] = 0;
+ return loadFile(mP010File, &mRawP010Image);
}
bool UltraHdrAppInput::fillYuv420ImageHandle() {
int yuv420Size = mWidth * mHeight * 1.5;
- mRawYuv420Image.width = mWidth;
- mRawYuv420Image.height = mHeight;
- mRawYuv420Image.colorGamut = mYuv420Cg;
- return loadFile(mYuv420File, mRawYuv420Image.data, yuv420Size);
+ mRawYuv420Image.fmt = UHDR_IMG_FMT_12bppYCbCr420;
+ mRawYuv420Image.cg = mYuv420Cg;
+ mRawYuv420Image.ct = UHDR_CT_SRGB;
+ mRawYuv420Image.range = UHDR_CR_FULL_RANGE;
+ mRawYuv420Image.w = mWidth;
+ mRawYuv420Image.h = mHeight;
+ mRawYuv420Image.planes[UHDR_PLANE_Y] = malloc(mWidth * mHeight);
+ mRawYuv420Image.planes[UHDR_PLANE_U] = malloc((mWidth / 2) * (mHeight / 2));
+ mRawYuv420Image.planes[UHDR_PLANE_V] = malloc((mWidth / 2) * (mHeight / 2));
+ mRawYuv420Image.stride[UHDR_PLANE_Y] = mWidth;
+ mRawYuv420Image.stride[UHDR_PLANE_U] = mWidth / 2;
+ mRawYuv420Image.stride[UHDR_PLANE_V] = mWidth / 2;
+ return loadFile(mYuv420File, &mRawYuv420Image);
}
bool UltraHdrAppInput::fillYuv420JpegImageHandle() {
std::ifstream ifd(mYuv420JpegFile, std::ios::binary | std::ios::ate);
if (ifd.good()) {
int size = ifd.tellg();
- mYuv420JpegImage.length = size;
- mYuv420JpegImage.maxLength = size;
+ mYuv420JpegImage.capacity = size;
+ mYuv420JpegImage.data_sz = size;
mYuv420JpegImage.data = nullptr;
- mYuv420JpegImage.colorGamut = mYuv420Cg;
+ mYuv420JpegImage.cg = mYuv420Cg;
+ mYuv420JpegImage.ct = UHDR_CT_UNSPECIFIED;
+ mYuv420JpegImage.range = UHDR_CR_UNSPECIFIED;
ifd.close();
return loadFile(mYuv420JpegFile, mYuv420JpegImage.data, size);
}
return false;
}
+bool UltraHdrAppInput::fillGainMapJpegImageHandle() {
+ std::ifstream ifd(mGainMapJpegFile, std::ios::binary | std::ios::ate);
+ if (ifd.good()) {
+ int size = ifd.tellg();
+ mGainMapJpegImage.capacity = size;
+ mGainMapJpegImage.data_sz = size;
+ mGainMapJpegImage.data = nullptr;
+ mGainMapJpegImage.cg = UHDR_CG_UNSPECIFIED;
+ mGainMapJpegImage.ct = UHDR_CT_UNSPECIFIED;
+ mGainMapJpegImage.range = UHDR_CR_UNSPECIFIED;
+ ifd.close();
+ return loadFile(mGainMapJpegFile, mGainMapJpegImage.data, size);
+ }
+ return false;
+}
+
+void parse_argument(uhdr_gainmap_metadata* metadata, char* argument, float* value) {
+ if (!strcmp(argument, "maxContentBoost"))
+ metadata->max_content_boost = *value;
+ else if (!strcmp(argument, "minContentBoost"))
+ metadata->min_content_boost = *value;
+ else if (!strcmp(argument, "gamma"))
+ metadata->gamma = *value;
+ else if (!strcmp(argument, "offsetSdr"))
+ metadata->offset_sdr = *value;
+ else if (!strcmp(argument, "offsetHdr"))
+ metadata->offset_hdr = *value;
+ else if (!strcmp(argument, "hdrCapacityMin"))
+ metadata->hdr_capacity_min = *value;
+ else if (!strcmp(argument, "hdrCapacityMax"))
+ metadata->hdr_capacity_max = *value;
+ else
+ std::cout << " Ignoring argument " << argument << std::endl;
+}
+
+bool UltraHdrAppInput::fillGainMapMetadataDescriptor() {
+ std::ifstream file(mGainMapMetadataCfgFile);
+ if (!file.is_open()) {
+ return false;
+ }
+ std::string line;
+ char argument[128];
+ float value;
+ while (std::getline(file, line)) {
+ if (sscanf(line.c_str(), "--%s %f", argument, &value) == 2) {
+ parse_argument(&mMetadata, argument, &value);
+ }
+ }
+ file.close();
+ return true;
+}
+
bool UltraHdrAppInput::fillJpegRImageHandle() {
std::ifstream ifd(mJpegRFile, std::ios::binary | std::ios::ate);
if (ifd.good()) {
int size = ifd.tellg();
- mJpegImgR.length = size;
- mJpegImgR.maxLength = size;
+ mJpegImgR.capacity = size;
+ mJpegImgR.data_sz = size;
mJpegImgR.data = nullptr;
- mJpegImgR.colorGamut = mYuv420Cg;
+ mYuv420JpegImage.cg = UHDR_CG_UNSPECIFIED;
+ mYuv420JpegImage.ct = UHDR_CT_UNSPECIFIED;
+ mYuv420JpegImage.range = UHDR_CR_UNSPECIFIED;
ifd.close();
return loadFile(mJpegRFile, mJpegImgR.data, size);
}
@@ -302,140 +468,187 @@ bool UltraHdrAppInput::fillJpegRImageHandle() {
}
bool UltraHdrAppInput::encode() {
- if (!fillP010ImageHandle()) return false;
- if (mYuv420File != nullptr && !fillYuv420ImageHandle()) return false;
- if (mYuv420JpegFile != nullptr && !fillYuv420JpegImageHandle()) return false;
-
- mJpegImgR.maxLength = (std::max)(static_cast<size_t>(8 * 1024) /* min size 8kb */,
- mRawP010Image.width * mRawP010Image.height * 3 * 2);
- mJpegImgR.data = malloc(mJpegImgR.maxLength);
- if (mJpegImgR.data == nullptr) {
- std::cerr << "unable to allocate memory to store compressed image" << std::endl;
- return false;
+#define RET_IF_ERR(x) \
+ { \
+ uhdr_error_info_t status = (x); \
+ if (status.error_code != UHDR_CODEC_OK) { \
+ if (status.has_detail) { \
+ std::cerr << status.detail << std::endl; \
+ } \
+ uhdr_release_encoder(handle); \
+ return false; \
+ } \
}
- JpegR jpegHdr;
- status_t status = JPEGR_UNKNOWN_ERROR;
+ uhdr_codec_private_t* handle = uhdr_create_encoder();
+ if (mP010File != nullptr) {
+ if (!fillP010ImageHandle()) {
+ std::cerr << " failed to load file " << mP010File << std::endl;
+ return false;
+ }
+ RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawP010Image, UHDR_HDR_IMG))
+ }
+ if (mYuv420File != nullptr) {
+ if (!fillYuv420ImageHandle()) {
+ std::cerr << " failed to load file " << mYuv420File << std::endl;
+ return false;
+ }
+ RET_IF_ERR(uhdr_enc_set_raw_image(handle, &mRawYuv420Image, UHDR_SDR_IMG))
+ }
+ if (mYuv420JpegFile != nullptr) {
+ if (!fillYuv420JpegImageHandle()) {
+ std::cerr << " failed to load file " << mYuv420JpegFile << std::endl;
+ return false;
+ }
+ RET_IF_ERR(uhdr_enc_set_compressed_image(
+ handle, &mYuv420JpegImage,
+ (mGainMapJpegFile != nullptr && mGainMapMetadataCfgFile != nullptr) ? UHDR_BASE_IMG
+ : UHDR_SDR_IMG))
+ }
+ if (mGainMapJpegFile != nullptr && mGainMapMetadataCfgFile != nullptr) {
+ if (!fillGainMapJpegImageHandle()) {
+ std::cerr << " failed to load file " << mGainMapJpegFile << std::endl;
+ return false;
+ }
+ if (!fillGainMapMetadataDescriptor()) {
+ std::cerr << " failed to read config file " << mGainMapMetadataCfgFile << std::endl;
+ return false;
+ }
+ RET_IF_ERR(uhdr_enc_set_gainmap_image(handle, &mGainMapJpegImage, &mMetadata))
+ }
+ RET_IF_ERR(uhdr_enc_set_quality(handle, mQuality, UHDR_BASE_IMG))
#ifdef PROFILE_ENABLE
const int profileCount = 10;
Profiler profileEncode;
profileEncode.timerStart();
for (auto i = 0; i < profileCount; i++) {
#endif
- if (mYuv420File == nullptr && mYuv420JpegFile == nullptr) { // api-0
- status = jpegHdr.encodeJPEGR(&mRawP010Image, mTf, &mJpegImgR, mQuality, nullptr);
- if (JPEGR_NO_ERROR != status) {
- std::cerr << "Encountered error during encodeJPEGR call, error code " << status
- << std::endl;
- return false;
- }
- } else if (mYuv420File != nullptr && mYuv420JpegFile == nullptr) { // api-1
- status =
- jpegHdr.encodeJPEGR(&mRawP010Image, &mRawYuv420Image, mTf, &mJpegImgR, mQuality, nullptr);
- if (JPEGR_NO_ERROR != status) {
- std::cerr << "Encountered error during encodeJPEGR call, error code " << status
- << std::endl;
- return false;
- }
- } else if (mYuv420File != nullptr && mYuv420JpegFile != nullptr) { // api-2
- status =
- jpegHdr.encodeJPEGR(&mRawP010Image, &mRawYuv420Image, &mYuv420JpegImage, mTf, &mJpegImgR);
- if (JPEGR_NO_ERROR != status) {
- std::cerr << "Encountered error during encodeJPEGR call, error code " << status
- << std::endl;
- return false;
- }
- } else if (mYuv420File == nullptr && mYuv420JpegFile != nullptr) { // api-3
- status = jpegHdr.encodeJPEGR(&mRawP010Image, &mYuv420JpegImage, mTf, &mJpegImgR);
- if (JPEGR_NO_ERROR != status) {
- std::cerr << "Encountered error during encodeJPEGR call, error code " << status
- << std::endl;
- return false;
- }
- }
+ RET_IF_ERR(uhdr_encode(handle))
#ifdef PROFILE_ENABLE
}
profileEncode.timerStop();
auto avgEncTime = profileEncode.elapsedTime() / (profileCount * 1000.f);
printf("Average encode time for res %d x %d is %f ms \n", mWidth, mHeight, avgEncTime);
#endif
- writeFile("out.jpeg", mJpegImgR.data, mJpegImgR.length);
+
+#undef RET_IF_ERR
+
+ auto output = uhdr_get_encoded_stream(handle);
+
+ // for decoding
+ mJpegImgR.data = malloc(output->data_sz);
+ memcpy(mJpegImgR.data, output->data, output->data_sz);
+ mJpegImgR.capacity = mJpegImgR.data_sz = output->data_sz;
+ mJpegImgR.cg = output->cg;
+ mJpegImgR.ct = output->ct;
+ mJpegImgR.range = output->range;
+ writeFile("out.jpeg", output->data, output->data_sz);
+ uhdr_release_encoder(handle);
+
return true;
}
bool UltraHdrAppInput::decode() {
- if (mMode == 1 && !fillJpegRImageHandle()) return false;
- std::vector<uint8_t> iccData(0);
- std::vector<uint8_t> exifData(0);
- jpegr_info_struct info{};
- JpegR jpegHdr;
- status_t status = jpegHdr.getJPEGRInfo(&mJpegImgR, &info);
- if (JPEGR_NO_ERROR == status) {
- size_t outSize = info.width * info.height * ((mOf == ULTRAHDR_OUTPUT_HDR_LINEAR) ? 8 : 4);
- mDestImage.data = malloc(outSize);
- if (mDestImage.data == nullptr) {
- std::cerr << "failed to allocate memory to store decoded output" << std::endl;
- return false;
- }
+ if (mMode == 1 && !fillJpegRImageHandle()) {
+ std::cerr << " failed to load file " << mJpegRFile << std::endl;
+ return false;
+ }
+
+#define RET_IF_ERR(x) \
+ { \
+ uhdr_error_info_t status = (x); \
+ if (status.error_code != UHDR_CODEC_OK) { \
+ if (status.has_detail) { \
+ std::cerr << status.detail << std::endl; \
+ } \
+ uhdr_release_decoder(handle); \
+ return false; \
+ } \
+ }
+
+ uhdr_codec_private_t* handle = uhdr_create_decoder();
+ RET_IF_ERR(uhdr_dec_set_image(handle, &mJpegImgR))
+ RET_IF_ERR(uhdr_dec_set_out_color_transfer(handle, mOTf))
+ RET_IF_ERR(uhdr_dec_set_out_img_format(handle, mOfmt))
+
#ifdef PROFILE_ENABLE
- const int profileCount = 10;
- Profiler profileDecode;
- profileDecode.timerStart();
- for (auto i = 0; i < profileCount; i++) {
+ const int profileCount = 10;
+ Profiler profileDecode;
+ profileDecode.timerStart();
+ for (auto i = 0; i < profileCount; i++) {
#endif
- status =
- jpegHdr.decodeJPEGR(&mJpegImgR, &mDestImage, FLT_MAX, nullptr, mOf, nullptr, nullptr);
- if (JPEGR_NO_ERROR != status) {
- std::cerr << "Encountered error during decodeJPEGR call, error code " << status
- << std::endl;
- return false;
- }
+ RET_IF_ERR(uhdr_decode(handle))
#ifdef PROFILE_ENABLE
- }
- profileDecode.timerStop();
- auto avgDecTime = profileDecode.elapsedTime() / (profileCount * 1000.f);
- printf("Average decode time for res %ld x %ld is %f ms \n", info.width, info.height,
- avgDecTime);
+ }
+ profileDecode.timerStop();
+ auto avgDecTime = profileDecode.elapsedTime() / (profileCount * 1000.f);
+ printf("Average decode time for res %ld x %ld is %f ms \n", info.width, info.height, avgDecTime);
#endif
- writeFile("outrgb.raw", mDestImage.data, outSize);
- } else {
- std::cerr << "Encountered error during getJPEGRInfo call, error code " << status << std::endl;
- return false;
+
+#undef RET_IF_ERR
+
+ uhdr_raw_image_t* output = uhdr_get_decoded_image(handle);
+
+ mDestImage.fmt = output->fmt;
+ mDestImage.cg = output->cg;
+ mDestImage.ct = output->ct;
+ mDestImage.range = output->range;
+ mDestImage.w = output->w;
+ mDestImage.h = output->h;
+ int bpp = (output->fmt == UHDR_IMG_FMT_64bppRGBAHalfFloat) ? 8 : 4;
+ mDestImage.planes[UHDR_PLANE_PACKED] = malloc(output->w * output->h * bpp);
+ char* inData = static_cast<char*>(output->planes[UHDR_PLANE_PACKED]);
+ char* outData = static_cast<char*>(mDestImage.planes[UHDR_PLANE_PACKED]);
+ const size_t inStride = output->stride[UHDR_PLANE_PACKED] * bpp;
+ const size_t outStride = output->w * bpp;
+ mDestImage.stride[UHDR_PLANE_PACKED] = output->w;
+ const size_t length = output->w * bpp;
+ for (unsigned i = 0; i < output->h; i++, inData += inStride, outData += outStride) {
+ memcpy(outData, inData, length);
}
+ writeFile("outrgb.raw", output);
+ uhdr_release_decoder(handle);
+
return true;
}
+#define CLIP3(x, min, max) ((x) < (min)) ? (min) : ((x) > (max)) ? (max) : (x)
bool UltraHdrAppInput::convertP010ToRGBImage() {
const float* coeffs = BT2020YUVtoRGBMatrix;
- if (mP010Cg == ULTRAHDR_COLORGAMUT_BT709) {
+ if (mP010Cg == UHDR_CG_BT_709) {
coeffs = BT709YUVtoRGBMatrix;
- } else if (mP010Cg == ULTRAHDR_COLORGAMUT_BT2100) {
+ } else if (mP010Cg == UHDR_CG_BT_2100) {
coeffs = BT2020YUVtoRGBMatrix;
- } else if (mP010Cg == ULTRAHDR_COLORGAMUT_P3) {
+ } else if (mP010Cg == UHDR_CG_DISPLAY_P3) {
coeffs = BT601YUVtoRGBMatrix;
} else {
std::cerr << "color matrix not present for gamut " << mP010Cg << " using BT2020Matrix"
<< std::endl;
}
- mRawRgba1010102Image.data = malloc(mRawP010Image.width * mRawP010Image.height * 4);
- if (mRawRgba1010102Image.data == nullptr) {
- std::cerr << "failed to allocate memory to store Rgba1010102" << std::endl;
- return false;
- }
- mRawRgba1010102Image.width = mRawP010Image.width;
- mRawRgba1010102Image.height = mRawP010Image.height;
- mRawRgba1010102Image.colorGamut = mRawP010Image.colorGamut;
- uint32_t* rgbData = static_cast<uint32_t*>(mRawRgba1010102Image.data);
- uint16_t* y = static_cast<uint16_t*>(mRawP010Image.data);
- uint16_t* u = y + mRawP010Image.width * mRawP010Image.height;
+ mRawRgba1010102Image.fmt = UHDR_IMG_FMT_32bppRGBA1010102;
+ mRawRgba1010102Image.cg = mRawP010Image.cg;
+ mRawRgba1010102Image.ct = mRawP010Image.ct;
+ mRawRgba1010102Image.range = UHDR_CR_FULL_RANGE;
+ mRawRgba1010102Image.w = mRawP010Image.w;
+ mRawRgba1010102Image.h = mRawP010Image.h;
+ mRawRgba1010102Image.planes[UHDR_PLANE_PACKED] = malloc(mRawP010Image.w * mRawP010Image.h * 4);
+ mRawRgba1010102Image.planes[UHDR_PLANE_U] = nullptr;
+ mRawRgba1010102Image.planes[UHDR_PLANE_V] = nullptr;
+ mRawRgba1010102Image.stride[UHDR_PLANE_PACKED] = mWidth;
+ mRawRgba1010102Image.stride[UHDR_PLANE_U] = 0;
+ mRawRgba1010102Image.stride[UHDR_PLANE_V] = 0;
+
+ uint32_t* rgbData = static_cast<uint32_t*>(mRawRgba1010102Image.planes[UHDR_PLANE_PACKED]);
+ uint16_t* y = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_Y]);
+ uint16_t* u = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_UV]);
uint16_t* v = u + 1;
- for (size_t i = 0; i < mRawP010Image.height; i++) {
- for (size_t j = 0; j < mRawP010Image.width; j++) {
- float y0 = float(y[mRawP010Image.width * i + j] >> 6);
- float u0 = float(u[mRawP010Image.width * (i / 2) + (j / 2) * 2] >> 6);
- float v0 = float(v[mRawP010Image.width * (i / 2) + (j / 2) * 2] >> 6);
+ for (size_t i = 0; i < mRawP010Image.h; i++) {
+ for (size_t j = 0; j < mRawP010Image.w; j++) {
+ float y0 = float(y[mRawP010Image.stride[UHDR_PLANE_Y] * i + j] >> 6);
+ float u0 = float(u[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6);
+ float v0 = float(v[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6);
y0 = CLIP3(y0, 64.0f, 940.0f);
u0 = CLIP3(u0, 64.0f, 960.0f);
@@ -462,31 +675,35 @@ bool UltraHdrAppInput::convertP010ToRGBImage() {
rgbData++;
}
}
- writeFile("inRgba1010102.raw", mRawRgba1010102Image.data,
- mRawP010Image.width * mRawP010Image.height * 4);
+ writeFile("inRgba1010102.raw", &mRawRgba1010102Image);
return true;
}
bool UltraHdrAppInput::convertYuv420ToRGBImage() {
- mRawRgba8888Image.data = malloc(mRawYuv420Image.width * mRawYuv420Image.height * 4);
- if (mRawRgba8888Image.data == nullptr) {
- std::cerr << "failed to allocate memory to store rgba888" << std::endl;
- return false;
- }
- mRawRgba8888Image.width = mRawYuv420Image.width;
- mRawRgba8888Image.height = mRawYuv420Image.height;
- mRawRgba8888Image.colorGamut = mRawYuv420Image.colorGamut;
- uint32_t* rgbData = static_cast<uint32_t*>(mRawRgba8888Image.data);
- uint8_t* y = static_cast<uint8_t*>(mRawYuv420Image.data);
- uint8_t* u = y + (mRawYuv420Image.width * mRawYuv420Image.height);
- uint8_t* v = u + (mRawYuv420Image.width * mRawYuv420Image.height / 4);
+ mRawRgba8888Image.fmt = UHDR_IMG_FMT_32bppRGBA8888;
+ mRawRgba8888Image.cg = mRawYuv420Image.cg;
+ mRawRgba8888Image.ct = mRawYuv420Image.ct;
+ mRawRgba8888Image.range = UHDR_CR_FULL_RANGE;
+ mRawRgba8888Image.w = mRawYuv420Image.w;
+ mRawRgba8888Image.h = mRawYuv420Image.h;
+ mRawRgba8888Image.planes[UHDR_PLANE_PACKED] = malloc(mRawYuv420Image.w * mRawYuv420Image.h * 4);
+ mRawRgba8888Image.planes[UHDR_PLANE_U] = nullptr;
+ mRawRgba8888Image.planes[UHDR_PLANE_V] = nullptr;
+ mRawRgba8888Image.stride[UHDR_PLANE_PACKED] = mWidth;
+ mRawRgba8888Image.stride[UHDR_PLANE_U] = 0;
+ mRawRgba8888Image.stride[UHDR_PLANE_V] = 0;
+
+ uint32_t* rgbData = static_cast<uint32_t*>(mRawRgba8888Image.planes[UHDR_PLANE_PACKED]);
+ uint8_t* y = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_Y]);
+ uint8_t* u = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_U]);
+ uint8_t* v = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_V]);
const float* coeffs = BT601YUVtoRGBMatrix;
- for (size_t i = 0; i < mRawYuv420Image.height; i++) {
- for (size_t j = 0; j < mRawYuv420Image.width; j++) {
- float y0 = float(y[mRawYuv420Image.width * i + j]);
- float u0 = float(u[mRawYuv420Image.width / 2 * (i / 2) + (j / 2)] - 128);
- float v0 = float(v[mRawYuv420Image.width / 2 * (i / 2) + (j / 2)] - 128);
+ for (size_t i = 0; i < mRawYuv420Image.h; i++) {
+ for (size_t j = 0; j < mRawYuv420Image.w; j++) {
+ float y0 = float(y[mRawYuv420Image.stride[UHDR_PLANE_Y] * i + j]);
+ float u0 = float(u[mRawYuv420Image.stride[UHDR_PLANE_U] * (i / 2) + (j / 2)] - 128);
+ float v0 = float(v[mRawYuv420Image.stride[UHDR_PLANE_V] * (i / 2) + (j / 2)] - 128);
y0 /= 255.0f;
u0 /= 255.0f;
@@ -512,33 +729,36 @@ bool UltraHdrAppInput::convertYuv420ToRGBImage() {
rgbData++;
}
}
- writeFile("inRgba8888.raw", mRawRgba8888Image.data,
- mRawYuv420Image.width * mRawYuv420Image.height * 4);
+ writeFile("inRgba8888.raw", &mRawRgba8888Image);
return true;
}
bool UltraHdrAppInput::convertRgba8888ToYUV444Image() {
- mDestYUV444Image.data = malloc(mDestImage.width * mDestImage.height * 3);
- if (mDestYUV444Image.data == nullptr) {
- std::cerr << "failed to allocate memory to store yuv444" << std::endl;
- return false;
- }
- mDestYUV444Image.width = mDestImage.width;
- mDestYUV444Image.height = mDestImage.height;
- mDestYUV444Image.colorGamut = mDestImage.colorGamut;
-
- uint32_t* rgbData = static_cast<uint32_t*>(mDestImage.data);
-
- uint8_t* yData = static_cast<uint8_t*>(mDestYUV444Image.data);
- uint8_t* uData = yData + (mDestYUV444Image.width * mDestYUV444Image.height);
- uint8_t* vData = uData + (mDestYUV444Image.width * mDestYUV444Image.height);
+ mDestYUV444Image.fmt = static_cast<uhdr_img_fmt_t>(UHDR_IMG_FMT_24bppYCbCr444);
+ mDestYUV444Image.cg = mDestImage.cg;
+ mDestYUV444Image.ct = mDestImage.ct;
+ mDestYUV444Image.range = UHDR_CR_FULL_RANGE;
+ mDestYUV444Image.w = mDestImage.w;
+ mDestYUV444Image.h = mDestImage.h;
+ mDestYUV444Image.planes[UHDR_PLANE_Y] = malloc(mDestImage.w * mDestImage.h);
+ mDestYUV444Image.planes[UHDR_PLANE_U] = malloc(mDestImage.w * mDestImage.h);
+ mDestYUV444Image.planes[UHDR_PLANE_V] = malloc(mDestImage.w * mDestImage.h);
+ mDestYUV444Image.stride[UHDR_PLANE_Y] = mWidth;
+ mDestYUV444Image.stride[UHDR_PLANE_U] = mWidth;
+ mDestYUV444Image.stride[UHDR_PLANE_V] = mWidth;
+
+ uint32_t* rgbData = static_cast<uint32_t*>(mDestImage.planes[UHDR_PLANE_PACKED]);
+
+ uint8_t* yData = static_cast<uint8_t*>(mDestYUV444Image.planes[UHDR_PLANE_Y]);
+ uint8_t* uData = static_cast<uint8_t*>(mDestYUV444Image.planes[UHDR_PLANE_U]);
+ uint8_t* vData = static_cast<uint8_t*>(mDestYUV444Image.planes[UHDR_PLANE_V]);
const float* coeffs = BT601RGBtoYUVMatrix;
- for (size_t i = 0; i < mDestImage.height; i++) {
- for (size_t j = 0; j < mDestImage.width; j++) {
- float r0 = float(rgbData[mDestImage.width * i + j] & 0xff);
- float g0 = float((rgbData[mDestImage.width * i + j] >> 8) & 0xff);
- float b0 = float((rgbData[mDestImage.width * i + j] >> 16) & 0xff);
+ for (size_t i = 0; i < mDestImage.h; i++) {
+ for (size_t j = 0; j < mDestImage.w; j++) {
+ float r0 = float(rgbData[mDestImage.stride[UHDR_PLANE_PACKED] * i + j] & 0xff);
+ float g0 = float((rgbData[mDestImage.stride[UHDR_PLANE_PACKED] * i + j] >> 8) & 0xff);
+ float b0 = float((rgbData[mDestImage.stride[UHDR_PLANE_PACKED] * i + j] >> 16) & 0xff);
r0 /= 255.0f;
g0 /= 255.0f;
@@ -556,49 +776,52 @@ bool UltraHdrAppInput::convertRgba8888ToYUV444Image() {
u = CLIP3(u, 0.0f, 255.0f);
v = CLIP3(v, 0.0f, 255.0f);
- yData[mDestYUV444Image.width * i + j] = uint8_t(y);
- uData[mDestYUV444Image.width * i + j] = uint8_t(u);
- vData[mDestYUV444Image.width * i + j] = uint8_t(v);
+ yData[mDestYUV444Image.stride[UHDR_PLANE_Y] * i + j] = uint8_t(y);
+ uData[mDestYUV444Image.stride[UHDR_PLANE_U] * i + j] = uint8_t(u);
+ vData[mDestYUV444Image.stride[UHDR_PLANE_V] * i + j] = uint8_t(v);
}
}
- writeFile("outyuv444.yuv", mDestYUV444Image.data,
- mDestYUV444Image.width * mDestYUV444Image.height * 3);
+ writeFile("outyuv444.yuv", &mDestYUV444Image);
return true;
}
bool UltraHdrAppInput::convertRgba1010102ToYUV444Image() {
const float* coeffs = BT2020RGBtoYUVMatrix;
- if (mP010Cg == ULTRAHDR_COLORGAMUT_BT709) {
+ if (mP010Cg == UHDR_CG_BT_709) {
coeffs = BT709RGBtoYUVMatrix;
- } else if (mP010Cg == ULTRAHDR_COLORGAMUT_BT2100) {
+ } else if (mP010Cg == UHDR_CG_BT_2100) {
coeffs = BT2020RGBtoYUVMatrix;
- } else if (mP010Cg == ULTRAHDR_COLORGAMUT_P3) {
+ } else if (mP010Cg == UHDR_CG_DISPLAY_P3) {
coeffs = BT601RGBtoYUVMatrix;
} else {
std::cerr << "color matrix not present for gamut " << mP010Cg << " using BT2020Matrix"
<< std::endl;
}
- mDestYUV444Image.data = malloc(mDestImage.width * mDestImage.height * 3 * 2);
- if (mDestYUV444Image.data == nullptr) {
- std::cerr << "failed to allocate memory to store yuv444" << std::endl;
- return false;
- }
- mDestYUV444Image.width = mDestImage.width;
- mDestYUV444Image.height = mDestImage.height;
- mDestYUV444Image.colorGamut = mDestImage.colorGamut;
-
- uint32_t* rgbData = static_cast<uint32_t*>(mDestImage.data);
-
- uint16_t* yData = static_cast<uint16_t*>(mDestYUV444Image.data);
- uint16_t* uData = yData + (mDestYUV444Image.width * mDestYUV444Image.height);
- uint16_t* vData = uData + (mDestYUV444Image.width * mDestYUV444Image.height);
-
- for (size_t i = 0; i < mDestImage.height; i++) {
- for (size_t j = 0; j < mDestImage.width; j++) {
- float r0 = float(rgbData[mDestImage.width * i + j] & 0x3ff);
- float g0 = float((rgbData[mDestImage.width * i + j] >> 10) & 0x3ff);
- float b0 = float((rgbData[mDestImage.width * i + j] >> 20) & 0x3ff);
+ mDestYUV444Image.fmt = static_cast<uhdr_img_fmt_t>(UHDR_IMG_FMT_48bppYCbCr444);
+ mDestYUV444Image.cg = mDestImage.cg;
+ mDestYUV444Image.ct = mDestImage.ct;
+ mDestYUV444Image.range = UHDR_CR_FULL_RANGE;
+ mDestYUV444Image.w = mDestImage.w;
+ mDestYUV444Image.h = mDestImage.h;
+ mDestYUV444Image.planes[UHDR_PLANE_Y] = malloc(mDestImage.w * mDestImage.h * 2);
+ mDestYUV444Image.planes[UHDR_PLANE_U] = malloc(mDestImage.w * mDestImage.h * 2);
+ mDestYUV444Image.planes[UHDR_PLANE_V] = malloc(mDestImage.w * mDestImage.h * 2);
+ mDestYUV444Image.stride[UHDR_PLANE_Y] = mWidth;
+ mDestYUV444Image.stride[UHDR_PLANE_U] = mWidth;
+ mDestYUV444Image.stride[UHDR_PLANE_V] = mWidth;
+
+ uint32_t* rgbData = static_cast<uint32_t*>(mDestImage.planes[UHDR_PLANE_PACKED]);
+
+ uint16_t* yData = static_cast<uint16_t*>(mDestYUV444Image.planes[UHDR_PLANE_Y]);
+ uint16_t* uData = static_cast<uint16_t*>(mDestYUV444Image.planes[UHDR_PLANE_U]);
+ uint16_t* vData = static_cast<uint16_t*>(mDestYUV444Image.planes[UHDR_PLANE_V]);
+
+ for (size_t i = 0; i < mDestImage.h; i++) {
+ for (size_t j = 0; j < mDestImage.w; j++) {
+ float r0 = float(rgbData[mDestImage.stride[UHDR_PLANE_PACKED] * i + j] & 0x3ff);
+ float g0 = float((rgbData[mDestImage.stride[UHDR_PLANE_PACKED] * i + j] >> 10) & 0x3ff);
+ float b0 = float((rgbData[mDestImage.stride[UHDR_PLANE_PACKED] * i + j] >> 20) & 0x3ff);
r0 /= 1023.0f;
g0 /= 1023.0f;
@@ -616,35 +839,33 @@ bool UltraHdrAppInput::convertRgba1010102ToYUV444Image() {
u = CLIP3(u, 64.0f, 960.0f);
v = CLIP3(v, 64.0f, 960.0f);
- yData[mDestYUV444Image.width * i + j] = uint16_t(y);
- uData[mDestYUV444Image.width * i + j] = uint16_t(u);
- vData[mDestYUV444Image.width * i + j] = uint16_t(v);
+ yData[mDestYUV444Image.stride[UHDR_PLANE_Y] * i + j] = uint16_t(y);
+ uData[mDestYUV444Image.stride[UHDR_PLANE_U] * i + j] = uint16_t(u);
+ vData[mDestYUV444Image.stride[UHDR_PLANE_V] * i + j] = uint16_t(v);
}
}
- writeFile("outyuv444.yuv", mDestYUV444Image.data,
- mDestYUV444Image.width * mDestYUV444Image.height * 3 * 2);
+ writeFile("outyuv444.yuv", &mDestYUV444Image);
return true;
}
void UltraHdrAppInput::computeRGBHdrPSNR() {
- if (mOf == ULTRAHDR_OUTPUT_SDR || mOf == ULTRAHDR_OUTPUT_HDR_LINEAR) {
- std::cout << "psnr not supported for output format " << mOf << std::endl;
+ if (mOfmt != UHDR_IMG_FMT_32bppRGBA1010102) {
+ std::cout << "psnr not supported for output format " << mOfmt << std::endl;
return;
}
- uint32_t* rgbDataSrc = static_cast<uint32_t*>(mRawRgba1010102Image.data);
- uint32_t* rgbDataDst = static_cast<uint32_t*>(mDestImage.data);
+ uint32_t* rgbDataSrc = static_cast<uint32_t*>(mRawRgba1010102Image.planes[UHDR_PLANE_PACKED]);
+ uint32_t* rgbDataDst = static_cast<uint32_t*>(mDestImage.planes[UHDR_PLANE_PACKED]);
if (rgbDataSrc == nullptr || rgbDataDst == nullptr) {
std::cerr << "invalid src or dst pointer for psnr computation " << std::endl;
return;
}
- if ((mOf == ULTRAHDR_OUTPUT_HDR_PQ && mTf != ULTRAHDR_TF_PQ) ||
- (mOf == ULTRAHDR_OUTPUT_HDR_HLG && mTf != ULTRAHDR_TF_HLG)) {
+ if (mOTf != mP010Tf) {
std::cout << "input transfer function and output format are not compatible, psnr results "
"may be unreliable"
<< std::endl;
}
uint64_t rSqError = 0, gSqError = 0, bSqError = 0;
- for (size_t i = 0; i < mRawP010Image.width * mRawP010Image.height; i++) {
+ for (size_t i = 0; i < mRawP010Image.w * mRawP010Image.h; i++) {
int rSrc = *rgbDataSrc & 0x3ff;
int rDst = *rgbDataDst & 0x3ff;
rSqError += (rSrc - rDst) * (rSrc - rDst);
@@ -660,13 +881,13 @@ void UltraHdrAppInput::computeRGBHdrPSNR() {
rgbDataSrc++;
rgbDataDst++;
}
- double meanSquareError = (double)rSqError / (mRawP010Image.width * mRawP010Image.height);
+ double meanSquareError = (double)rSqError / (mRawP010Image.w * mRawP010Image.h);
mPsnr[0] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
- meanSquareError = (double)gSqError / (mRawP010Image.width * mRawP010Image.height);
+ meanSquareError = (double)gSqError / (mRawP010Image.w * mRawP010Image.h);
mPsnr[1] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
- meanSquareError = (double)bSqError / (mRawP010Image.width * mRawP010Image.height);
+ meanSquareError = (double)bSqError / (mRawP010Image.w * mRawP010Image.h);
mPsnr[2] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
std::cout << "psnr r :: " << mPsnr[0] << " psnr g :: " << mPsnr[1] << " psnr b :: " << mPsnr[2]
@@ -674,19 +895,19 @@ void UltraHdrAppInput::computeRGBHdrPSNR() {
}
void UltraHdrAppInput::computeRGBSdrPSNR() {
- if (mOf != ULTRAHDR_OUTPUT_SDR) {
- std::cout << "psnr not supported for output format " << mOf << std::endl;
+ if (mOfmt != UHDR_IMG_FMT_32bppRGBA8888) {
+ std::cout << "psnr not supported for output format " << mOfmt << std::endl;
return;
}
- uint32_t* rgbDataSrc = static_cast<uint32_t*>(mRawRgba8888Image.data);
- uint32_t* rgbDataDst = static_cast<uint32_t*>(mDestImage.data);
+ uint32_t* rgbDataSrc = static_cast<uint32_t*>(mRawRgba8888Image.planes[UHDR_PLANE_PACKED]);
+ uint32_t* rgbDataDst = static_cast<uint32_t*>(mDestImage.planes[UHDR_PLANE_PACKED]);
if (rgbDataSrc == nullptr || rgbDataDst == nullptr) {
std::cerr << "invalid src or dst pointer for psnr computation " << std::endl;
return;
}
uint64_t rSqError = 0, gSqError = 0, bSqError = 0;
- for (size_t i = 0; i < mRawYuv420Image.width * mRawYuv420Image.height; i++) {
+ for (size_t i = 0; i < mRawYuv420Image.w * mRawYuv420Image.h; i++) {
int rSrc = *rgbDataSrc & 0xff;
int rDst = *rgbDataDst & 0xff;
rSqError += (rSrc - rDst) * (rSrc - rDst);
@@ -702,13 +923,13 @@ void UltraHdrAppInput::computeRGBSdrPSNR() {
rgbDataSrc++;
rgbDataDst++;
}
- double meanSquareError = (double)rSqError / (mRawYuv420Image.width * mRawYuv420Image.height);
+ double meanSquareError = (double)rSqError / (mRawYuv420Image.w * mRawYuv420Image.h);
mPsnr[0] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
- meanSquareError = (double)gSqError / (mRawYuv420Image.width * mRawYuv420Image.height);
+ meanSquareError = (double)gSqError / (mRawYuv420Image.w * mRawYuv420Image.h);
mPsnr[1] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
- meanSquareError = (double)bSqError / (mRawYuv420Image.width * mRawYuv420Image.height);
+ meanSquareError = (double)bSqError / (mRawYuv420Image.w * mRawYuv420Image.h);
mPsnr[2] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
std::cout << "psnr r :: " << mPsnr[0] << " psnr g :: " << mPsnr[1] << " psnr b :: " << mPsnr[2]
@@ -716,68 +937,67 @@ void UltraHdrAppInput::computeRGBSdrPSNR() {
}
void UltraHdrAppInput::computeYUVHdrPSNR() {
- if (mOf == ULTRAHDR_OUTPUT_SDR || mOf == ULTRAHDR_OUTPUT_HDR_LINEAR) {
- std::cout << "psnr not supported for output format " << mOf << std::endl;
+ if (mOfmt != UHDR_IMG_FMT_32bppRGBA1010102) {
+ std::cout << "psnr not supported for output format " << mOfmt << std::endl;
return;
}
- uint16_t* yuvDataSrc = static_cast<uint16_t*>(mRawP010Image.data);
- uint16_t* yuvDataDst = static_cast<uint16_t*>(mDestYUV444Image.data);
- if (yuvDataSrc == nullptr || yuvDataDst == nullptr) {
+ uint16_t* yDataSrc = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_Y]);
+ uint16_t* uDataSrc = static_cast<uint16_t*>(mRawP010Image.planes[UHDR_PLANE_UV]);
+ uint16_t* vDataSrc = uDataSrc + 1;
+
+ uint16_t* yDataDst = static_cast<uint16_t*>(mDestYUV444Image.planes[UHDR_PLANE_Y]);
+ uint16_t* uDataDst = static_cast<uint16_t*>(mDestYUV444Image.planes[UHDR_PLANE_U]);
+ uint16_t* vDataDst = static_cast<uint16_t*>(mDestYUV444Image.planes[UHDR_PLANE_V]);
+ if (yDataSrc == nullptr || uDataSrc == nullptr || yDataDst == nullptr || uDataDst == nullptr ||
+ vDataDst == nullptr) {
std::cerr << "invalid src or dst pointer for psnr computation " << std::endl;
return;
}
- if ((mOf == ULTRAHDR_OUTPUT_HDR_PQ && mTf != ULTRAHDR_TF_PQ) ||
- (mOf == ULTRAHDR_OUTPUT_HDR_HLG && mTf != ULTRAHDR_TF_HLG)) {
+ if (mOTf != mP010Tf) {
std::cout << "input transfer function and output format are not compatible, psnr results "
"may be unreliable"
<< std::endl;
}
- uint16_t* yDataSrc = static_cast<uint16_t*>(mRawP010Image.data);
- uint16_t* uDataSrc = yDataSrc + (mRawP010Image.width * mRawP010Image.height);
- uint16_t* vDataSrc = uDataSrc + 1;
-
- uint16_t* yDataDst = static_cast<uint16_t*>(mDestYUV444Image.data);
- uint16_t* uDataDst = yDataDst + (mDestYUV444Image.width * mDestYUV444Image.height);
- uint16_t* vDataDst = uDataDst + (mDestYUV444Image.width * mDestYUV444Image.height);
-
uint64_t ySqError = 0, uSqError = 0, vSqError = 0;
- for (size_t i = 0; i < mDestYUV444Image.height; i++) {
- for (size_t j = 0; j < mDestYUV444Image.width; j++) {
- int ySrc = (yDataSrc[mRawP010Image.width * i + j] >> 6) & 0x3ff;
+ for (size_t i = 0; i < mDestYUV444Image.h; i++) {
+ for (size_t j = 0; j < mDestYUV444Image.w; j++) {
+ int ySrc = (yDataSrc[mRawP010Image.stride[UHDR_PLANE_Y] * i + j] >> 6) & 0x3ff;
ySrc = CLIP3(ySrc, 64, 940);
- int yDst = yDataDst[mDestYUV444Image.width * i + j] & 0x3ff;
+ int yDst = yDataDst[mDestYUV444Image.stride[UHDR_PLANE_Y] * i + j] & 0x3ff;
ySqError += (ySrc - yDst) * (ySrc - yDst);
if (i % 2 == 0 && j % 2 == 0) {
- int uSrc = (uDataSrc[mRawP010Image.width * (i / 2) + (j / 2) * 2] >> 6) & 0x3ff;
+ int uSrc =
+ (uDataSrc[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6) & 0x3ff;
uSrc = CLIP3(uSrc, 64, 960);
- int uDst = uDataDst[mDestYUV444Image.width * i + j] & 0x3ff;
- uDst += uDataDst[mDestYUV444Image.width * i + j + 1] & 0x3ff;
- uDst += uDataDst[mDestYUV444Image.width * (i + 1) + j + 1] & 0x3ff;
- uDst += uDataDst[mDestYUV444Image.width * (i + 1) + j + 1] & 0x3ff;
+ int uDst = uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * i + j] & 0x3ff;
+ uDst += uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * i + j + 1] & 0x3ff;
+ uDst += uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * (i + 1) + j + 1] & 0x3ff;
+ uDst += uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * (i + 1) + j + 1] & 0x3ff;
uDst = (uDst + 2) >> 2;
uSqError += (uSrc - uDst) * (uSrc - uDst);
- int vSrc = (vDataSrc[mRawP010Image.width * (i / 2) + (j / 2) * 2] >> 6) & 0x3ff;
+ int vSrc =
+ (vDataSrc[mRawP010Image.stride[UHDR_PLANE_UV] * (i / 2) + (j / 2) * 2] >> 6) & 0x3ff;
vSrc = CLIP3(vSrc, 64, 960);
- int vDst = vDataDst[mDestYUV444Image.width * i + j] & 0x3ff;
- vDst += vDataDst[mDestYUV444Image.width * i + j + 1] & 0x3ff;
- vDst += vDataDst[mDestYUV444Image.width * (i + 1) + j + 1] & 0x3ff;
- vDst += vDataDst[mDestYUV444Image.width * (i + 1) + j + 1] & 0x3ff;
+ int vDst = vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * i + j] & 0x3ff;
+ vDst += vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * i + j + 1] & 0x3ff;
+ vDst += vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * (i + 1) + j + 1] & 0x3ff;
+ vDst += vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * (i + 1) + j + 1] & 0x3ff;
vDst = (vDst + 2) >> 2;
vSqError += (vSrc - vDst) * (vSrc - vDst);
}
}
}
- double meanSquareError = (double)ySqError / (mDestYUV444Image.width * mDestYUV444Image.height);
+ double meanSquareError = (double)ySqError / (mDestYUV444Image.w * mDestYUV444Image.h);
mPsnr[0] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
- meanSquareError = (double)uSqError / (mDestYUV444Image.width * mDestYUV444Image.height / 4);
+ meanSquareError = (double)uSqError / (mDestYUV444Image.w * mDestYUV444Image.h / 4);
mPsnr[1] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
- meanSquareError = (double)vSqError / (mDestYUV444Image.width * mDestYUV444Image.height / 4);
+ meanSquareError = (double)vSqError / (mDestYUV444Image.w * mDestYUV444Image.h / 4);
mPsnr[2] = meanSquareError ? 10 * log10((double)1023 * 1023 / meanSquareError) : 100;
std::cout << "psnr y :: " << mPsnr[0] << " psnr u :: " << mPsnr[1] << " psnr v :: " << mPsnr[2]
@@ -785,52 +1005,52 @@ void UltraHdrAppInput::computeYUVHdrPSNR() {
}
void UltraHdrAppInput::computeYUVSdrPSNR() {
- if (mOf != ULTRAHDR_OUTPUT_SDR) {
- std::cout << "psnr not supported for output format " << mOf << std::endl;
+ if (mOfmt != UHDR_IMG_FMT_32bppRGBA8888) {
+ std::cout << "psnr not supported for output format " << mOfmt << std::endl;
return;
}
- uint8_t* yDataSrc = static_cast<uint8_t*>(mRawYuv420Image.data);
- uint8_t* uDataSrc = yDataSrc + (mRawYuv420Image.width * mRawYuv420Image.height);
- uint8_t* vDataSrc = uDataSrc + (mRawYuv420Image.width * mRawYuv420Image.height / 4);
+ uint8_t* yDataSrc = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_Y]);
+ uint8_t* uDataSrc = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_U]);
+ uint8_t* vDataSrc = static_cast<uint8_t*>(mRawYuv420Image.planes[UHDR_PLANE_V]);
- uint8_t* yDataDst = static_cast<uint8_t*>(mDestYUV444Image.data);
- uint8_t* uDataDst = yDataDst + (mDestYUV444Image.width * mDestYUV444Image.height);
- uint8_t* vDataDst = uDataDst + (mDestYUV444Image.width * mDestYUV444Image.height);
+ uint8_t* yDataDst = static_cast<uint8_t*>(mDestYUV444Image.planes[UHDR_PLANE_Y]);
+ uint8_t* uDataDst = static_cast<uint8_t*>(mDestYUV444Image.planes[UHDR_PLANE_U]);
+ uint8_t* vDataDst = static_cast<uint8_t*>(mDestYUV444Image.planes[UHDR_PLANE_V]);
uint64_t ySqError = 0, uSqError = 0, vSqError = 0;
- for (size_t i = 0; i < mDestYUV444Image.height; i++) {
- for (size_t j = 0; j < mDestYUV444Image.width; j++) {
- int ySrc = yDataSrc[mRawYuv420Image.width * i + j];
- int yDst = yDataDst[mDestYUV444Image.width * i + j];
+ for (size_t i = 0; i < mDestYUV444Image.h; i++) {
+ for (size_t j = 0; j < mDestYUV444Image.w; j++) {
+ int ySrc = yDataSrc[mRawYuv420Image.stride[UHDR_PLANE_Y] * i + j];
+ int yDst = yDataDst[mDestYUV444Image.stride[UHDR_PLANE_Y] * i + j];
ySqError += (ySrc - yDst) * (ySrc - yDst);
if (i % 2 == 0 && j % 2 == 0) {
- int uSrc = uDataSrc[mRawYuv420Image.width / 2 * (i / 2) + j / 2];
- int uDst = uDataDst[mDestYUV444Image.width * i + j];
- uDst += uDataDst[mDestYUV444Image.width * i + j + 1];
- uDst += uDataDst[mDestYUV444Image.width * (i + 1) + j];
- uDst += uDataDst[mDestYUV444Image.width * (i + 1) + j + 1];
+ int uSrc = uDataSrc[mRawYuv420Image.stride[UHDR_PLANE_U] * (i / 2) + j / 2];
+ int uDst = uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * i + j];
+ uDst += uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * i + j + 1];
+ uDst += uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * (i + 1) + j];
+ uDst += uDataDst[mDestYUV444Image.stride[UHDR_PLANE_U] * (i + 1) + j + 1];
uDst = (uDst + 2) >> 2;
uSqError += (uSrc - uDst) * (uSrc - uDst);
- int vSrc = vDataSrc[mRawYuv420Image.width / 2 * (i / 2) + j / 2];
- int vDst = vDataDst[mDestYUV444Image.width * i + j];
- vDst += vDataDst[mDestYUV444Image.width * i + j + 1];
- vDst += vDataDst[mDestYUV444Image.width * (i + 1) + j];
- vDst += vDataDst[mDestYUV444Image.width * (i + 1) + j + 1];
+ int vSrc = vDataSrc[mRawYuv420Image.stride[UHDR_PLANE_V] * (i / 2) + j / 2];
+ int vDst = vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * i + j];
+ vDst += vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * i + j + 1];
+ vDst += vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * (i + 1) + j];
+ vDst += vDataDst[mDestYUV444Image.stride[UHDR_PLANE_V] * (i + 1) + j + 1];
vDst = (vDst + 2) >> 2;
vSqError += (vSrc - vDst) * (vSrc - vDst);
}
}
}
- double meanSquareError = (double)ySqError / (mDestYUV444Image.width * mDestYUV444Image.height);
+ double meanSquareError = (double)ySqError / (mDestYUV444Image.w * mDestYUV444Image.h);
mPsnr[0] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
- meanSquareError = (double)uSqError / (mDestYUV444Image.width * mDestYUV444Image.height / 4);
+ meanSquareError = (double)uSqError / (mDestYUV444Image.w * mDestYUV444Image.h / 4);
mPsnr[1] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
- meanSquareError = (double)vSqError / (mDestYUV444Image.width * mDestYUV444Image.height / 4);
+ meanSquareError = (double)vSqError / (mDestYUV444Image.w * mDestYUV444Image.h / 4);
mPsnr[2] = meanSquareError ? 10 * log10((double)255 * 255 / meanSquareError) : 100;
std::cout << "psnr y :: " << mPsnr[0] << " psnr u:: " << mPsnr[1] << " psnr v :: " << mPsnr[2]
@@ -841,16 +1061,18 @@ static void usage(const char* name) {
fprintf(stderr, "\n## ultra hdr demo application.\nUsage : %s \n", name);
fprintf(stderr, " -m mode of operation. [0:encode, 1:decode] \n");
fprintf(stderr, "\n## encoder options : \n");
- fprintf(stderr, " -p raw 10 bit input resource in p010 color format, mandatory. \n");
+ fprintf(stderr, " -p raw 10 bit input resource in p010 color format. \n");
fprintf(stderr,
" -y raw 8 bit input resource in yuv420, optional. \n"
" if not provided tonemapping happens internally. \n");
- fprintf(stderr, " -i compressed 8 bit jpeg file path, optional \n");
- fprintf(stderr, " -w input file width, mandatory. \n");
- fprintf(stderr, " -h input file height, mandatory. \n");
+ fprintf(stderr, " -i compressed 8 bit jpeg file path. \n");
+ fprintf(stderr, " -g compressed 8 bit gainmap file path. \n");
+ fprintf(stderr, " -f gainmap metadata config file. \n");
+ fprintf(stderr, " -w input file width. \n");
+ fprintf(stderr, " -h input file height. \n");
fprintf(stderr, " -C 10 bit input color gamut, optional. [0:bt709, 1:p3, 2:bt2100] \n");
fprintf(stderr, " -c 8 bit input color gamut, optional. [0:bt709, 1:p3, 2:bt2100] \n");
- fprintf(stderr, " -t input transfer function, optional. [0:linear, 1:hlg, 2:pq] \n");
+ fprintf(stderr, " -t 10 bit input transfer function, optional. [0:linear, 1:hlg, 2:pq] \n");
fprintf(stderr,
" -q quality factor to be used while encoding 8 bit image, optional. [0-100].\n"
" gain map image does not use this quality factor. \n"
@@ -859,22 +1081,23 @@ static void usage(const char* name) {
fprintf(stderr, "\n## decoder options : \n");
fprintf(stderr, " -j ultra hdr input resource, mandatory in decode mode. \n");
fprintf(stderr,
- " -o output transfer function, optional. [0:sdr, 1:hdr_linear, 2:hdr_pq, "
- "3:hdr_hlg] \n");
+ " -o output transfer function, optional. [0:linear, 1:hlg, 2:pq, 3:srgb] \n");
+ fprintf(stderr,
+ " -O output color format, optional. [3:rgba8888, 4:rgbahalffloat, 5:rgba1010102] \n"
+ "It should be noted that not all combinations of output color format and output transfer "
+ "function are supported. srgb output color transfer shall be paired with rgba8888 only. "
+ "hlg, pq shall be paired with rgba1010102. linear shall be paired with rgbahalffloat");
fprintf(stderr, "\n## examples of usage :\n");
fprintf(stderr, "\n## encode api-0 :\n");
fprintf(stderr, " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97\n");
fprintf(stderr,
- " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97 -C 2 -t 2\n");
+ " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -w 1920 -h 1080 -q 97 -C 1 -t 2\n");
fprintf(stderr, "\n## encode api-1 :\n");
fprintf(stderr,
" ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
"-h 1080 -q 97\n");
fprintf(stderr,
" ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
- "-h 1080 -q 97\n");
- fprintf(stderr,
- " ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
"-h 1080 -q 97 -C 2 -c 1 -t 1\n");
fprintf(stderr,
" ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -w 1920 "
@@ -882,27 +1105,34 @@ static void usage(const char* name) {
fprintf(stderr, "\n## encode api-2 :\n");
fprintf(stderr,
" ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -y cosmat_1920x1080_420.yuv -i "
- "cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 3 -e 1\n");
+ "cosmat_1920x1080_420_8bit.jpg -w 1920 -h 1080 -t 1 -o 3 -O 3 -e 1\n");
fprintf(stderr, "\n## encode api-3 :\n");
fprintf(stderr,
" ultrahdr_app -m 0 -p cosmat_1920x1080_p010.yuv -i cosmat_1920x1080_420_8bit.jpg -w "
- "1920 -h 1080 -t 1 -o 3 -e 1\n");
+ "1920 -h 1080 -t 1 -o 1 -O 5 -e 1\n");
+ fprintf(stderr, "\n## encode api-4 :\n");
+ fprintf(stderr,
+ " ultrahdr_app -m 0 -i cosmat_1920x1080_420_8bit.jpg -g cosmat_1920x1080_420_8bit.jpg "
+ "-f metadata.cfg\n");
fprintf(stderr, "\n## decode api :\n");
fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg \n");
- fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg -o 2\n");
+ fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg -o 3 -O 3\n");
+ fprintf(stderr, " ultrahdr_app -m 1 -j cosmat_1920x1080_hdr.jpg -o 1 -O 5\n");
fprintf(stderr, "\n");
}
int main(int argc, char* argv[]) {
- char opt_string[] = "p:y:i:w:h:C:c:t:q:o:m:j:e:";
+ char opt_string[] = "p:y:i:g:f:w:h:C:c:t:q:o:O:m:j:e:";
char *p010_file = nullptr, *yuv420_file = nullptr, *jpegr_file = nullptr,
- *yuv420_jpeg_file = nullptr;
+ *yuv420_jpeg_file = nullptr, *gainmap_jpeg_file = nullptr,
+ *gainmap_metadata_cfg_file = nullptr;
int width = 0, height = 0;
- ultrahdr_color_gamut p010Cg = ULTRAHDR_COLORGAMUT_BT709;
- ultrahdr_color_gamut yuv420Cg = ULTRAHDR_COLORGAMUT_BT709;
- ultrahdr_transfer_function tf = ULTRAHDR_TF_HLG;
+ uhdr_color_gamut_t p010Cg = UHDR_CG_BT_709;
+ uhdr_color_gamut_t yuv420Cg = UHDR_CG_BT_709;
+ uhdr_color_transfer_t p010Tf = UHDR_CT_HLG;
int quality = 100;
- ultrahdr_output_format of = ULTRAHDR_OUTPUT_HDR_HLG;
+ uhdr_color_transfer_t outTf = UHDR_CT_HLG;
+ uhdr_img_fmt_t outFmt = UHDR_IMG_FMT_32bppRGBA1010102;
int mode = 0;
int compute_psnr = 0;
int ch;
@@ -917,6 +1147,12 @@ int main(int argc, char* argv[]) {
case 'i':
yuv420_jpeg_file = optarg_s;
break;
+ case 'g':
+ gainmap_jpeg_file = optarg_s;
+ break;
+ case 'f':
+ gainmap_metadata_cfg_file = optarg_s;
+ break;
case 'w':
width = atoi(optarg_s);
break;
@@ -924,19 +1160,22 @@ int main(int argc, char* argv[]) {
height = atoi(optarg_s);
break;
case 'C':
- p010Cg = static_cast<ultrahdr_color_gamut>(atoi(optarg_s));
+ p010Cg = static_cast<uhdr_color_gamut_t>(atoi(optarg_s));
break;
case 'c':
- yuv420Cg = static_cast<ultrahdr_color_gamut>(atoi(optarg_s));
+ yuv420Cg = static_cast<uhdr_color_gamut_t>(atoi(optarg_s));
break;
case 't':
- tf = static_cast<ultrahdr_transfer_function>(atoi(optarg_s));
+ p010Tf = static_cast<uhdr_color_transfer_t>(atoi(optarg_s));
break;
case 'q':
quality = atoi(optarg_s);
break;
+ case 'O':
+ outFmt = static_cast<uhdr_img_fmt_t>(atoi(optarg_s));
+ break;
case 'o':
- of = static_cast<ultrahdr_output_format>(atoi(optarg_s));
+ outTf = static_cast<uhdr_color_transfer_t>(atoi(optarg_s));
break;
case 'm':
mode = atoi(optarg_s);
@@ -953,25 +1192,30 @@ int main(int argc, char* argv[]) {
}
}
if (mode == 0) {
- if (width <= 0 || height <= 0 || p010_file == nullptr) {
+ if ((width <= 0 || height <= 0 || p010_file == nullptr) &&
+ (yuv420_jpeg_file == nullptr || gainmap_jpeg_file == nullptr ||
+ gainmap_metadata_cfg_file == nullptr)) {
usage(argv[0]);
return -1;
}
- UltraHdrAppInput appInput(p010_file, yuv420_file, yuv420_jpeg_file, width, height, p010Cg,
- yuv420Cg, tf, quality, of);
+ UltraHdrAppInput appInput(p010_file, yuv420_file, yuv420_jpeg_file, gainmap_jpeg_file,
+ gainmap_metadata_cfg_file, width, height, p010Cg, yuv420Cg, p010Tf,
+ quality, outTf, outFmt);
if (!appInput.encode()) return -1;
if (compute_psnr == 1) {
if (!appInput.decode()) return -1;
- if (of == ULTRAHDR_OUTPUT_SDR && yuv420_file != nullptr) {
+ if (outFmt == UHDR_IMG_FMT_32bppRGBA8888 && yuv420_file != nullptr) {
appInput.convertYuv420ToRGBImage();
appInput.computeRGBSdrPSNR();
appInput.convertRgba8888ToYUV444Image();
appInput.computeYUVSdrPSNR();
- } else if (of == ULTRAHDR_OUTPUT_HDR_HLG || of == ULTRAHDR_OUTPUT_HDR_PQ) {
+ } else if (outFmt == UHDR_IMG_FMT_32bppRGBA1010102 && p010_file != nullptr) {
appInput.convertP010ToRGBImage();
appInput.computeRGBHdrPSNR();
appInput.convertRgba1010102ToYUV444Image();
appInput.computeYUVHdrPSNR();
+ } else {
+ std::cerr << "failed to compute psnr " << std::endl;
}
}
} else if (mode == 1) {
@@ -979,7 +1223,7 @@ int main(int argc, char* argv[]) {
usage(argv[0]);
return -1;
}
- UltraHdrAppInput appInput(jpegr_file, of);
+ UltraHdrAppInput appInput(jpegr_file, outTf, outFmt);
if (!appInput.decode()) return -1;
} else {
std::cerr << "unrecognized input mode " << mode << std::endl;