Loading libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h +1 −5 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ public: */ void* getDecompressedImagePtr(); /* * Returns the decompressed raw image buffer size. This mgit ethod must be called only after * Returns the decompressed raw image buffer size. This method must be called only after * calling decompressImage(). */ size_t getDecompressedImageSize(); Loading Loading @@ -92,10 +92,6 @@ public: size_t* pWidth, size_t* pHeight, std::vector<uint8_t>* iccData, std::vector<uint8_t>* exifData); /* * Extracts EXIF package and updates the EXIF position / length without decoding the image. */ bool extractEXIF(const void* image, int length); private: bool decode(const void* image, int length, bool decodeToRGBA); Loading libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h +8 −4 Original line number Diff line number Diff line Loading @@ -321,13 +321,17 @@ private: jr_compressed_ptr dest); /* * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image * and the compressed recovery map as input, and update the XMP metadata with the end of JPEG * marker, and append the compressed gian map after the JPEG. * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image, * the compressed recovery map and optionally the exif package as inputs, and generate the XMP * metadata, and finally append everything in the order of: * SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, recovery map * Note that EXIF package is only available for encoding API-0 and API-1. For encoding API-2 and * API-3 this parameter is null, but the primary image in JPEG/R may still have EXIF as long as * the input JPEG has EXIF. * * @param compressed_jpeg_image compressed 8-bit JPEG image * @param compress_recovery_map compressed recover map * @param exif EXIF package * @param (nullable) exif EXIF package * @param metadata JPEG/R metadata to encode in XMP of the jpeg * @param dest compressed JPEGR image * @return NO_ERROR if calculation succeeds, error code if error occurs. Loading libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h +0 −78 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ const size_t EXIF_J_R_ENTRY_LENGTH = 12; * @return status of succeed or error code. */ status_t Write(jr_compressed_ptr destination, const void* source, size_t length, int &position); status_t Write(jr_exif_ptr destination, const void* source, size_t length, int &position); /* Loading Loading @@ -105,83 +104,6 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* meta * @return XMP metadata in type of string */ std::string generateXmp(int secondary_image_length, jpegr_metadata& metadata); /* * Add J R entry to existing exif, or create a new one with J R entry if it's null. * EXIF syntax / change: * ori: * FF E1 - APP1 * 01 FC - size of APP1 (to be calculated) * ----------------------------------------------------- * 45 78 69 66 00 00 - Exif\0\0 "Exif header" * 49 49 2A 00 - TIFF Header * 08 00 00 00 - offset to the IFD (image file directory) * 06 00 - 6 entries * 00 01 - Width Tag * 03 00 - 'Short' type * 01 00 00 00 - 1 component * 00 05 00 00 - image with 0x500 *-------------------------------------------------------------------------- * new: * FF E1 - APP1 * 02 08 - new size, equals to old size + EXIF_J_R_ENTRY_LENGTH (12) *----------------------------------------------------- * 45 78 69 66 00 00 - Exif\0\0 "Exif header" * 49 49 2A 00 - TIFF Header * 08 00 00 00 - offset to the IFD (image file directory) * 07 00 - +1 entry * 4A 52 Custom ('J''R') Tag * 07 00 - Unknown type * 01 00 00 00 - 1 component * 00 00 00 00 - empty data * 00 01 - Width Tag * 03 00 - 'Short' type * 01 00 00 00 - 1 component * 00 05 00 00 - image with 0x500 */ status_t updateExif(jr_exif_ptr exif, jr_exif_ptr dest); /* * Modify offsets in EXIF in place. * * Each tag has the following structure: * * 00 01 - Tag * 03 00 - data format * 01 00 00 00 - number of components * 00 05 00 00 - value * * The value means offset if * (1) num_of_components * bytes_per_component > 4 bytes, or * (2) tag == 0x8769 (ExifOffset). * In both cases, the method will add EXIF_J_R_ENTRY_LENGTH (12) to the offsets. */ void updateExifOffsets(jr_exif_ptr exif, int pos, bool use_big_endian); void updateExifOffsets(jr_exif_ptr exif, int pos, int num_entry, bool use_big_endian); /* * Read data from the target position and target length in bytes; */ int readValue(uint8_t* data, int pos, int length, bool use_big_endian); /* * Returns the length of data format in bytes * * ---------------------------------------------------------------------------------------------- * | value | 1 | 2 | 3 | 4 | * | format | unsigned byte | ascii strings | unsigned short | unsigned long | * | bytes/component | 1 | 1 | 2 | 4 | * ---------------------------------------------------------------------------------------------- * | value | 5 | 6 | 7 | 8 | * | format |unsigned rational| signed byte | undefined | signed short | * | bytes/component | 8 | 1 | 1 | 2 | * ---------------------------------------------------------------------------------------------- * | value | 9 | 10 | 11 | 12 | * | format | signed long | signed rational | single float | double float | * | bytes/component | 4 | 8 | 4 | 8 | * ---------------------------------------------------------------------------------------------- */ int findFormatLengthInBytes(int data_format); } #endif //ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H libs/jpegrecoverymap/jpegdecoder.cpp +0 −54 Original line number Diff line number Diff line Loading @@ -248,60 +248,6 @@ bool JpegDecoder::decode(const void* image, int length, bool decodeToRGBA) { return true; } // TODO (Fyodor/Dichen): merge this method with getCompressedImageParameters() since they have // similar functionality. Yet Dichen is not familiar with who's calling // getCompressedImageParameters(), looks like it's used by some pending CLs. bool JpegDecoder::extractEXIF(const void* image, int length) { 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, kAPP0Marker, 0xFFFF); jpeg_save_markers(&cinfo, kAPP1Marker, 0xFFFF); jpeg_save_markers(&cinfo, kAPP2Marker, 0xFFFF); cinfo.src = &mgr; jpeg_read_header(&cinfo, TRUE); bool exifAppears = false; size_t pos = 2; // position after SOI for (jpeg_marker_struct* marker = cinfo.marker_list; marker && !exifAppears; marker = marker->next) { pos += 4; pos += marker->original_length; if (marker->marker != kAPP1Marker) { continue; } const unsigned int len = marker->data_length; 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; mExifPos = pos - marker->original_length; } } jpeg_destroy_decompress(&cinfo); return true; } bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel) { if (isSingleChannel) { Loading libs/jpegrecoverymap/recoverymap.cpp +13 −105 Original line number Diff line number Diff line Loading @@ -175,18 +175,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jpeg.data = jpeg_encoder.getCompressedImagePtr(); jpeg.length = jpeg_encoder.getCompressedImageSize(); jpegr_exif_struct new_exif; if (exif == nullptr || exif->data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif->length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(exif, &new_exif)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, &new_exif, &metadata, dest)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -250,19 +239,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jpeg.data = jpeg_encoder.getCompressedImagePtr(); jpeg.length = jpeg_encoder.getCompressedImageSize(); jpegr_exif_struct new_exif; if (exif == nullptr || exif->data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif->length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(exif, &new_exif)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, &new_exif, &metadata, dest)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -311,47 +288,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.data = compressed_map_data.get(); JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); // Extract EXIF from JPEG without decoding. JpegDecoder jpeg_decoder; if (!jpeg_decoder.extractEXIF(compressed_jpeg_image->data, compressed_jpeg_image->length)) { return ERROR_JPEGR_DECODE_ERROR; } // Update exif. jpegr_exif_struct exif; exif.data = nullptr; exif.length = 0; jpegr_compressed_struct new_jpeg_image; new_jpeg_image.data = nullptr; new_jpeg_image.length = 0; if (jpeg_decoder.getEXIFPos() != 0) { copyJpegWithoutExif(&new_jpeg_image, compressed_jpeg_image, jpeg_decoder.getEXIFPos(), jpeg_decoder.getEXIFSize()); exif.data = jpeg_decoder.getEXIFPtr(); exif.length = jpeg_decoder.getEXIFSize(); } jpegr_exif_struct new_exif; if (exif.data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif.length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(&exif, &new_exif)); JPEGR_CHECK(appendRecoveryMap( new_jpeg_image.data == nullptr ? compressed_jpeg_image : &new_jpeg_image, &compressed_map, &new_exif, &metadata, dest)); if (new_jpeg_image.data != nullptr) { free(new_jpeg_image.data); } JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -384,33 +321,6 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, uncompressed_yuv_420_image.height = jpeg_decoder.getDecompressedImageHeight(); uncompressed_yuv_420_image.colorGamut = compressed_jpeg_image->colorGamut; // Update exif. jpegr_exif_struct exif; exif.data = nullptr; exif.length = 0; jpegr_compressed_struct new_jpeg_image; new_jpeg_image.data = nullptr; new_jpeg_image.length = 0; if (jpeg_decoder.getEXIFPos() != 0) { copyJpegWithoutExif(&new_jpeg_image, compressed_jpeg_image, jpeg_decoder.getEXIFPos(), jpeg_decoder.getEXIFSize()); exif.data = jpeg_decoder.getEXIFPtr(); exif.length = jpeg_decoder.getEXIFSize(); } jpegr_exif_struct new_exif; if (exif.data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif.length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(&exif, &new_exif)); if (uncompressed_p010_image->width != uncompressed_yuv_420_image.width || uncompressed_p010_image->height != uncompressed_yuv_420_image.height) { return ERROR_JPEGR_RESOLUTION_MISMATCH; Loading @@ -435,13 +345,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.data = compressed_map_data.get(); JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); JPEGR_CHECK(appendRecoveryMap( new_jpeg_image.data == nullptr ? compressed_jpeg_image : &new_jpeg_image, &compressed_map, &new_exif, &metadata, dest)); if (new_jpeg_image.data != nullptr) { free(new_jpeg_image.data); } JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -967,15 +871,20 @@ status_t RecoveryMap::extractRecoveryMap(jr_compressed_ptr compressed_jpegr_imag // JPEG/R structure: // SOI (ff d8) // // (Optional, only if EXIF package is from outside) // APP1 (ff e1) // 2 bytes of length (2 + length of exif package) // EXIF package (this includes the first two bytes representing the package length) // APP1 (ff e1) // // (Required, XMP package) APP1 (ff e1) // 2 bytes of length (2 + 29 + length of xmp package) // name space ("http://ns.adobe.com/xap/1.0/\0") // xmp // primary image (without the first two bytes (SOI) and without EXIF, may have other packages) // secondary image (the recovery map) // // (Required) primary image (without the first two bytes (SOI), may have other packages) // // (Required) secondary image (the recovery map) // // Metadata versions we are using: // ECMA TR-98 for JFIF marker Loading @@ -989,7 +898,6 @@ status_t RecoveryMap::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, jr_compressed_ptr dest) { if (compressed_jpeg_image == nullptr || compressed_recovery_map == nullptr || exif == nullptr || metadata == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; Loading @@ -1002,7 +910,7 @@ status_t RecoveryMap::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kSOI, 1, pos)); // Write EXIF { if (exif != nullptr) { const int length = 2 + exif->length; const uint8_t lengthH = ((length >> 8) & 0xff); const uint8_t lengthL = (length & 0xff); Loading Loading
libs/jpegrecoverymap/include/jpegrecoverymap/jpegdecoder.h +1 −5 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ public: */ void* getDecompressedImagePtr(); /* * Returns the decompressed raw image buffer size. This mgit ethod must be called only after * Returns the decompressed raw image buffer size. This method must be called only after * calling decompressImage(). */ size_t getDecompressedImageSize(); Loading Loading @@ -92,10 +92,6 @@ public: size_t* pWidth, size_t* pHeight, std::vector<uint8_t>* iccData, std::vector<uint8_t>* exifData); /* * Extracts EXIF package and updates the EXIF position / length without decoding the image. */ bool extractEXIF(const void* image, int length); private: bool decode(const void* image, int length, bool decodeToRGBA); Loading
libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h +8 −4 Original line number Diff line number Diff line Loading @@ -321,13 +321,17 @@ private: jr_compressed_ptr dest); /* * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image * and the compressed recovery map as input, and update the XMP metadata with the end of JPEG * marker, and append the compressed gian map after the JPEG. * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image, * the compressed recovery map and optionally the exif package as inputs, and generate the XMP * metadata, and finally append everything in the order of: * SOI, APP2(EXIF) (if EXIF is from outside), APP2(XMP), primary image, recovery map * Note that EXIF package is only available for encoding API-0 and API-1. For encoding API-2 and * API-3 this parameter is null, but the primary image in JPEG/R may still have EXIF as long as * the input JPEG has EXIF. * * @param compressed_jpeg_image compressed 8-bit JPEG image * @param compress_recovery_map compressed recover map * @param exif EXIF package * @param (nullable) exif EXIF package * @param metadata JPEG/R metadata to encode in XMP of the jpeg * @param dest compressed JPEGR image * @return NO_ERROR if calculation succeeds, error code if error occurs. Loading
libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h +0 −78 Original line number Diff line number Diff line Loading @@ -45,7 +45,6 @@ const size_t EXIF_J_R_ENTRY_LENGTH = 12; * @return status of succeed or error code. */ status_t Write(jr_compressed_ptr destination, const void* source, size_t length, int &position); status_t Write(jr_exif_ptr destination, const void* source, size_t length, int &position); /* Loading Loading @@ -105,83 +104,6 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* meta * @return XMP metadata in type of string */ std::string generateXmp(int secondary_image_length, jpegr_metadata& metadata); /* * Add J R entry to existing exif, or create a new one with J R entry if it's null. * EXIF syntax / change: * ori: * FF E1 - APP1 * 01 FC - size of APP1 (to be calculated) * ----------------------------------------------------- * 45 78 69 66 00 00 - Exif\0\0 "Exif header" * 49 49 2A 00 - TIFF Header * 08 00 00 00 - offset to the IFD (image file directory) * 06 00 - 6 entries * 00 01 - Width Tag * 03 00 - 'Short' type * 01 00 00 00 - 1 component * 00 05 00 00 - image with 0x500 *-------------------------------------------------------------------------- * new: * FF E1 - APP1 * 02 08 - new size, equals to old size + EXIF_J_R_ENTRY_LENGTH (12) *----------------------------------------------------- * 45 78 69 66 00 00 - Exif\0\0 "Exif header" * 49 49 2A 00 - TIFF Header * 08 00 00 00 - offset to the IFD (image file directory) * 07 00 - +1 entry * 4A 52 Custom ('J''R') Tag * 07 00 - Unknown type * 01 00 00 00 - 1 component * 00 00 00 00 - empty data * 00 01 - Width Tag * 03 00 - 'Short' type * 01 00 00 00 - 1 component * 00 05 00 00 - image with 0x500 */ status_t updateExif(jr_exif_ptr exif, jr_exif_ptr dest); /* * Modify offsets in EXIF in place. * * Each tag has the following structure: * * 00 01 - Tag * 03 00 - data format * 01 00 00 00 - number of components * 00 05 00 00 - value * * The value means offset if * (1) num_of_components * bytes_per_component > 4 bytes, or * (2) tag == 0x8769 (ExifOffset). * In both cases, the method will add EXIF_J_R_ENTRY_LENGTH (12) to the offsets. */ void updateExifOffsets(jr_exif_ptr exif, int pos, bool use_big_endian); void updateExifOffsets(jr_exif_ptr exif, int pos, int num_entry, bool use_big_endian); /* * Read data from the target position and target length in bytes; */ int readValue(uint8_t* data, int pos, int length, bool use_big_endian); /* * Returns the length of data format in bytes * * ---------------------------------------------------------------------------------------------- * | value | 1 | 2 | 3 | 4 | * | format | unsigned byte | ascii strings | unsigned short | unsigned long | * | bytes/component | 1 | 1 | 2 | 4 | * ---------------------------------------------------------------------------------------------- * | value | 5 | 6 | 7 | 8 | * | format |unsigned rational| signed byte | undefined | signed short | * | bytes/component | 8 | 1 | 1 | 2 | * ---------------------------------------------------------------------------------------------- * | value | 9 | 10 | 11 | 12 | * | format | signed long | signed rational | single float | double float | * | bytes/component | 4 | 8 | 4 | 8 | * ---------------------------------------------------------------------------------------------- */ int findFormatLengthInBytes(int data_format); } #endif //ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H
libs/jpegrecoverymap/jpegdecoder.cpp +0 −54 Original line number Diff line number Diff line Loading @@ -248,60 +248,6 @@ bool JpegDecoder::decode(const void* image, int length, bool decodeToRGBA) { return true; } // TODO (Fyodor/Dichen): merge this method with getCompressedImageParameters() since they have // similar functionality. Yet Dichen is not familiar with who's calling // getCompressedImageParameters(), looks like it's used by some pending CLs. bool JpegDecoder::extractEXIF(const void* image, int length) { 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, kAPP0Marker, 0xFFFF); jpeg_save_markers(&cinfo, kAPP1Marker, 0xFFFF); jpeg_save_markers(&cinfo, kAPP2Marker, 0xFFFF); cinfo.src = &mgr; jpeg_read_header(&cinfo, TRUE); bool exifAppears = false; size_t pos = 2; // position after SOI for (jpeg_marker_struct* marker = cinfo.marker_list; marker && !exifAppears; marker = marker->next) { pos += 4; pos += marker->original_length; if (marker->marker != kAPP1Marker) { continue; } const unsigned int len = marker->data_length; 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; mExifPos = pos - marker->original_length; } } jpeg_destroy_decompress(&cinfo); return true; } bool JpegDecoder::decompress(jpeg_decompress_struct* cinfo, const uint8_t* dest, bool isSingleChannel) { if (isSingleChannel) { Loading
libs/jpegrecoverymap/recoverymap.cpp +13 −105 Original line number Diff line number Diff line Loading @@ -175,18 +175,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jpeg.data = jpeg_encoder.getCompressedImagePtr(); jpeg.length = jpeg_encoder.getCompressedImageSize(); jpegr_exif_struct new_exif; if (exif == nullptr || exif->data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif->length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(exif, &new_exif)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, &new_exif, &metadata, dest)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -250,19 +239,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, jpeg.data = jpeg_encoder.getCompressedImagePtr(); jpeg.length = jpeg_encoder.getCompressedImageSize(); jpegr_exif_struct new_exif; if (exif == nullptr || exif->data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif->length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(exif, &new_exif)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, &new_exif, &metadata, dest)); JPEGR_CHECK(appendRecoveryMap(&jpeg, &compressed_map, exif, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -311,47 +288,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.data = compressed_map_data.get(); JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); // Extract EXIF from JPEG without decoding. JpegDecoder jpeg_decoder; if (!jpeg_decoder.extractEXIF(compressed_jpeg_image->data, compressed_jpeg_image->length)) { return ERROR_JPEGR_DECODE_ERROR; } // Update exif. jpegr_exif_struct exif; exif.data = nullptr; exif.length = 0; jpegr_compressed_struct new_jpeg_image; new_jpeg_image.data = nullptr; new_jpeg_image.length = 0; if (jpeg_decoder.getEXIFPos() != 0) { copyJpegWithoutExif(&new_jpeg_image, compressed_jpeg_image, jpeg_decoder.getEXIFPos(), jpeg_decoder.getEXIFSize()); exif.data = jpeg_decoder.getEXIFPtr(); exif.length = jpeg_decoder.getEXIFSize(); } jpegr_exif_struct new_exif; if (exif.data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif.length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(&exif, &new_exif)); JPEGR_CHECK(appendRecoveryMap( new_jpeg_image.data == nullptr ? compressed_jpeg_image : &new_jpeg_image, &compressed_map, &new_exif, &metadata, dest)); if (new_jpeg_image.data != nullptr) { free(new_jpeg_image.data); } JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -384,33 +321,6 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, uncompressed_yuv_420_image.height = jpeg_decoder.getDecompressedImageHeight(); uncompressed_yuv_420_image.colorGamut = compressed_jpeg_image->colorGamut; // Update exif. jpegr_exif_struct exif; exif.data = nullptr; exif.length = 0; jpegr_compressed_struct new_jpeg_image; new_jpeg_image.data = nullptr; new_jpeg_image.length = 0; if (jpeg_decoder.getEXIFPos() != 0) { copyJpegWithoutExif(&new_jpeg_image, compressed_jpeg_image, jpeg_decoder.getEXIFPos(), jpeg_decoder.getEXIFSize()); exif.data = jpeg_decoder.getEXIFPtr(); exif.length = jpeg_decoder.getEXIFSize(); } jpegr_exif_struct new_exif; if (exif.data == nullptr) { new_exif.length = PSEUDO_EXIF_PACKAGE_LENGTH; } else { new_exif.length = exif.length + EXIF_J_R_ENTRY_LENGTH; } new_exif.data = new uint8_t[new_exif.length]; std::unique_ptr<uint8_t[]> new_exif_data; new_exif_data.reset(reinterpret_cast<uint8_t*>(new_exif.data)); JPEGR_CHECK(updateExif(&exif, &new_exif)); if (uncompressed_p010_image->width != uncompressed_yuv_420_image.width || uncompressed_p010_image->height != uncompressed_yuv_420_image.height) { return ERROR_JPEGR_RESOLUTION_MISMATCH; Loading @@ -435,13 +345,7 @@ status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image, compressed_map.data = compressed_map_data.get(); JPEGR_CHECK(compressRecoveryMap(&map, &compressed_map)); JPEGR_CHECK(appendRecoveryMap( new_jpeg_image.data == nullptr ? compressed_jpeg_image : &new_jpeg_image, &compressed_map, &new_exif, &metadata, dest)); if (new_jpeg_image.data != nullptr) { free(new_jpeg_image.data); } JPEGR_CHECK(appendRecoveryMap(compressed_jpeg_image, &compressed_map, nullptr, &metadata, dest)); return NO_ERROR; } Loading Loading @@ -967,15 +871,20 @@ status_t RecoveryMap::extractRecoveryMap(jr_compressed_ptr compressed_jpegr_imag // JPEG/R structure: // SOI (ff d8) // // (Optional, only if EXIF package is from outside) // APP1 (ff e1) // 2 bytes of length (2 + length of exif package) // EXIF package (this includes the first two bytes representing the package length) // APP1 (ff e1) // // (Required, XMP package) APP1 (ff e1) // 2 bytes of length (2 + 29 + length of xmp package) // name space ("http://ns.adobe.com/xap/1.0/\0") // xmp // primary image (without the first two bytes (SOI) and without EXIF, may have other packages) // secondary image (the recovery map) // // (Required) primary image (without the first two bytes (SOI), may have other packages) // // (Required) secondary image (the recovery map) // // Metadata versions we are using: // ECMA TR-98 for JFIF marker Loading @@ -989,7 +898,6 @@ status_t RecoveryMap::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, jr_compressed_ptr dest) { if (compressed_jpeg_image == nullptr || compressed_recovery_map == nullptr || exif == nullptr || metadata == nullptr || dest == nullptr) { return ERROR_JPEGR_INVALID_NULL_PTR; Loading @@ -1002,7 +910,7 @@ status_t RecoveryMap::appendRecoveryMap(jr_compressed_ptr compressed_jpeg_image, JPEGR_CHECK(Write(dest, &photos_editing_formats::image_io::JpegMarker::kSOI, 1, pos)); // Write EXIF { if (exif != nullptr) { const int length = 2 + exif->length; const uint8_t lengthH = ((length >> 8) & 0xff); const uint8_t lengthL = (length & 0xff); Loading