Loading libs/ultrahdr/gainmapmath.cpp +27 −17 Original line number Diff line number Diff line Loading @@ -598,14 +598,26 @@ Color applyGainLUT(Color e, float gain, GainLUT& gainLUT) { } Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { size_t pixel_count = image->width * image->height; uint8_t* luma_data = reinterpret_cast<uint8_t*>(image->data); size_t luma_stride = image->luma_stride == 0 ? image->width : image->luma_stride; uint8_t* chroma_data; size_t chroma_stride; if (image->chroma_data == nullptr) { chroma_stride = luma_stride / 2; chroma_data = &reinterpret_cast<uint8_t*>(image->data)[luma_stride * image->height]; } else { chroma_stride = image->chroma_stride; chroma_data = reinterpret_cast<uint8_t*>(image->chroma_data); } size_t pixel_y_idx = x + y * image->width; size_t pixel_uv_idx = x / 2 + (y / 2) * (image->width / 2); size_t offset_cr = chroma_stride * (image->height / 2); size_t pixel_y_idx = x + y * luma_stride; size_t pixel_chroma_idx = x / 2 + (y / 2) * chroma_stride; uint8_t y_uint = reinterpret_cast<uint8_t*>(image->data)[pixel_y_idx]; uint8_t u_uint = reinterpret_cast<uint8_t*>(image->data)[pixel_count + pixel_uv_idx]; uint8_t v_uint = reinterpret_cast<uint8_t*>(image->data)[pixel_count * 5 / 4 + pixel_uv_idx]; uint8_t y_uint = luma_data[pixel_y_idx]; uint8_t u_uint = chroma_data[pixel_chroma_idx]; uint8_t v_uint = chroma_data[offset_cr + pixel_chroma_idx]; // 128 bias for UV given we are using jpeglib; see: // https://github.com/kornelski/libjpeg/blob/master/structure.doc Loading @@ -615,19 +627,17 @@ Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { } Color getP010Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { size_t luma_stride = image->luma_stride; size_t chroma_stride = image->chroma_stride; uint16_t* luma_data = reinterpret_cast<uint16_t*>(image->data); uint16_t* chroma_data = reinterpret_cast<uint16_t*>(image->chroma_data); size_t luma_stride = image->luma_stride == 0 ? image->width : image->luma_stride; if (luma_stride == 0) { luma_stride = image->width; } if (chroma_stride == 0) { uint16_t* chroma_data; size_t chroma_stride; if (image->chroma_data == nullptr) { chroma_stride = luma_stride; } if (chroma_data == nullptr) { chroma_data = &reinterpret_cast<uint16_t*>(image->data)[luma_stride * image->height]; } else { chroma_stride = image->chroma_stride; chroma_data = reinterpret_cast<uint16_t*>(image->chroma_data); } size_t pixel_y_idx = y * luma_stride + x; Loading libs/ultrahdr/include/ultrahdr/jpegr.h +11 −8 Original line number Diff line number Diff line Loading @@ -49,16 +49,19 @@ struct jpegr_uncompressed_struct { // Values below are optional // Pointer to chroma data, if it's NULL, chroma plane is considered to be immediately // following after the luma plane. // Note: currently this feature is only supported for P010 image (HDR input). // after the luma plane. void* chroma_data = nullptr; // Strides of Y plane in number of pixels, using 0 to present uninitialized, must be // larger than or equal to luma width. // Note: currently this feature is only supported for P010 image (HDR input). // Stride of Y plane in number of pixels. 0 indicates the member is uninitialized. If // non-zero this value must be larger than or equal to luma width. If stride is // uninitialized then it is assumed to be equal to luma width. int luma_stride = 0; // Strides of UV plane in number of pixels, using 0 to present uninitialized, must be // larger than or equal to chroma width. // Note: currently this feature is only supported for P010 image (HDR input). // Stride of UV plane in number of pixels. // 1. If this handle points to P010 image then this value must be larger than // or equal to luma width. // 2. If this handle points to 420 image then this value must be larger than // or equal to (luma width / 2). // NOTE: if chroma_data is nullptr, chroma_stride is irrelevant. Just as the way, // chroma_data is derived from luma ptr, chroma stride is derived from luma stride. int chroma_stride = 0; }; Loading libs/ultrahdr/jpegr.cpp +65 −28 Original line number Diff line number Diff line Loading @@ -167,15 +167,18 @@ status_t JpegR::areInputArgumentsValid(jr_uncompressed_ptr uncompressed_p010_ima return ERROR_JPEGR_INVALID_NULL_PTR; } if (uncompressed_yuv_420_image->luma_stride != 0) { ALOGE("Stride is not supported for YUV420 image"); return ERROR_JPEGR_UNSUPPORTED_FEATURE; if (uncompressed_yuv_420_image->luma_stride != 0 && uncompressed_yuv_420_image->luma_stride < uncompressed_yuv_420_image->width) { ALOGE("Luma stride can not be smaller than width, stride=%d, width=%d", uncompressed_yuv_420_image->luma_stride, uncompressed_yuv_420_image->width); return ERROR_JPEGR_INVALID_INPUT_TYPE; } if (uncompressed_yuv_420_image->chroma_data != nullptr) { ALOGE("Pointer to chroma plane is not supported for YUV420 image, chroma data must" "be immediately after the luma data."); return ERROR_JPEGR_UNSUPPORTED_FEATURE; if (uncompressed_yuv_420_image->chroma_data != nullptr && uncompressed_yuv_420_image->chroma_stride < uncompressed_yuv_420_image->width / 2) { ALOGE("Chroma stride can not be smaller than 1/2 of the width, stride=%d, width=%d", uncompressed_yuv_420_image->chroma_stride, uncompressed_yuv_420_image->width); return ERROR_JPEGR_INVALID_INPUT_TYPE; } if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width Loading Loading @@ -323,11 +326,49 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, sp<DataStruct> icc = IccHelper::writeIccProfile(ULTRAHDR_TF_SRGB, uncompressed_yuv_420_image->colorGamut); // Convert to Bt601 YUV encoding for JPEG encode; make a copy so as to no clobber client data // Convert to Bt601 YUV encoding for JPEG encode and remove stride if needed; // make a copy so as to no clobber client data unique_ptr<uint8_t[]> yuv_420_bt601_data = make_unique<uint8_t[]>( uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height * 3 / 2); memcpy(yuv_420_bt601_data.get(), uncompressed_yuv_420_image->data, uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height * 3 / 2); // copy data { uint8_t* src_luma_data = reinterpret_cast<uint8_t*>(uncompressed_yuv_420_image->data); size_t src_luma_stride = uncompressed_yuv_420_image->luma_stride == 0 ? uncompressed_yuv_420_image->width : uncompressed_yuv_420_image->luma_stride; uint8_t* src_chroma_data = reinterpret_cast<uint8_t*>(uncompressed_yuv_420_image->chroma_data); size_t src_chroma_stride = uncompressed_yuv_420_image->chroma_stride; if (uncompressed_yuv_420_image->chroma_data == nullptr) { src_chroma_data = &reinterpret_cast<uint8_t*>(uncompressed_yuv_420_image->data)[src_luma_stride * uncompressed_yuv_420_image->height]; } if (src_chroma_stride == 0) { src_chroma_stride = src_luma_stride / 2; } // copy luma for (size_t i = 0; i < uncompressed_yuv_420_image->height; i++) { memcpy(yuv_420_bt601_data.get() + i * uncompressed_yuv_420_image->width, src_luma_data + i * src_luma_stride, uncompressed_yuv_420_image->width); } // copy cb for (size_t i = 0; i < uncompressed_yuv_420_image->height / 2; i++) { memcpy(yuv_420_bt601_data.get() + uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height + i * uncompressed_yuv_420_image->width / 2, src_chroma_data + i * src_chroma_stride, uncompressed_yuv_420_image->width / 2); } // copy cr for (size_t i = 0; i < uncompressed_yuv_420_image->height / 2; i++) { memcpy(yuv_420_bt601_data.get() + uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height * 5 / 4 + i * uncompressed_yuv_420_image->width / 2, src_chroma_data + src_chroma_stride * (uncompressed_yuv_420_image->height / 2) + i * src_chroma_stride, uncompressed_yuv_420_image->width / 2); } } jpegr_uncompressed_struct yuv_420_bt601_image = { yuv_420_bt601_data.get(), uncompressed_yuv_420_image->width, uncompressed_yuv_420_image->height, Loading Loading @@ -792,16 +833,15 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, size_t image_width = uncompressed_yuv_420_image->width; size_t image_height = uncompressed_yuv_420_image->height; size_t map_width = image_width / kMapDimensionScaleFactor; size_t map_height = image_height / kMapDimensionScaleFactor; size_t map_stride = static_cast<size_t>( floor((map_width + kJpegBlock - 1) / kJpegBlock)) * kJpegBlock; size_t map_height_aligned = ((map_height + 1) >> 1) << 1; dest->width = map_stride; dest->height = map_height_aligned; size_t map_width = static_cast<size_t>( floor((image_width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); size_t map_height = static_cast<size_t>( floor((image_height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); dest->width = map_width; dest->height = map_height; dest->colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED; dest->data = new uint8_t[map_stride * map_height_aligned]; dest->data = new uint8_t[map_width * map_height]; std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(dest->data)); Loading Loading @@ -895,11 +935,9 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, luminanceFn, sdrYuvToRgbFn, hdrYuvToRgbFn, hdr_white_nits, log2MinBoost, log2MaxBoost, &jobQueue]() -> void { size_t rowStart, rowEnd; size_t dest_map_width = uncompressed_yuv_420_image->width / kMapDimensionScaleFactor; size_t dest_map_stride = dest->width; while (jobQueue.dequeueJob(rowStart, rowEnd)) { for (size_t y = rowStart; y < rowEnd; ++y) { for (size_t x = 0; x < dest_map_width; ++x) { for (size_t x = 0; x < dest->width; ++x) { Color sdr_yuv_gamma = sampleYuv420(uncompressed_yuv_420_image, kMapDimensionScaleFactor, x, y); Color sdr_rgb_gamma = sdrYuvToRgbFn(sdr_yuv_gamma); Loading @@ -917,7 +955,7 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, hdr_rgb = hdrGamutConversionFn(hdr_rgb); float hdr_y_nits = luminanceFn(hdr_rgb) * hdr_white_nits; size_t pixel_idx = x + y * dest_map_stride; size_t pixel_idx = x + y * dest->width; reinterpret_cast<uint8_t*>(dest->data)[pixel_idx] = encodeGain(sdr_y_nits, hdr_y_nits, metadata, log2MinBoost, log2MaxBoost); } Loading Loading @@ -981,11 +1019,10 @@ status_t JpegR::applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, // TODO: remove once map scaling factor is computed based on actual map dims size_t image_width = uncompressed_yuv_420_image->width; size_t image_height = uncompressed_yuv_420_image->height; size_t map_width = image_width / kMapDimensionScaleFactor; size_t map_height = image_height / kMapDimensionScaleFactor; map_width = static_cast<size_t>( floor((map_width + kJpegBlock - 1) / kJpegBlock)) * kJpegBlock; map_height = ((map_height + 1) >> 1) << 1; size_t map_width = static_cast<size_t>( floor((image_width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); size_t map_height = static_cast<size_t>( floor((image_height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); if (map_width != uncompressed_gain_map->width || map_height != uncompressed_gain_map->height) { ALOGE("gain map dimensions and primary image dimensions are not to scale"); Loading libs/ultrahdr/tests/jpegr_test.cpp +195 −11 Original line number Diff line number Diff line Loading @@ -728,23 +728,23 @@ TEST(JpegRTest, EncodeAPI1WithInvalidArgs) { rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = kWidth; rawImg420->luma_stride = kWidth - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle(), kQuality, nullptr), OK) << "fail, API allows luma stride for 420"; << "fail, API allows bad luma stride for 420"; rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = 0; rawImg420->chroma_data = rawImgP010->data; rawImg420->chroma_stride = kWidth; rawImg420->chroma_stride = kWidth / 2 - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle(), kQuality, nullptr), OK) << "fail, API allows bad chroma pointer for 420"; << "fail, API allows bad chroma stride for 420"; } } Loading Loading @@ -1021,23 +1021,23 @@ TEST(JpegRTest, EncodeAPI2WithInvalidArgs) { rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = kWidth; rawImg420->luma_stride = kWidth - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()), OK) << "fail, API allows luma stride for 420"; << "fail, API allows bad luma stride for 420"; rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = 0; rawImg420->chroma_data = rawImgP010->data; rawImg420->chroma_stride = kWidth; rawImg420->chroma_stride = kWidth / 2 - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()), OK) << "fail, API allows bad chroma pointer for 420"; << "fail, API allows bad chroma stride for 420"; } } Loading Loading @@ -1445,6 +1445,24 @@ TEST(JpegRTest, EncodeAPI0AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set but no chroma ptr { UhdrUnCompressedStructWrapper rawImg2(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); ASSERT_TRUE(rawImg2.setImageStride(kImageWidth, kImageWidth + 256)); ASSERT_TRUE(rawImg2.allocateMemory()); ASSERT_TRUE(rawImg2.loadRawResource(kYCbCrP010FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); #ifdef DUMP_OUTPUT Loading Loading @@ -1473,7 +1491,7 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle(), kQuality, nullptr), OK); // encode with luma stride set // encode with luma stride set p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); Loading @@ -1491,7 +1509,7 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set // encode with luma and chroma stride set p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); Loading @@ -1510,7 +1528,7 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with chroma stride set // encode with chroma stride set p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); Loading @@ -1529,6 +1547,98 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set but no chroma ptr p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 64, kImageWidth + 256)); ASSERT_TRUE(rawImg2P010.allocateMemory()); ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma stride set 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, 0)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth / 2 + 256)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with chroma stride set 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(0, kImageWidth / 2 + 64)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set but no chroma ptr 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth / 2 + 64)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); Loading Loading @@ -1618,6 +1728,62 @@ TEST(JpegRTest, EncodeAPI2AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma stride set { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, 0)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth + 256)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with chroma stride set { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(0, kImageWidth + 64)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); Loading Loading @@ -1703,6 +1869,24 @@ TEST(JpegRTest, EncodeAPI3AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set and no chroma ptr { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 32, kImageWidth + 256)); ASSERT_TRUE(rawImg2P010.allocateMemory()); ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); Loading Loading
libs/ultrahdr/gainmapmath.cpp +27 −17 Original line number Diff line number Diff line Loading @@ -598,14 +598,26 @@ Color applyGainLUT(Color e, float gain, GainLUT& gainLUT) { } Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { size_t pixel_count = image->width * image->height; uint8_t* luma_data = reinterpret_cast<uint8_t*>(image->data); size_t luma_stride = image->luma_stride == 0 ? image->width : image->luma_stride; uint8_t* chroma_data; size_t chroma_stride; if (image->chroma_data == nullptr) { chroma_stride = luma_stride / 2; chroma_data = &reinterpret_cast<uint8_t*>(image->data)[luma_stride * image->height]; } else { chroma_stride = image->chroma_stride; chroma_data = reinterpret_cast<uint8_t*>(image->chroma_data); } size_t pixel_y_idx = x + y * image->width; size_t pixel_uv_idx = x / 2 + (y / 2) * (image->width / 2); size_t offset_cr = chroma_stride * (image->height / 2); size_t pixel_y_idx = x + y * luma_stride; size_t pixel_chroma_idx = x / 2 + (y / 2) * chroma_stride; uint8_t y_uint = reinterpret_cast<uint8_t*>(image->data)[pixel_y_idx]; uint8_t u_uint = reinterpret_cast<uint8_t*>(image->data)[pixel_count + pixel_uv_idx]; uint8_t v_uint = reinterpret_cast<uint8_t*>(image->data)[pixel_count * 5 / 4 + pixel_uv_idx]; uint8_t y_uint = luma_data[pixel_y_idx]; uint8_t u_uint = chroma_data[pixel_chroma_idx]; uint8_t v_uint = chroma_data[offset_cr + pixel_chroma_idx]; // 128 bias for UV given we are using jpeglib; see: // https://github.com/kornelski/libjpeg/blob/master/structure.doc Loading @@ -615,19 +627,17 @@ Color getYuv420Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { } Color getP010Pixel(jr_uncompressed_ptr image, size_t x, size_t y) { size_t luma_stride = image->luma_stride; size_t chroma_stride = image->chroma_stride; uint16_t* luma_data = reinterpret_cast<uint16_t*>(image->data); uint16_t* chroma_data = reinterpret_cast<uint16_t*>(image->chroma_data); size_t luma_stride = image->luma_stride == 0 ? image->width : image->luma_stride; if (luma_stride == 0) { luma_stride = image->width; } if (chroma_stride == 0) { uint16_t* chroma_data; size_t chroma_stride; if (image->chroma_data == nullptr) { chroma_stride = luma_stride; } if (chroma_data == nullptr) { chroma_data = &reinterpret_cast<uint16_t*>(image->data)[luma_stride * image->height]; } else { chroma_stride = image->chroma_stride; chroma_data = reinterpret_cast<uint16_t*>(image->chroma_data); } size_t pixel_y_idx = y * luma_stride + x; Loading
libs/ultrahdr/include/ultrahdr/jpegr.h +11 −8 Original line number Diff line number Diff line Loading @@ -49,16 +49,19 @@ struct jpegr_uncompressed_struct { // Values below are optional // Pointer to chroma data, if it's NULL, chroma plane is considered to be immediately // following after the luma plane. // Note: currently this feature is only supported for P010 image (HDR input). // after the luma plane. void* chroma_data = nullptr; // Strides of Y plane in number of pixels, using 0 to present uninitialized, must be // larger than or equal to luma width. // Note: currently this feature is only supported for P010 image (HDR input). // Stride of Y plane in number of pixels. 0 indicates the member is uninitialized. If // non-zero this value must be larger than or equal to luma width. If stride is // uninitialized then it is assumed to be equal to luma width. int luma_stride = 0; // Strides of UV plane in number of pixels, using 0 to present uninitialized, must be // larger than or equal to chroma width. // Note: currently this feature is only supported for P010 image (HDR input). // Stride of UV plane in number of pixels. // 1. If this handle points to P010 image then this value must be larger than // or equal to luma width. // 2. If this handle points to 420 image then this value must be larger than // or equal to (luma width / 2). // NOTE: if chroma_data is nullptr, chroma_stride is irrelevant. Just as the way, // chroma_data is derived from luma ptr, chroma stride is derived from luma stride. int chroma_stride = 0; }; Loading
libs/ultrahdr/jpegr.cpp +65 −28 Original line number Diff line number Diff line Loading @@ -167,15 +167,18 @@ status_t JpegR::areInputArgumentsValid(jr_uncompressed_ptr uncompressed_p010_ima return ERROR_JPEGR_INVALID_NULL_PTR; } if (uncompressed_yuv_420_image->luma_stride != 0) { ALOGE("Stride is not supported for YUV420 image"); return ERROR_JPEGR_UNSUPPORTED_FEATURE; if (uncompressed_yuv_420_image->luma_stride != 0 && uncompressed_yuv_420_image->luma_stride < uncompressed_yuv_420_image->width) { ALOGE("Luma stride can not be smaller than width, stride=%d, width=%d", uncompressed_yuv_420_image->luma_stride, uncompressed_yuv_420_image->width); return ERROR_JPEGR_INVALID_INPUT_TYPE; } if (uncompressed_yuv_420_image->chroma_data != nullptr) { ALOGE("Pointer to chroma plane is not supported for YUV420 image, chroma data must" "be immediately after the luma data."); return ERROR_JPEGR_UNSUPPORTED_FEATURE; if (uncompressed_yuv_420_image->chroma_data != nullptr && uncompressed_yuv_420_image->chroma_stride < uncompressed_yuv_420_image->width / 2) { ALOGE("Chroma stride can not be smaller than 1/2 of the width, stride=%d, width=%d", uncompressed_yuv_420_image->chroma_stride, uncompressed_yuv_420_image->width); return ERROR_JPEGR_INVALID_INPUT_TYPE; } if (uncompressed_p010_image->width != uncompressed_yuv_420_image->width Loading Loading @@ -323,11 +326,49 @@ status_t JpegR::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, sp<DataStruct> icc = IccHelper::writeIccProfile(ULTRAHDR_TF_SRGB, uncompressed_yuv_420_image->colorGamut); // Convert to Bt601 YUV encoding for JPEG encode; make a copy so as to no clobber client data // Convert to Bt601 YUV encoding for JPEG encode and remove stride if needed; // make a copy so as to no clobber client data unique_ptr<uint8_t[]> yuv_420_bt601_data = make_unique<uint8_t[]>( uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height * 3 / 2); memcpy(yuv_420_bt601_data.get(), uncompressed_yuv_420_image->data, uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height * 3 / 2); // copy data { uint8_t* src_luma_data = reinterpret_cast<uint8_t*>(uncompressed_yuv_420_image->data); size_t src_luma_stride = uncompressed_yuv_420_image->luma_stride == 0 ? uncompressed_yuv_420_image->width : uncompressed_yuv_420_image->luma_stride; uint8_t* src_chroma_data = reinterpret_cast<uint8_t*>(uncompressed_yuv_420_image->chroma_data); size_t src_chroma_stride = uncompressed_yuv_420_image->chroma_stride; if (uncompressed_yuv_420_image->chroma_data == nullptr) { src_chroma_data = &reinterpret_cast<uint8_t*>(uncompressed_yuv_420_image->data)[src_luma_stride * uncompressed_yuv_420_image->height]; } if (src_chroma_stride == 0) { src_chroma_stride = src_luma_stride / 2; } // copy luma for (size_t i = 0; i < uncompressed_yuv_420_image->height; i++) { memcpy(yuv_420_bt601_data.get() + i * uncompressed_yuv_420_image->width, src_luma_data + i * src_luma_stride, uncompressed_yuv_420_image->width); } // copy cb for (size_t i = 0; i < uncompressed_yuv_420_image->height / 2; i++) { memcpy(yuv_420_bt601_data.get() + uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height + i * uncompressed_yuv_420_image->width / 2, src_chroma_data + i * src_chroma_stride, uncompressed_yuv_420_image->width / 2); } // copy cr for (size_t i = 0; i < uncompressed_yuv_420_image->height / 2; i++) { memcpy(yuv_420_bt601_data.get() + uncompressed_yuv_420_image->width * uncompressed_yuv_420_image->height * 5 / 4 + i * uncompressed_yuv_420_image->width / 2, src_chroma_data + src_chroma_stride * (uncompressed_yuv_420_image->height / 2) + i * src_chroma_stride, uncompressed_yuv_420_image->width / 2); } } jpegr_uncompressed_struct yuv_420_bt601_image = { yuv_420_bt601_data.get(), uncompressed_yuv_420_image->width, uncompressed_yuv_420_image->height, Loading Loading @@ -792,16 +833,15 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, size_t image_width = uncompressed_yuv_420_image->width; size_t image_height = uncompressed_yuv_420_image->height; size_t map_width = image_width / kMapDimensionScaleFactor; size_t map_height = image_height / kMapDimensionScaleFactor; size_t map_stride = static_cast<size_t>( floor((map_width + kJpegBlock - 1) / kJpegBlock)) * kJpegBlock; size_t map_height_aligned = ((map_height + 1) >> 1) << 1; dest->width = map_stride; dest->height = map_height_aligned; size_t map_width = static_cast<size_t>( floor((image_width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); size_t map_height = static_cast<size_t>( floor((image_height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); dest->width = map_width; dest->height = map_height; dest->colorGamut = ULTRAHDR_COLORGAMUT_UNSPECIFIED; dest->data = new uint8_t[map_stride * map_height_aligned]; dest->data = new uint8_t[map_width * map_height]; std::unique_ptr<uint8_t[]> map_data; map_data.reset(reinterpret_cast<uint8_t*>(dest->data)); Loading Loading @@ -895,11 +935,9 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, luminanceFn, sdrYuvToRgbFn, hdrYuvToRgbFn, hdr_white_nits, log2MinBoost, log2MaxBoost, &jobQueue]() -> void { size_t rowStart, rowEnd; size_t dest_map_width = uncompressed_yuv_420_image->width / kMapDimensionScaleFactor; size_t dest_map_stride = dest->width; while (jobQueue.dequeueJob(rowStart, rowEnd)) { for (size_t y = rowStart; y < rowEnd; ++y) { for (size_t x = 0; x < dest_map_width; ++x) { for (size_t x = 0; x < dest->width; ++x) { Color sdr_yuv_gamma = sampleYuv420(uncompressed_yuv_420_image, kMapDimensionScaleFactor, x, y); Color sdr_rgb_gamma = sdrYuvToRgbFn(sdr_yuv_gamma); Loading @@ -917,7 +955,7 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, hdr_rgb = hdrGamutConversionFn(hdr_rgb); float hdr_y_nits = luminanceFn(hdr_rgb) * hdr_white_nits; size_t pixel_idx = x + y * dest_map_stride; size_t pixel_idx = x + y * dest->width; reinterpret_cast<uint8_t*>(dest->data)[pixel_idx] = encodeGain(sdr_y_nits, hdr_y_nits, metadata, log2MinBoost, log2MaxBoost); } Loading Loading @@ -981,11 +1019,10 @@ status_t JpegR::applyGainMap(jr_uncompressed_ptr uncompressed_yuv_420_image, // TODO: remove once map scaling factor is computed based on actual map dims size_t image_width = uncompressed_yuv_420_image->width; size_t image_height = uncompressed_yuv_420_image->height; size_t map_width = image_width / kMapDimensionScaleFactor; size_t map_height = image_height / kMapDimensionScaleFactor; map_width = static_cast<size_t>( floor((map_width + kJpegBlock - 1) / kJpegBlock)) * kJpegBlock; map_height = ((map_height + 1) >> 1) << 1; size_t map_width = static_cast<size_t>( floor((image_width + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); size_t map_height = static_cast<size_t>( floor((image_height + kMapDimensionScaleFactor - 1) / kMapDimensionScaleFactor)); if (map_width != uncompressed_gain_map->width || map_height != uncompressed_gain_map->height) { ALOGE("gain map dimensions and primary image dimensions are not to scale"); Loading
libs/ultrahdr/tests/jpegr_test.cpp +195 −11 Original line number Diff line number Diff line Loading @@ -728,23 +728,23 @@ TEST(JpegRTest, EncodeAPI1WithInvalidArgs) { rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = kWidth; rawImg420->luma_stride = kWidth - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle(), kQuality, nullptr), OK) << "fail, API allows luma stride for 420"; << "fail, API allows bad luma stride for 420"; rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = 0; rawImg420->chroma_data = rawImgP010->data; rawImg420->chroma_stride = kWidth; rawImg420->chroma_stride = kWidth / 2 - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle(), kQuality, nullptr), OK) << "fail, API allows bad chroma pointer for 420"; << "fail, API allows bad chroma stride for 420"; } } Loading Loading @@ -1021,23 +1021,23 @@ TEST(JpegRTest, EncodeAPI2WithInvalidArgs) { rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = kWidth; rawImg420->luma_stride = kWidth - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()), OK) << "fail, API allows luma stride for 420"; << "fail, API allows bad luma stride for 420"; rawImg420->width = kWidth; rawImg420->height = kHeight; rawImg420->luma_stride = 0; rawImg420->chroma_data = rawImgP010->data; rawImg420->chroma_stride = kWidth; rawImg420->chroma_stride = kWidth / 2 - 2; ASSERT_NE(uHdrLib.encodeJPEGR(rawImgP010, rawImg420, jpgImg.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle()), OK) << "fail, API allows bad chroma pointer for 420"; << "fail, API allows bad chroma stride for 420"; } } Loading Loading @@ -1445,6 +1445,24 @@ TEST(JpegRTest, EncodeAPI0AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set but no chroma ptr { UhdrUnCompressedStructWrapper rawImg2(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); ASSERT_TRUE(rawImg2.setImageStride(kImageWidth, kImageWidth + 256)); ASSERT_TRUE(rawImg2.allocateMemory()); ASSERT_TRUE(rawImg2.loadRawResource(kYCbCrP010FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); #ifdef DUMP_OUTPUT Loading Loading @@ -1473,7 +1491,7 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg.getImageHandle(), kQuality, nullptr), OK); // encode with luma stride set // encode with luma stride set p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); Loading @@ -1491,7 +1509,7 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set // encode with luma and chroma stride set p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); Loading @@ -1510,7 +1528,7 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with chroma stride set // encode with chroma stride set p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); Loading @@ -1529,6 +1547,98 @@ TEST(JpegRTest, EncodeAPI1AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set but no chroma ptr p010 { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 64, kImageWidth + 256)); ASSERT_TRUE(rawImg2P010.allocateMemory()); ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), rawImg420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma stride set 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, 0)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth / 2 + 256)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with chroma stride set 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(0, kImageWidth / 2 + 64)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set but no chroma ptr 420 { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth / 2 + 64)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle(), kQuality, nullptr), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); Loading Loading @@ -1618,6 +1728,62 @@ TEST(JpegRTest, EncodeAPI2AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma stride set { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, 0)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(kImageWidth + 128, kImageWidth + 256)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with chroma stride set { UhdrUnCompressedStructWrapper rawImg2420(kImageWidth, kImageHeight, YCbCr_420); ASSERT_TRUE(rawImg2420.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT709)); ASSERT_TRUE(rawImg2420.setImageStride(0, kImageWidth + 64)); ASSERT_TRUE(rawImg2420.setChromaMode(false)); ASSERT_TRUE(rawImg2420.allocateMemory()); ASSERT_TRUE(rawImg2420.loadRawResource(kYCbCr420FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImgP010.getImageHandle(), rawImg2420.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); Loading Loading @@ -1703,6 +1869,24 @@ TEST(JpegRTest, EncodeAPI3AndDecodeTest) { ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } // encode with luma and chroma stride set and no chroma ptr { UhdrUnCompressedStructWrapper rawImg2P010(kImageWidth, kImageHeight, YCbCr_p010); ASSERT_TRUE(rawImg2P010.setImageColorGamut(ultrahdr_color_gamut::ULTRAHDR_COLORGAMUT_BT2100)); ASSERT_TRUE(rawImg2P010.setImageStride(kImageWidth + 32, kImageWidth + 256)); ASSERT_TRUE(rawImg2P010.allocateMemory()); ASSERT_TRUE(rawImg2P010.loadRawResource(kYCbCrP010FileName)); UhdrCompressedStructWrapper jpgImg2(kImageWidth, kImageHeight); ASSERT_TRUE(jpgImg2.allocateMemory()); ASSERT_EQ(uHdrLib.encodeJPEGR(rawImg2P010.getImageHandle(), sdr, ultrahdr_transfer_function::ULTRAHDR_TF_HLG, jpgImg2.getImageHandle()), OK); auto jpg1 = jpgImg.getImageHandle(); auto jpg2 = jpgImg2.getImageHandle(); ASSERT_EQ(jpg1->length, jpg2->length); ASSERT_EQ(0, memcmp(jpg1->data, jpg2->data, jpg1->length)); } auto jpg1 = jpgImg.getImageHandle(); Loading