diff options
author | Aayush Soni <aayush.soni@ittiam.com> | 2023-12-16 04:08:25 +0530 |
---|---|---|
committer | Aayush Soni <aayush.soni@ittiam.com> | 2023-12-21 12:04:57 +0530 |
commit | 5379ccc557e408fe92800ab616182a77b444a186 (patch) | |
tree | d70d834ce84f066a37e1fc406b13423cd81fc42e | |
parent | fd468466f4ff2d44ebc28b51e521929305aea096 (diff) | |
download | libultrahdr-5379ccc557e408fe92800ab616182a77b444a186.tar.gz |
Remove duplicate code from getCompressedImageParameters
Improve getJPEGRInfo statistics
Also, getCompressedImageParameters() does not return xmp info as
pointed by the documentation. This is fixed
-rw-r--r-- | benchmark/benchmark_test.cpp | 4 | ||||
-rw-r--r-- | examples/ultrahdr_app.cpp | 2 | ||||
-rw-r--r-- | fuzzer/ultrahdr_dec_fuzzer.cpp | 4 | ||||
-rw-r--r-- | fuzzer/ultrahdr_enc_fuzzer.cpp | 4 | ||||
-rw-r--r-- | lib/include/ultrahdr/jpegdecoderhelper.h | 14 | ||||
-rw-r--r-- | lib/include/ultrahdr/jpegr.h | 35 | ||||
-rw-r--r-- | lib/src/jpegdecoderhelper.cpp | 81 | ||||
-rw-r--r-- | lib/src/jpegr.cpp | 75 | ||||
-rw-r--r-- | tests/jpegdecoderhelper_test.cpp | 34 | ||||
-rw-r--r-- | tests/jpegr_test.cpp | 4 |
10 files changed, 128 insertions, 129 deletions
diff --git a/benchmark/benchmark_test.cpp b/benchmark/benchmark_test.cpp index 13b136b..ed47356 100644 --- a/benchmark/benchmark_test.cpp +++ b/benchmark/benchmark_test.cpp @@ -205,9 +205,7 @@ static void BM_Decode(benchmark::State& s) { compData.reset(reinterpret_cast<uint8_t*>(jpegImgR.data)); JpegR jpegHdr; - std::vector<uint8_t> iccData(0); - std::vector<uint8_t> exifData(0); - jpegr_info_struct info{0, 0, &iccData, &exifData}; + jpegr_info_struct info{}; status_t status = jpegHdr.getJPEGRInfo(&jpegImgR, &info); if (JPEGR_NO_ERROR != status) { s.SkipWithError("getJPEGRInfo returned with error " + std::to_string(status)); diff --git a/examples/ultrahdr_app.cpp b/examples/ultrahdr_app.cpp index 4aa0814..20b9329 100644 --- a/examples/ultrahdr_app.cpp +++ b/examples/ultrahdr_app.cpp @@ -367,7 +367,7 @@ 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{0, 0, &iccData, &exifData}; + jpegr_info_struct info{}; JpegR jpegHdr; status_t status = jpegHdr.getJPEGRInfo(&mJpegImgR, &info); if (JPEGR_NO_ERROR == status) { diff --git a/fuzzer/ultrahdr_dec_fuzzer.cpp b/fuzzer/ultrahdr_dec_fuzzer.cpp index 49dc913..4adc942 100644 --- a/fuzzer/ultrahdr_dec_fuzzer.cpp +++ b/fuzzer/ultrahdr_dec_fuzzer.cpp @@ -42,9 +42,7 @@ void UltraHdrDecFuzzer::process() { jpegr_compressed_struct jpegImgR{buffer.data(), (int)buffer.size(), (int)buffer.size(), ULTRAHDR_COLORGAMUT_UNSPECIFIED}; - std::vector<uint8_t> iccData(0); - std::vector<uint8_t> exifData(0); - jpegr_info_struct info{0, 0, &iccData, &exifData}; + jpegr_info_struct info{}; JpegR jpegHdr; (void)jpegHdr.getJPEGRInfo(&jpegImgR, &info); //#define DUMP_PARAM diff --git a/fuzzer/ultrahdr_enc_fuzzer.cpp b/fuzzer/ultrahdr_enc_fuzzer.cpp index 23cc845..ff749c7 100644 --- a/fuzzer/ultrahdr_enc_fuzzer.cpp +++ b/fuzzer/ultrahdr_enc_fuzzer.cpp @@ -289,9 +289,7 @@ void UltraHdrEncFuzzer::process() { } } if (status == JPEGR_NO_ERROR) { - std::vector<uint8_t> iccData(0); - std::vector<uint8_t> exifData(0); - jpegr_info_struct info{0, 0, &iccData, &exifData}; + jpegr_info_struct info{}; status = jpegHdr.getJPEGRInfo(&jpegImgR, &info); if (status == JPEGR_NO_ERROR) { size_t outSize = info.width * info.height * ((of == ULTRAHDR_OUTPUT_HDR_LINEAR) ? 8 : 4); diff --git a/lib/include/ultrahdr/jpegdecoderhelper.h b/lib/include/ultrahdr/jpegdecoderhelper.h index 01a05e4..d0b1f6f 100644 --- a/lib/include/ultrahdr/jpegdecoderhelper.h +++ b/lib/include/ultrahdr/jpegdecoderhelper.h @@ -41,6 +41,13 @@ static const int kMaxWidth = 8192; static const int kMaxHeight = 8192; namespace ultrahdr { + +typedef enum { + PARSE_ONLY = 0, // Dont decode. Parse for dimensions, EXIF, ICC, XMP + DECODE_TO_RGBA = 1, // Parse and decode to rgba + DECODE_TO_YCBCR = 2, // Parse and decode to YCBCR or Grayscale +} decode_mode_t; + /* * Encapsulates a converter from JPEG to raw image (YUV420planer or grey-scale) format. * This class is not thread-safe. @@ -54,7 +61,7 @@ class JpegDecoderHelper { * calling this method, call getDecompressedImage() to get the image. * Returns false if decompressing the image fails. */ - bool decompressImage(const void* image, int length, bool decodeToRGBA = false); + bool decompressImage(const void* image, int length, decode_mode_t decodeTo = DECODE_TO_YCBCR); /* * Returns the decompressed raw image buffer pointer. This method must be called only after * calling decompressImage(). @@ -117,11 +124,10 @@ class JpegDecoderHelper { /* * Decompresses metadata of the image. All vectors are owned by the caller. */ - bool getCompressedImageParameters(const void* image, int length, size_t* pWidth, size_t* pHeight, - std::vector<uint8_t>* iccData, std::vector<uint8_t>* exifData); + bool getCompressedImageParameters(const void* image, int length); private: - bool decode(const void* image, int length, bool decodeToRGBA); + bool decode(const void* image, int length, decode_mode_t decodeTo); // Returns false if errors occur. bool decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel); bool decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest); diff --git a/lib/include/ultrahdr/jpegr.h b/lib/include/ultrahdr/jpegr.h index 56be834..49ddaea 100644 --- a/lib/include/ultrahdr/jpegr.h +++ b/lib/include/ultrahdr/jpegr.h @@ -67,13 +67,25 @@ typedef enum { } status_t; /* - * Holds information of jpegr image + * Holds information of jpeg image */ -struct jpegr_info_struct { +struct jpeg_info_struct { + std::vector<uint8_t> imgData = std::vector<uint8_t>(0); + std::vector<uint8_t> iccData = std::vector<uint8_t>(0); + std::vector<uint8_t> exifData = std::vector<uint8_t>(0); + std::vector<uint8_t> xmpData = std::vector<uint8_t>(0); size_t width; size_t height; - std::vector<uint8_t>* iccData; - std::vector<uint8_t>* exifData; +}; + +/* + * Holds information of jpegr image + */ +struct jpegr_info_struct { + size_t width; // copy of primary image width (for easier access) + size_t height; // copy of primary image height (for easier access) + jpeg_info_struct* primaryImgInfo = nullptr; + jpeg_info_struct* gainmapImgInfo = nullptr; }; /* @@ -134,6 +146,7 @@ struct jpegr_exif_struct { typedef struct jpegr_uncompressed_struct* jr_uncompressed_ptr; typedef struct jpegr_compressed_struct* jr_compressed_ptr; typedef struct jpegr_exif_struct* jr_exif_ptr; +typedef struct jpeg_info_struct* j_info_ptr; typedef struct jpegr_info_struct* jr_info_ptr; class JpegR { @@ -375,6 +388,20 @@ class JpegR { jr_compressed_ptr gainmap_jpg_image_ptr); /* + * Gets Info from JPEG image without decoding it. + * + * The output is filled jpeg_info structure + * @param jpegr_image_ptr compressed JPEG image + * @param jpeg_image_info_ptr pointer to jpeg info struct. Members of jpeg_info_struct + * are owned by the caller + * @param img_width (optional) pointer to store width of jpeg image + * @param img_height (optional) pointer to store height of jpeg image + * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise + */ + status_t parseJpegInfo(jr_compressed_ptr jpeg_image_ptr, j_info_ptr jpeg_image_info_ptr, + size_t* img_width = nullptr, size_t* img_height = nullptr); + + /* * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image, * the compressed gain map and optionally the exif package as inputs, and generate the XMP * metadata, and finally append everything in the order of: diff --git a/lib/src/jpegdecoderhelper.cpp b/lib/src/jpegdecoderhelper.cpp index 8a8278d..70efb87 100644 --- a/lib/src/jpegdecoderhelper.cpp +++ b/lib/src/jpegdecoderhelper.cpp @@ -108,14 +108,14 @@ JpegDecoderHelper::JpegDecoderHelper() {} JpegDecoderHelper::~JpegDecoderHelper() {} -bool JpegDecoderHelper::decompressImage(const void* image, int length, bool decodeToRGBA) { +bool JpegDecoderHelper::decompressImage(const void* image, int length, decode_mode_t decodeTo) { if (image == nullptr || length <= 0) { ALOGE("Image size can not be handled: %d", length); return false; } mResultBuffer.clear(); mXMPBuffer.clear(); - return decode(image, length, decodeToRGBA); + return decode(image, length, decodeTo); } void* JpegDecoderHelper::getDecompressedImagePtr() { return mResultBuffer.data(); } @@ -187,7 +187,7 @@ bool JpegDecoderHelper::extractEXIF(const void* image, int length) { return true; } -bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) { +bool JpegDecoderHelper::decode(const void* image, int length, decode_mode_t decodeTo) { bool status = true; jpeg_decompress_struct cinfo; jpegrerror_mgr myerr; @@ -256,7 +256,7 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) goto CleanUp; } - if (decodeToRGBA) { + if (decodeTo == DECODE_TO_RGBA) { // The primary image is expected to be yuv420 sampling if (cinfo.jpeg_color_space != JCS_YCbCr) { status = false; @@ -273,7 +273,7 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) // 4 bytes per pixel mResultBuffer.resize(cinfo.image_width * cinfo.image_height * 4); cinfo.out_color_space = JCS_EXT_RGBA; - } else { + } else if (decodeTo == DECODE_TO_YCBCR) { if (cinfo.jpeg_color_space == JCS_YCbCr) { if (cinfo.comp_info[0].h_samp_factor != 2 || cinfo.comp_info[0].v_samp_factor != 2 || cinfo.comp_info[1].h_samp_factor != 1 || cinfo.comp_info[1].v_samp_factor != 1 || @@ -292,6 +292,10 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) } cinfo.out_color_space = cinfo.jpeg_color_space; cinfo.raw_data_out = TRUE; + } else { + status = decodeTo == PARSE_ONLY; + jpeg_destroy_decompress(&cinfo); + return status; } cinfo.dct_method = JDCT_ISLOW; @@ -316,71 +320,8 @@ bool JpegDecoderHelper::decompress(jpeg_decompress_struct* cinfo, const uint8_t* : decompressYUV(cinfo, dest)); } -bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int length, size_t* pWidth, - size_t* pHeight, std::vector<uint8_t>* iccData, - std::vector<uint8_t>* exifData) { - jpeg_decompress_struct cinfo; - jpegrerror_mgr myerr; - cinfo.err = jpeg_std_error(&myerr.pub); - myerr.pub.error_exit = jpegrerror_exit; - myerr.pub.output_message = output_message; - - if (setjmp(myerr.setjmp_buffer)) { - jpeg_destroy_decompress(&cinfo); - return false; - } - jpeg_create_decompress(&cinfo); - - jpeg_save_markers(&cinfo, kAPP1Marker, 0xFFFF); - jpeg_save_markers(&cinfo, kAPP2Marker, 0xFFFF); - - jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); - cinfo.src = &mgr; - if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { - jpeg_destroy_decompress(&cinfo); - return false; - } - - if (pWidth != nullptr) { - *pWidth = cinfo.image_width; - } - if (pHeight != nullptr) { - *pHeight = cinfo.image_height; - } - - if (iccData != nullptr) { - for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { - if (marker->marker != kAPP2Marker) { - continue; - } - if (marker->data_length <= kICCMarkerHeaderSize || - memcmp(marker->data, kICCSig, sizeof(kICCSig)) != 0) { - continue; - } - - iccData->insert(iccData->end(), marker->data, marker->data + marker->data_length); - } - } - - if (exifData != nullptr) { - bool exifAppears = false; - for (jpeg_marker_struct* marker = cinfo.marker_list; marker && !exifAppears; - marker = marker->next) { - if (marker->marker != kAPP1Marker) { - continue; - } - - const unsigned int len = marker->data_length; - if (len >= sizeof(kExifIdCode) && !memcmp(marker->data, kExifIdCode, sizeof(kExifIdCode))) { - exifData->resize(len, 0); - memcpy(static_cast<void*>(exifData->data()), marker->data, len); - exifAppears = true; - } - } - } - - jpeg_destroy_decompress(&cinfo); - return true; +bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int length) { + return decode(image, length, PARSE_ONLY); } bool JpegDecoderHelper::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) { diff --git a/lib/src/jpegr.cpp b/lib/src/jpegr.cpp index 55ec1a2..74ef134 100644 --- a/lib/src/jpegr.cpp +++ b/lib/src/jpegr.cpp @@ -558,13 +558,13 @@ status_t JpegR::encodeJPEGR(jr_compressed_ptr yuv420jpg_image_ptr, // We just want to check if ICC is present, so don't do a full decode. Note, // this doesn't verify that the ICC is valid. JpegDecoderHelper decoder; - std::vector<uint8_t> icc; - decoder.getCompressedImageParameters(yuv420jpg_image_ptr->data, yuv420jpg_image_ptr->length, - /* pWidth */ nullptr, /* pHeight */ nullptr, &icc, - /* exifData */ nullptr); + if (!decoder.getCompressedImageParameters(yuv420jpg_image_ptr->data, + yuv420jpg_image_ptr->length)) { + return ERROR_JPEGR_DECODE_ERROR; + } // Add ICC if not already present. - if (icc.size() > 0) { + if (decoder.getICCSize() > 0) { JPEGR_CHECK(appendGainMap(yuv420jpg_image_ptr, gainmapjpg_image_ptr, /* exif */ nullptr, /* icc */ nullptr, /* icc size */ 0, metadata, dest)); } else { @@ -577,12 +577,12 @@ status_t JpegR::encodeJPEGR(jr_compressed_ptr yuv420jpg_image_ptr, return JPEGR_NO_ERROR; } -status_t JpegR::getJPEGRInfo(jr_compressed_ptr jpegr_image_ptr, jr_info_ptr jpeg_image_info_ptr) { +status_t JpegR::getJPEGRInfo(jr_compressed_ptr jpegr_image_ptr, jr_info_ptr jpegr_image_info_ptr) { if (jpegr_image_ptr == nullptr || jpegr_image_ptr->data == nullptr) { ALOGE("received nullptr for compressed jpegr image"); return ERROR_JPEGR_BAD_PTR; } - if (jpeg_image_info_ptr == nullptr) { + if (jpegr_image_info_ptr == nullptr) { ALOGE("received nullptr for compressed jpegr info struct"); return ERROR_JPEGR_BAD_PTR; } @@ -592,13 +592,16 @@ status_t JpegR::getJPEGRInfo(jr_compressed_ptr jpegr_image_ptr, jr_info_ptr jpeg if (status != JPEGR_NO_ERROR && status != ERROR_JPEGR_GAIN_MAP_IMAGE_NOT_FOUND) { return status; } - - JpegDecoderHelper jpeg_dec_obj_hdr; - if (!jpeg_dec_obj_hdr.getCompressedImageParameters( - primary_image.data, primary_image.length, &jpeg_image_info_ptr->width, - &jpeg_image_info_ptr->height, jpeg_image_info_ptr->iccData, - jpeg_image_info_ptr->exifData)) { - return ERROR_JPEGR_DECODE_ERROR; + status = parseJpegInfo(&primary_image, jpegr_image_info_ptr->primaryImgInfo, + &jpegr_image_info_ptr->width, &jpegr_image_info_ptr->height); + if (status != JPEGR_NO_ERROR) { + return status; + } + if (jpegr_image_info_ptr->gainmapImgInfo != nullptr) { + status = parseJpegInfo(&gainmap_image, jpegr_image_info_ptr->gainmapImgInfo); + if (status != JPEGR_NO_ERROR) { + return status; + } } return status; @@ -641,8 +644,9 @@ status_t JpegR::decodeJPEGR(jr_compressed_ptr jpegr_image_ptr, jr_uncompressed_p } JpegDecoderHelper jpeg_dec_obj_yuv420; - if (!jpeg_dec_obj_yuv420.decompressImage(primary_jpeg_image.data, primary_jpeg_image.length, - (output_format == ULTRAHDR_OUTPUT_SDR))) { + if (!jpeg_dec_obj_yuv420.decompressImage( + primary_jpeg_image.data, primary_jpeg_image.length, + (output_format == ULTRAHDR_OUTPUT_SDR) ? DECODE_TO_RGBA : DECODE_TO_YCBCR)) { return ERROR_JPEGR_DECODE_ERROR; } @@ -1183,6 +1187,45 @@ status_t JpegR::extractPrimaryImageAndGainMap(jr_compressed_ptr jpegr_image_ptr, return JPEGR_NO_ERROR; } +status_t JpegR::parseJpegInfo(jr_compressed_ptr jpeg_image_ptr, j_info_ptr jpeg_image_info_ptr, + size_t* img_width, size_t* img_height) { + JpegDecoderHelper jpeg_dec_obj; + if (!jpeg_dec_obj.getCompressedImageParameters(jpeg_image_ptr->data, jpeg_image_ptr->length)) { + return ERROR_JPEGR_DECODE_ERROR; + } + size_t imgWidth, imgHeight; + imgWidth = jpeg_dec_obj.getDecompressedImageWidth(); + imgHeight = jpeg_dec_obj.getDecompressedImageHeight(); + + if (jpeg_image_info_ptr != nullptr) { + jpeg_image_info_ptr->width = imgWidth; + jpeg_image_info_ptr->height = imgHeight; + jpeg_image_info_ptr->imgData.resize(jpeg_image_ptr->length, 0); + memcpy(static_cast<void*>(jpeg_image_info_ptr->imgData.data()), jpeg_image_ptr->data, + jpeg_image_ptr->length); + if (jpeg_dec_obj.getICCSize() != 0) { + jpeg_image_info_ptr->iccData.resize(jpeg_dec_obj.getICCSize(), 0); + memcpy(static_cast<void*>(jpeg_image_info_ptr->iccData.data()), jpeg_dec_obj.getICCPtr(), + jpeg_dec_obj.getICCSize()); + } + if (jpeg_dec_obj.getEXIFSize() != 0) { + jpeg_image_info_ptr->exifData.resize(jpeg_dec_obj.getEXIFSize(), 0); + memcpy(static_cast<void*>(jpeg_image_info_ptr->exifData.data()), jpeg_dec_obj.getEXIFPtr(), + jpeg_dec_obj.getEXIFSize()); + } + if (jpeg_dec_obj.getXMPSize() != 0) { + jpeg_image_info_ptr->xmpData.resize(jpeg_dec_obj.getXMPSize(), 0); + memcpy(static_cast<void*>(jpeg_image_info_ptr->xmpData.data()), jpeg_dec_obj.getXMPPtr(), + jpeg_dec_obj.getXMPSize()); + } + } + if (img_width != nullptr && img_height != nullptr) { + *img_width = imgWidth; + *img_height = imgHeight; + } + return JPEGR_NO_ERROR; +} + // JPEG/R structure: // SOI (ff d8) // diff --git a/tests/jpegdecoderhelper_test.cpp b/tests/jpegdecoderhelper_test.cpp index 4e72be1..ef6df1d 100644 --- a/tests/jpegdecoderhelper_test.cpp +++ b/tests/jpegdecoderhelper_test.cpp @@ -115,33 +115,23 @@ TEST_F(JpegDecoderHelperTest, decodeGreyImage) { } TEST_F(JpegDecoderHelperTest, getCompressedImageParameters) { - size_t width = 0, height = 0; - std::vector<uint8_t> icc, exif; - JpegDecoderHelper decoder; - EXPECT_TRUE(decoder.getCompressedImageParameters(mYuvImage.buffer.get(), mYuvImage.size, &width, - &height, &icc, &exif)); - - EXPECT_EQ(width, IMAGE_WIDTH); - EXPECT_EQ(height, IMAGE_HEIGHT); - EXPECT_EQ(icc.size(), 0); - EXPECT_EQ(exif.size(), 0); + EXPECT_TRUE(decoder.getCompressedImageParameters(mYuvImage.buffer.get(), mYuvImage.size)); + EXPECT_EQ(IMAGE_WIDTH, decoder.getDecompressedImageWidth()); + EXPECT_EQ(IMAGE_HEIGHT, decoder.getDecompressedImageHeight()); + EXPECT_EQ(decoder.getICCSize(), 0); + EXPECT_EQ(decoder.getEXIFSize(), 0); } TEST_F(JpegDecoderHelperTest, getCompressedImageParametersIcc) { - size_t width = 0, height = 0; - std::vector<uint8_t> icc, exif; - JpegDecoderHelper decoder; - EXPECT_TRUE(decoder.getCompressedImageParameters(mYuvIccImage.buffer.get(), mYuvIccImage.size, - &width, &height, &icc, &exif)); - - EXPECT_EQ(width, IMAGE_WIDTH); - EXPECT_EQ(height, IMAGE_HEIGHT); - EXPECT_GT(icc.size(), 0); - EXPECT_GT(exif.size(), 0); - - EXPECT_EQ(IccHelper::readIccColorGamut(icc.data(), icc.size()), ULTRAHDR_COLORGAMUT_BT709); + EXPECT_TRUE(decoder.getCompressedImageParameters(mYuvIccImage.buffer.get(), mYuvIccImage.size)); + EXPECT_EQ(IMAGE_WIDTH, decoder.getDecompressedImageWidth()); + EXPECT_EQ(IMAGE_HEIGHT, decoder.getDecompressedImageHeight()); + EXPECT_GT(decoder.getICCSize(), 0); + EXPECT_GT(decoder.getEXIFSize(), 0); + EXPECT_EQ(IccHelper::readIccColorGamut(decoder.getICCPtr(), decoder.getICCSize()), + ULTRAHDR_COLORGAMUT_BT709); } } // namespace ultrahdr diff --git a/tests/jpegr_test.cpp b/tests/jpegr_test.cpp index 39c7af0..0b420e6 100644 --- a/tests/jpegr_test.cpp +++ b/tests/jpegr_test.cpp @@ -302,9 +302,7 @@ static bool readFile(const char* fileName, void*& result, int maxLength, int& le } void decodeJpegRImg(jr_compressed_ptr img, [[maybe_unused]] const char* outFileName) { - std::vector<uint8_t> iccData(0); - std::vector<uint8_t> exifData(0); - jpegr_info_struct info{0, 0, &iccData, &exifData}; + jpegr_info_struct info{}; JpegR jpegHdr; ASSERT_EQ(JPEGR_NO_ERROR, jpegHdr.getJPEGRInfo(img, &info)); ASSERT_EQ(kImageWidth, info.width); |