Loading libs/jpegrecoverymap/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ cc_library_static { srcs: [ "recoverymap.cpp", "recoverymapmath.cpp", "recoverymaputils.cpp", ], shared_libs: [ Loading libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h +18 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,21 @@ public: * decompressImage(). */ size_t getDecompressedImageHeight(); /* * Returns the XMP data from the image. */ void* getXMPPtr(); /* * Returns the decompressed XMP buffer size. This method must be called only after * calling decompressImage(). */ size_t getXMPSize(); bool getCompressedImageParameters(const void* image, int length, size_t* pWidth, size_t* pHeight, std::vector<uint8_t>* &iccData, std::vector<uint8_t>* &exifData); private: bool decode(const void* image, int length); // Returns false if errors occur. Loading @@ -72,6 +87,9 @@ private: static const int kCompressBatchSize = 16; // The buffer that holds the decompressed result. std::vector<JOCTET> mResultBuffer; // The buffer that holds XMP Data. std::vector<JOCTET> mXMPBuffer; // Resolution of the decompressed image. size_t mWidth; size_t mHeight; Loading libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h +33 −5 Original line number Diff line number Diff line Loading @@ -34,6 +34,13 @@ typedef enum { JPEGR_TF_PQ = 1, } jpegr_transfer_function; struct jpegr_info_struct { size_t width; size_t height; std::vector<uint8_t>* iccData; std::vector<uint8_t>* exifData; }; /* * Holds information for uncompressed image or recovery map. */ Loading Loading @@ -117,6 +124,7 @@ 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 jpegr_metadata* jr_metadata_ptr; typedef struct jpegr_info_struct* jr_info_ptr; class RecoveryMap { public: Loading Loading @@ -200,8 +208,19 @@ public: */ status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, jr_uncompressed_ptr dest, jr_exif_ptr exif, bool request_sdr); jr_exif_ptr exif = nullptr, bool request_sdr = false); /* * Gets Info from JPEGR file without decoding it. * * The output is filled jpegr_info structure * @param compressed_jpegr_image compressed JPEGR image * @param jpegr_info pointer to output JPEGR info * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise */ status_t getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image, jr_info_ptr jpegr_info); private: /* * This method is called in the decoding pipeline. It will decode the recovery map. Loading Loading @@ -259,18 +278,27 @@ private: jr_metadata_ptr metadata, jr_uncompressed_ptr dest); /* * This methoud is called to separate primary image and recovery map image from JPEGR * * @param compressed_jpegr_image compressed JPEGR image * @param primary_image destination of primary image * @param recovery_map destination of compressed recovery map * @return NO_ERROR if calculation succeeds, error code if error occurs. */ status_t extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image, jr_compressed_ptr primary_image, jr_compressed_ptr recovery_map); /* * This method is called in the decoding pipeline. It will read XMP metadata to find the start * position of the compressed recovery map, and will extract the compressed recovery map. * * @param compressed_jpegr_image compressed JPEGR image * @param dest destination of compressed recovery map * @param metadata destination of the recovery map metadata * @return NO_ERROR if calculation succeeds, error code if error occurs. */ status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image, jr_compressed_ptr dest, jr_metadata_ptr metadata); jr_compressed_ptr dest); /* * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image Loading libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #include <stdint.h> #include <cstdio> namespace android::recoverymap { struct jpegr_metadata; /* * Parses XMP packet and fills metadata with data from XMP * * @param xmp_data pointer to XMP packet * @param xmp_size size of XMP packet * @param metadata place to store HDR metadata values * @return true if metadata is successfully retrieved, false otherwise */ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* metadata); } #endif //ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H No newline at end of file libs/jpegrecoverymap/jpegdecoder.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -20,8 +20,15 @@ #include <errno.h> #include <setjmp.h> #include <string> using namespace std; namespace android::recoverymap { const uint32_t kExifMarker = JPEG_APP0 + 1; const uint32_t kICCMarker = JPEG_APP0 + 2; struct jpegr_source_mgr : jpeg_source_mgr { jpegr_source_mgr(const uint8_t* ptr, int len); ~jpegr_source_mgr(); Loading Loading @@ -88,6 +95,7 @@ bool JpegDecoder::decompressImage(const void* image, int length) { } mResultBuffer.clear(); mXMPBuffer.clear(); if (!decode(image, length)) { return false; } Loading @@ -103,6 +111,15 @@ size_t JpegDecoder::getDecompressedImageSize() { return mResultBuffer.size(); } void* JpegDecoder::getXMPPtr() { return mXMPBuffer.data(); } size_t JpegDecoder::getXMPSize() { return mXMPBuffer.size(); } size_t JpegDecoder::getDecompressedImageWidth() { return mWidth; } Loading @@ -115,6 +132,8 @@ bool JpegDecoder::decode(const void* image, int length) { jpeg_decompress_struct cinfo; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; string nameSpace = "http://ns.adobe.com/xap/1.0/"; cinfo.err = jpeg_std_error(&myerr.pub); myerr.pub.error_exit = jpegrerror_exit; Loading @@ -124,9 +143,26 @@ bool JpegDecoder::decode(const void* image, int length) { } jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF); cinfo.src = &mgr; jpeg_read_header(&cinfo, TRUE); // Save XMP Data for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { if (marker->marker == kExifMarker) { const unsigned int len = marker->data_length; if (len > nameSpace.size() && !strncmp(reinterpret_cast<const char*>(marker->data), nameSpace.c_str(), nameSpace.size())) { mXMPBuffer.resize(len+1, 0); memcpy(static_cast<void*>(mXMPBuffer.data()), marker->data, len); break; } } } mWidth = cinfo.image_width; mHeight = cinfo.image_height; Loading Loading @@ -161,6 +197,43 @@ bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, return decompressYUV(cinfo, dest); } bool JpegDecoder::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; } jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF); jpeg_save_markers(&cinfo, kICCMarker, 0xFFFF); cinfo.src = &mgr; if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { jpeg_destroy_decompress(&cinfo); return false; } *pWidth = cinfo.image_width; *pHeight = cinfo.image_height; //TODO: Parse iccProfile and exifData (void)iccData; (void)exifData; jpeg_destroy_decompress(&cinfo); return true; } bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPROW y[kCompressBatchSize]; Loading Loading
libs/jpegrecoverymap/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ cc_library_static { srcs: [ "recoverymap.cpp", "recoverymapmath.cpp", "recoverymaputils.cpp", ], shared_libs: [ Loading
libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h +18 −0 Original line number Diff line number Diff line Loading @@ -61,6 +61,21 @@ public: * decompressImage(). */ size_t getDecompressedImageHeight(); /* * Returns the XMP data from the image. */ void* getXMPPtr(); /* * Returns the decompressed XMP buffer size. This method must be called only after * calling decompressImage(). */ size_t getXMPSize(); bool getCompressedImageParameters(const void* image, int length, size_t* pWidth, size_t* pHeight, std::vector<uint8_t>* &iccData, std::vector<uint8_t>* &exifData); private: bool decode(const void* image, int length); // Returns false if errors occur. Loading @@ -72,6 +87,9 @@ private: static const int kCompressBatchSize = 16; // The buffer that holds the decompressed result. std::vector<JOCTET> mResultBuffer; // The buffer that holds XMP Data. std::vector<JOCTET> mXMPBuffer; // Resolution of the decompressed image. size_t mWidth; size_t mHeight; Loading
libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h +33 −5 Original line number Diff line number Diff line Loading @@ -34,6 +34,13 @@ typedef enum { JPEGR_TF_PQ = 1, } jpegr_transfer_function; struct jpegr_info_struct { size_t width; size_t height; std::vector<uint8_t>* iccData; std::vector<uint8_t>* exifData; }; /* * Holds information for uncompressed image or recovery map. */ Loading Loading @@ -117,6 +124,7 @@ 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 jpegr_metadata* jr_metadata_ptr; typedef struct jpegr_info_struct* jr_info_ptr; class RecoveryMap { public: Loading Loading @@ -200,8 +208,19 @@ public: */ status_t decodeJPEGR(jr_compressed_ptr compressed_jpegr_image, jr_uncompressed_ptr dest, jr_exif_ptr exif, bool request_sdr); jr_exif_ptr exif = nullptr, bool request_sdr = false); /* * Gets Info from JPEGR file without decoding it. * * The output is filled jpegr_info structure * @param compressed_jpegr_image compressed JPEGR image * @param jpegr_info pointer to output JPEGR info * @return NO_ERROR if JPEGR parsing succeeds, error code otherwise */ status_t getJPEGRInfo(jr_compressed_ptr compressed_jpegr_image, jr_info_ptr jpegr_info); private: /* * This method is called in the decoding pipeline. It will decode the recovery map. Loading Loading @@ -259,18 +278,27 @@ private: jr_metadata_ptr metadata, jr_uncompressed_ptr dest); /* * This methoud is called to separate primary image and recovery map image from JPEGR * * @param compressed_jpegr_image compressed JPEGR image * @param primary_image destination of primary image * @param recovery_map destination of compressed recovery map * @return NO_ERROR if calculation succeeds, error code if error occurs. */ status_t extractPrimaryImageAndRecoveryMap(jr_compressed_ptr compressed_jpegr_image, jr_compressed_ptr primary_image, jr_compressed_ptr recovery_map); /* * This method is called in the decoding pipeline. It will read XMP metadata to find the start * position of the compressed recovery map, and will extract the compressed recovery map. * * @param compressed_jpegr_image compressed JPEGR image * @param dest destination of compressed recovery map * @param metadata destination of the recovery map metadata * @return NO_ERROR if calculation succeeds, error code if error occurs. */ status_t extractRecoveryMap(jr_compressed_ptr compressed_jpegr_image, jr_compressed_ptr dest, jr_metadata_ptr metadata); jr_compressed_ptr dest); /* * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image Loading
libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h 0 → 100644 +40 −0 Original line number Diff line number Diff line /* * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #include <stdint.h> #include <cstdio> namespace android::recoverymap { struct jpegr_metadata; /* * Parses XMP packet and fills metadata with data from XMP * * @param xmp_data pointer to XMP packet * @param xmp_size size of XMP packet * @param metadata place to store HDR metadata values * @return true if metadata is successfully retrieved, false otherwise */ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* metadata); } #endif //ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H No newline at end of file
libs/jpegrecoverymap/jpegdecoder.cpp +73 −0 Original line number Diff line number Diff line Loading @@ -20,8 +20,15 @@ #include <errno.h> #include <setjmp.h> #include <string> using namespace std; namespace android::recoverymap { const uint32_t kExifMarker = JPEG_APP0 + 1; const uint32_t kICCMarker = JPEG_APP0 + 2; struct jpegr_source_mgr : jpeg_source_mgr { jpegr_source_mgr(const uint8_t* ptr, int len); ~jpegr_source_mgr(); Loading Loading @@ -88,6 +95,7 @@ bool JpegDecoder::decompressImage(const void* image, int length) { } mResultBuffer.clear(); mXMPBuffer.clear(); if (!decode(image, length)) { return false; } Loading @@ -103,6 +111,15 @@ size_t JpegDecoder::getDecompressedImageSize() { return mResultBuffer.size(); } void* JpegDecoder::getXMPPtr() { return mXMPBuffer.data(); } size_t JpegDecoder::getXMPSize() { return mXMPBuffer.size(); } size_t JpegDecoder::getDecompressedImageWidth() { return mWidth; } Loading @@ -115,6 +132,8 @@ bool JpegDecoder::decode(const void* image, int length) { jpeg_decompress_struct cinfo; jpegr_source_mgr mgr(static_cast<const uint8_t*>(image), length); jpegrerror_mgr myerr; string nameSpace = "http://ns.adobe.com/xap/1.0/"; cinfo.err = jpeg_std_error(&myerr.pub); myerr.pub.error_exit = jpegrerror_exit; Loading @@ -124,9 +143,26 @@ bool JpegDecoder::decode(const void* image, int length) { } jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF); cinfo.src = &mgr; jpeg_read_header(&cinfo, TRUE); // Save XMP Data for (jpeg_marker_struct* marker = cinfo.marker_list; marker; marker = marker->next) { if (marker->marker == kExifMarker) { const unsigned int len = marker->data_length; if (len > nameSpace.size() && !strncmp(reinterpret_cast<const char*>(marker->data), nameSpace.c_str(), nameSpace.size())) { mXMPBuffer.resize(len+1, 0); memcpy(static_cast<void*>(mXMPBuffer.data()), marker->data, len); break; } } } mWidth = cinfo.image_width; mHeight = cinfo.image_height; Loading Loading @@ -161,6 +197,43 @@ bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, return decompressYUV(cinfo, dest); } bool JpegDecoder::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; } jpeg_create_decompress(&cinfo); jpeg_save_markers(&cinfo, kExifMarker, 0xFFFF); jpeg_save_markers(&cinfo, kICCMarker, 0xFFFF); cinfo.src = &mgr; if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) { jpeg_destroy_decompress(&cinfo); return false; } *pWidth = cinfo.image_width; *pHeight = cinfo.image_height; //TODO: Parse iccProfile and exifData (void)iccData; (void)exifData; jpeg_destroy_decompress(&cinfo); return true; } bool JpegDecoder::decompressYUV(jpeg_decompress_struct* cinfo, const uint8_t* dest) { JSAMPROW y[kCompressBatchSize]; Loading