Loading libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h +4 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ extern "C" { #include <utils/Errors.h> #include <vector> // constraint on max width and max height is only due to device alloc constraints // Can tune these values basing on the target device static const int kMaxWidth = 8192; static const int kMaxHeight = 8192; Loading Loading @@ -94,9 +96,8 @@ public: /* * 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, bool getCompressedImageParameters(const void* image, int length, size_t* pWidth, size_t* pHeight, std::vector<uint8_t>* iccData, std::vector<uint8_t>* exifData); private: Loading libs/ultrahdr/include/ultrahdr/ultrahdr.h +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ typedef enum { } ultrahdr_color_gamut; // Transfer functions for image data // TODO: TF LINEAR is deprecated, remove this enum and the code surrounding it. typedef enum { ULTRAHDR_TF_UNSPECIFIED = -1, ULTRAHDR_TF_LINEAR = 0, Loading libs/ultrahdr/jpegdecoderhelper.cpp +63 −95 Original line number Diff line number Diff line Loading @@ -76,8 +76,8 @@ static void jpegr_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { static void jpegr_term_source(j_decompress_ptr /*cinfo*/) {} jpegr_source_mgr::jpegr_source_mgr(const uint8_t* ptr, int len) : mBufferPtr(ptr), mBufferLength(len) { jpegr_source_mgr::jpegr_source_mgr(const uint8_t* ptr, int len) : mBufferPtr(ptr), mBufferLength(len) { init_source = jpegr_init_source; fill_input_buffer = jpegr_fill_input_buffer; skip_input_data = jpegr_skip_input_data; Loading @@ -92,25 +92,18 @@ static void jpegrerror_exit(j_common_ptr cinfo) { longjmp(err->setjmp_buffer, 1); } JpegDecoderHelper::JpegDecoderHelper() { } JpegDecoderHelper::JpegDecoderHelper() {} JpegDecoderHelper::~JpegDecoderHelper() { } JpegDecoderHelper::~JpegDecoderHelper() {} bool JpegDecoderHelper::decompressImage(const void* image, int length, bool decodeToRGBA) { if (image == nullptr || length <= 0) { ALOGE("Image size can not be handled: %d", length); return false; } mResultBuffer.clear(); mXMPBuffer.clear(); if (!decode(image, length, decodeToRGBA)) { return false; } return true; return decode(image, length, decodeToRGBA); } void* JpegDecoderHelper::getDecompressedImagePtr() { Loading Loading @@ -154,26 +147,28 @@ size_t JpegDecoderHelper::getDecompressedImageHeight() { } bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) { bool status = true; jpeg_decompress_struct cinfo; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; bool status = true; cinfo.err = jpeg_std_error(&myerr.pub); myerr.pub.error_exit = jpegrerror_exit; if (setjmp(myerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return false; } jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, kAPP0Marker, 0xFFFF); 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; jpeg_read_header(&cinfo, TRUE); if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { jpeg_destroy_decompress(&cinfo); return false; } // Save XMP data, EXIF data, and ICC data. // Here we only handle the first XMP / EXIF / ICC package. Loading @@ -184,31 +179,24 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) bool xmpAppears = false; bool iccAppears = false; for (jpeg_marker_struct* marker = cinfo.marker_list; marker && !(exifAppears && xmpAppears && iccAppears); marker = marker->next) { marker && !(exifAppears && xmpAppears && iccAppears); marker = marker->next) { if (marker->marker != kAPP1Marker && marker->marker != kAPP2Marker) { continue; } const unsigned int len = marker->data_length; if (!xmpAppears && len > kXmpNameSpace.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kXmpNameSpace.c_str(), if (!xmpAppears && len > kXmpNameSpace.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kXmpNameSpace.c_str(), kXmpNameSpace.size())) { mXMPBuffer.resize(len + 1, 0); memcpy(static_cast<void*>(mXMPBuffer.data()), marker->data, len); xmpAppears = true; } else if (!exifAppears && len > kExifIdCode.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kExifIdCode.c_str(), } else if (!exifAppears && len > kExifIdCode.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kExifIdCode.c_str(), kExifIdCode.size())) { mEXIFBuffer.resize(len, 0); memcpy(static_cast<void*>(mEXIFBuffer.data()), marker->data, len); exifAppears = true; } else if (!iccAppears && len > sizeof(kICCSig) && } else if (!iccAppears && len > sizeof(kICCSig) && !memcmp(marker->data, kICCSig, sizeof(kICCSig))) { mICCBuffer.resize(len, 0); memcpy(static_cast<void*>(mICCBuffer.data()), marker->data, len); Loading @@ -216,16 +204,13 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) } } if (cinfo.image_width > kMaxWidth || cinfo.image_height > kMaxHeight) { // constraint on max width and max height is only due to alloc constraints // tune these values basing on the target device mWidth = cinfo.image_width; mHeight = cinfo.image_height; if (mWidth > kMaxWidth || mHeight > kMaxHeight) { status = false; goto CleanUp; } mWidth = cinfo.image_width; mHeight = cinfo.image_height; if (decodeToRGBA) { // The primary image is expected to be yuv420 sampling if (cinfo.jpeg_color_space != JCS_YCbCr) { Loading @@ -233,12 +218,9 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) ALOGE("%s: decodeToRGBA unexpected jpeg color space ", __func__); goto CleanUp; } if (cinfo.comp_info[0].h_samp_factor != 2 || cinfo.comp_info[1].h_samp_factor != 1 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[0].v_samp_factor != 2 || cinfo.comp_info[1].v_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1 ) { 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 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1) { status = false; ALOGE("%s: decodeToRGBA unexpected primary image sub-sampling", __func__); goto CleanUp; Loading @@ -248,12 +230,9 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) cinfo.out_color_space = JCS_EXT_RGBA; } else { if (cinfo.jpeg_color_space == JCS_YCbCr) { if (cinfo.comp_info[0].h_samp_factor != 2 || cinfo.comp_info[1].h_samp_factor != 1 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[0].v_samp_factor != 2 || cinfo.comp_info[1].v_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1) { 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 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1) { status = false; ALOGE("%s: decoding to YUV only supports 4:2:0 subsampling", __func__); goto CleanUp; Loading @@ -271,9 +250,7 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) } cinfo.dct_method = JDCT_ISLOW; jpeg_start_decompress(&cinfo); if (!decompress(&cinfo, static_cast<const uint8_t*>(mResultBuffer.data()), cinfo.jpeg_color_space == JCS_GRAYSCALE)) { status = false; Loading @@ -289,24 +266,19 @@ CleanUp: bool JpegDecoderHelper::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel) { if (isSingleChannel) { return decompressSingleChannel(cinfo, dest); } if (cinfo->out_color_space == JCS_EXT_RGBA) return decompressRGBA(cinfo, dest); else return decompressYUV(cinfo, dest); return isSingleChannel ? decompressSingleChannel(cinfo, dest) : ((cinfo->out_color_space == JCS_EXT_RGBA) ? decompressRGBA(cinfo, dest) : 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) { 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; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; cinfo.err = jpeg_std_error(&myerr.pub); myerr.pub.error_exit = jpegrerror_exit; if (setjmp(myerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return false; Loading @@ -316,6 +288,7 @@ bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int leng 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); Loading @@ -330,8 +303,7 @@ bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int leng } if (iccData != nullptr) { for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { if (marker->marker != kAPP2Marker) { continue; } Loading Loading @@ -368,18 +340,13 @@ bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int leng } bool JpegDecoderHelper::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPLE* decodeDst = (JSAMPLE*) dest; uint32_t lines = 0; // TODO: use batches for more effectiveness while (lines < cinfo->image_height) { uint32_t ret = jpeg_read_scanlines(cinfo, &decodeDst, 1); if (ret == 0) { break; } decodeDst += cinfo->image_width * 4; lines++; JSAMPLE* out = (JSAMPLE*)dest; while (cinfo->output_scanline < cinfo->image_height) { if (1 != jpeg_read_scanlines(cinfo, &out, 1)) return false; out += cinfo->image_width * 4; } return lines == cinfo->image_height; return true; } bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) { Loading Loading @@ -462,7 +429,8 @@ bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8 return true; } bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) { bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPROW y[kCompressBatchSize]; JSAMPARRAY planes[1]{y}; Loading Loading @@ -510,4 +478,4 @@ bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, c return true; } } // namespace ultrahdr } // namespace android::ultrahdr libs/ultrahdr/jpegr.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -815,10 +815,13 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr yuv420_image_ptr, map_data.reset(reinterpret_cast<uint8_t*>(dest->data)); ColorTransformFn hdrInvOetf = nullptr; float hdr_white_nits = kSdrWhiteNits; float hdr_white_nits; switch (hdr_tf) { case ULTRAHDR_TF_LINEAR: hdrInvOetf = identityConversion; // Note: this will produce clipping if the input exceeds kHlgMaxNits. // TODO: TF LINEAR will be deprecated. hdr_white_nits = kHlgMaxNits; break; case ULTRAHDR_TF_HLG: #if USE_HLG_INVOETF_LUT Loading libs/ultrahdr/tests/Android.bp +4 −33 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ cc_test { "gainmapmath_test.cpp", "icchelper_test.cpp", "jpegr_test.cpp", "jpegencoderhelper_test.cpp", "jpegdecoderhelper_test.cpp", ], shared_libs: [ "libimage_io", Loading @@ -42,38 +44,7 @@ cc_test { "libultrahdr", "libutils", ], } cc_test { name: "jpegencoderhelper_test", test_suites: ["device-tests"], srcs: [ "jpegencoderhelper_test.cpp", ], shared_libs: [ "libjpeg", "liblog", ], static_libs: [ "libgtest", "libjpegencoder", ], } cc_test { name: "jpegdecoderhelper_test", test_suites: ["device-tests"], srcs: [ "jpegdecoderhelper_test.cpp", ], shared_libs: [ "libjpeg", "liblog", ], static_libs: [ "libgtest", "libjpegdecoder", "libultrahdr", "libutils", data: [ "./data/*.*", ], } Loading
libs/ultrahdr/include/ultrahdr/jpegdecoderhelper.h +4 −3 Original line number Diff line number Diff line Loading @@ -26,6 +26,8 @@ extern "C" { #include <utils/Errors.h> #include <vector> // constraint on max width and max height is only due to device alloc constraints // Can tune these values basing on the target device static const int kMaxWidth = 8192; static const int kMaxHeight = 8192; Loading Loading @@ -94,9 +96,8 @@ public: /* * 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, bool getCompressedImageParameters(const void* image, int length, size_t* pWidth, size_t* pHeight, std::vector<uint8_t>* iccData, std::vector<uint8_t>* exifData); private: Loading
libs/ultrahdr/include/ultrahdr/ultrahdr.h +1 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ typedef enum { } ultrahdr_color_gamut; // Transfer functions for image data // TODO: TF LINEAR is deprecated, remove this enum and the code surrounding it. typedef enum { ULTRAHDR_TF_UNSPECIFIED = -1, ULTRAHDR_TF_LINEAR = 0, Loading
libs/ultrahdr/jpegdecoderhelper.cpp +63 −95 Original line number Diff line number Diff line Loading @@ -76,8 +76,8 @@ static void jpegr_skip_input_data(j_decompress_ptr cinfo, long num_bytes) { static void jpegr_term_source(j_decompress_ptr /*cinfo*/) {} jpegr_source_mgr::jpegr_source_mgr(const uint8_t* ptr, int len) : mBufferPtr(ptr), mBufferLength(len) { jpegr_source_mgr::jpegr_source_mgr(const uint8_t* ptr, int len) : mBufferPtr(ptr), mBufferLength(len) { init_source = jpegr_init_source; fill_input_buffer = jpegr_fill_input_buffer; skip_input_data = jpegr_skip_input_data; Loading @@ -92,25 +92,18 @@ static void jpegrerror_exit(j_common_ptr cinfo) { longjmp(err->setjmp_buffer, 1); } JpegDecoderHelper::JpegDecoderHelper() { } JpegDecoderHelper::JpegDecoderHelper() {} JpegDecoderHelper::~JpegDecoderHelper() { } JpegDecoderHelper::~JpegDecoderHelper() {} bool JpegDecoderHelper::decompressImage(const void* image, int length, bool decodeToRGBA) { if (image == nullptr || length <= 0) { ALOGE("Image size can not be handled: %d", length); return false; } mResultBuffer.clear(); mXMPBuffer.clear(); if (!decode(image, length, decodeToRGBA)) { return false; } return true; return decode(image, length, decodeToRGBA); } void* JpegDecoderHelper::getDecompressedImagePtr() { Loading Loading @@ -154,26 +147,28 @@ size_t JpegDecoderHelper::getDecompressedImageHeight() { } bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) { bool status = true; jpeg_decompress_struct cinfo; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; bool status = true; cinfo.err = jpeg_std_error(&myerr.pub); myerr.pub.error_exit = jpegrerror_exit; if (setjmp(myerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return false; } jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, kAPP0Marker, 0xFFFF); 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; jpeg_read_header(&cinfo, TRUE); if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { jpeg_destroy_decompress(&cinfo); return false; } // Save XMP data, EXIF data, and ICC data. // Here we only handle the first XMP / EXIF / ICC package. Loading @@ -184,31 +179,24 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) bool xmpAppears = false; bool iccAppears = false; for (jpeg_marker_struct* marker = cinfo.marker_list; marker && !(exifAppears && xmpAppears && iccAppears); marker = marker->next) { marker && !(exifAppears && xmpAppears && iccAppears); marker = marker->next) { if (marker->marker != kAPP1Marker && marker->marker != kAPP2Marker) { continue; } const unsigned int len = marker->data_length; if (!xmpAppears && len > kXmpNameSpace.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kXmpNameSpace.c_str(), if (!xmpAppears && len > kXmpNameSpace.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kXmpNameSpace.c_str(), kXmpNameSpace.size())) { mXMPBuffer.resize(len + 1, 0); memcpy(static_cast<void*>(mXMPBuffer.data()), marker->data, len); xmpAppears = true; } else if (!exifAppears && len > kExifIdCode.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kExifIdCode.c_str(), } else if (!exifAppears && len > kExifIdCode.size() && !strncmp(reinterpret_cast<const char*>(marker->data), kExifIdCode.c_str(), kExifIdCode.size())) { mEXIFBuffer.resize(len, 0); memcpy(static_cast<void*>(mEXIFBuffer.data()), marker->data, len); exifAppears = true; } else if (!iccAppears && len > sizeof(kICCSig) && } else if (!iccAppears && len > sizeof(kICCSig) && !memcmp(marker->data, kICCSig, sizeof(kICCSig))) { mICCBuffer.resize(len, 0); memcpy(static_cast<void*>(mICCBuffer.data()), marker->data, len); Loading @@ -216,16 +204,13 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) } } if (cinfo.image_width > kMaxWidth || cinfo.image_height > kMaxHeight) { // constraint on max width and max height is only due to alloc constraints // tune these values basing on the target device mWidth = cinfo.image_width; mHeight = cinfo.image_height; if (mWidth > kMaxWidth || mHeight > kMaxHeight) { status = false; goto CleanUp; } mWidth = cinfo.image_width; mHeight = cinfo.image_height; if (decodeToRGBA) { // The primary image is expected to be yuv420 sampling if (cinfo.jpeg_color_space != JCS_YCbCr) { Loading @@ -233,12 +218,9 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) ALOGE("%s: decodeToRGBA unexpected jpeg color space ", __func__); goto CleanUp; } if (cinfo.comp_info[0].h_samp_factor != 2 || cinfo.comp_info[1].h_samp_factor != 1 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[0].v_samp_factor != 2 || cinfo.comp_info[1].v_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1 ) { 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 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1) { status = false; ALOGE("%s: decodeToRGBA unexpected primary image sub-sampling", __func__); goto CleanUp; Loading @@ -248,12 +230,9 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) cinfo.out_color_space = JCS_EXT_RGBA; } else { if (cinfo.jpeg_color_space == JCS_YCbCr) { if (cinfo.comp_info[0].h_samp_factor != 2 || cinfo.comp_info[1].h_samp_factor != 1 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[0].v_samp_factor != 2 || cinfo.comp_info[1].v_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1) { 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 || cinfo.comp_info[2].h_samp_factor != 1 || cinfo.comp_info[2].v_samp_factor != 1) { status = false; ALOGE("%s: decoding to YUV only supports 4:2:0 subsampling", __func__); goto CleanUp; Loading @@ -271,9 +250,7 @@ bool JpegDecoderHelper::decode(const void* image, int length, bool decodeToRGBA) } cinfo.dct_method = JDCT_ISLOW; jpeg_start_decompress(&cinfo); if (!decompress(&cinfo, static_cast<const uint8_t*>(mResultBuffer.data()), cinfo.jpeg_color_space == JCS_GRAYSCALE)) { status = false; Loading @@ -289,24 +266,19 @@ CleanUp: bool JpegDecoderHelper::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel) { if (isSingleChannel) { return decompressSingleChannel(cinfo, dest); } if (cinfo->out_color_space == JCS_EXT_RGBA) return decompressRGBA(cinfo, dest); else return decompressYUV(cinfo, dest); return isSingleChannel ? decompressSingleChannel(cinfo, dest) : ((cinfo->out_color_space == JCS_EXT_RGBA) ? decompressRGBA(cinfo, dest) : 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) { 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; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; cinfo.err = jpeg_std_error(&myerr.pub); myerr.pub.error_exit = jpegrerror_exit; if (setjmp(myerr.setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return false; Loading @@ -316,6 +288,7 @@ bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int leng 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); Loading @@ -330,8 +303,7 @@ bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int leng } if (iccData != nullptr) { for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { if (marker->marker != kAPP2Marker) { continue; } Loading Loading @@ -368,18 +340,13 @@ bool JpegDecoderHelper::getCompressedImageParameters(const void* image, int leng } bool JpegDecoderHelper::decompressRGBA(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPLE* decodeDst = (JSAMPLE*) dest; uint32_t lines = 0; // TODO: use batches for more effectiveness while (lines < cinfo->image_height) { uint32_t ret = jpeg_read_scanlines(cinfo, &decodeDst, 1); if (ret == 0) { break; } decodeDst += cinfo->image_width * 4; lines++; JSAMPLE* out = (JSAMPLE*)dest; while (cinfo->output_scanline < cinfo->image_height) { if (1 != jpeg_read_scanlines(cinfo, &out, 1)) return false; out += cinfo->image_width * 4; } return lines == cinfo->image_height; return true; } bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) { Loading Loading @@ -462,7 +429,8 @@ bool JpegDecoderHelper::decompressYUV(jpeg_decompress_struct* cinfo, const uint8 return true; } bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) { bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPROW y[kCompressBatchSize]; JSAMPARRAY planes[1]{y}; Loading Loading @@ -510,4 +478,4 @@ bool JpegDecoderHelper::decompressSingleChannel(jpeg_decompress_struct* cinfo, c return true; } } // namespace ultrahdr } // namespace android::ultrahdr
libs/ultrahdr/jpegr.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -815,10 +815,13 @@ status_t JpegR::generateGainMap(jr_uncompressed_ptr yuv420_image_ptr, map_data.reset(reinterpret_cast<uint8_t*>(dest->data)); ColorTransformFn hdrInvOetf = nullptr; float hdr_white_nits = kSdrWhiteNits; float hdr_white_nits; switch (hdr_tf) { case ULTRAHDR_TF_LINEAR: hdrInvOetf = identityConversion; // Note: this will produce clipping if the input exceeds kHlgMaxNits. // TODO: TF LINEAR will be deprecated. hdr_white_nits = kHlgMaxNits; break; case ULTRAHDR_TF_HLG: #if USE_HLG_INVOETF_LUT Loading
libs/ultrahdr/tests/Android.bp +4 −33 Original line number Diff line number Diff line Loading @@ -28,6 +28,8 @@ cc_test { "gainmapmath_test.cpp", "icchelper_test.cpp", "jpegr_test.cpp", "jpegencoderhelper_test.cpp", "jpegdecoderhelper_test.cpp", ], shared_libs: [ "libimage_io", Loading @@ -42,38 +44,7 @@ cc_test { "libultrahdr", "libutils", ], } cc_test { name: "jpegencoderhelper_test", test_suites: ["device-tests"], srcs: [ "jpegencoderhelper_test.cpp", ], shared_libs: [ "libjpeg", "liblog", ], static_libs: [ "libgtest", "libjpegencoder", ], } cc_test { name: "jpegdecoderhelper_test", test_suites: ["device-tests"], srcs: [ "jpegdecoderhelper_test.cpp", ], shared_libs: [ "libjpeg", "liblog", ], static_libs: [ "libgtest", "libjpegdecoder", "libultrahdr", "libutils", data: [ "./data/*.*", ], }