Loading include/input/PrintTools.h +31 −1 Original line number Diff line number Diff line Loading @@ -16,18 +16,35 @@ #pragma once #include <bitset> #include <map> #include <optional> #include <set> #include <string> #include <vector> namespace android { template <size_t N> std::string bitsetToString(const std::bitset<N>& bitset) { return bitset.to_string(); } template <typename T> inline std::string constToString(const T& v) { return std::to_string(v); } template <> inline std::string constToString(const bool& value) { return value ? "true" : "false"; } template <> inline std::string constToString(const std::vector<bool>::reference& value) { return value ? "true" : "false"; } inline std::string constToString(const std::string& s) { return s; } Loading Loading @@ -70,6 +87,19 @@ std::string dumpMap(const std::map<K, V>& map, std::string (*keyToString)(const return out; } /** * Convert a vector to a string. The values of the vector should be of a type supported by * constToString. */ template <typename T> std::string dumpVector(std::vector<T> values) { std::string dump = constToString(values[0]); for (size_t i = 1; i < values.size(); i++) { dump += ", " + constToString(values[i]); } return dump; } const char* toString(bool value); /** Loading libs/binder/TEST_MAPPING +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,9 @@ { "name": "memunreachable_binder_test" }, { "name": "resolv_integration_test" }, { "name": "libbinderthreadstateutils_test" }, Loading libs/binder/ndk/parcel.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -700,6 +700,9 @@ binder_status_t AParcel_marshal(const AParcel* parcel, uint8_t* buffer, size_t s return STATUS_BAD_VALUE; } const uint8_t* internalBuffer = parcel->get()->data(); if (internalBuffer == nullptr) { return STATUS_UNEXPECTED_NULL; } memcpy(buffer, internalBuffer + start, len); return STATUS_OK; } Loading libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h +105 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #include <jpegrecoverymap/recoverymap.h> #include <sstream> #include <stdint.h> #include <string> Loading @@ -26,6 +28,26 @@ namespace android::recoverymap { struct jpegr_metadata; // If the EXIF package doesn't exist in the input JPEG, we'll create one with one entry // where the length is represented by this value. const size_t PSEUDO_EXIF_PACKAGE_LENGTH = 28; // If the EXIF package exists in the input JPEG, we'll add an "JR" entry where the length is // represented by this value. const size_t EXIF_J_R_ENTRY_LENGTH = 12; /* * Helper function used for writing data to destination. * * @param destination destination of the data to be written. * @param source source of data being written. * @param length length of the data to be written. * @param position cursor in desitination where the data is to be written. * @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); /* * Parses XMP packet and fills metadata with data from XMP * Loading Loading @@ -56,8 +78,8 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* meta * <rdf:Seq> * <rdf:li> * <GContainer:Item * Item:Semantic="Primary" * Item:Mime="image/jpeg" * GContainer:ItemSemantic="Primary" * GContainer:ItemMime="image/jpeg" * RecoveryMap:Version=”1” * RecoveryMap:RangeScalingFactor=”1.25” * RecoveryMap:TransferFunction=”2”/> Loading @@ -68,9 +90,9 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* meta * </rdf:li> * <rdf:li> * <GContainer:Item * Item:Semantic="RecoveryMap" * Item:Mime="image/jpeg" * Item:Length="1000"/> * GContainer:ItemSemantic="RecoveryMap" * GContainer:ItemMime="image/jpeg" * GContainer:ItemLength="1000"/> * </rdf:li> * </rdf:Seq> * </GContainer:Directory> Loading @@ -83,6 +105,83 @@ 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/recoverymap.cpp +0 −129 Original line number Diff line number Diff line Loading @@ -93,135 +93,6 @@ int GetCPUCoreCount() { return cpuCoreCount; } /* * Helper function used for writing data to destination. * * @param destination destination of the data to be written. * @param source source of data being written. * @param length length of the data to be written. * @param position cursor in desitination where the data is to be written. * @return status of succeed or error code. */ status_t Write(jr_compressed_ptr destination, const void* source, size_t length, int &position) { if (position + length > destination->maxLength) { return ERROR_JPEGR_BUFFER_TOO_SMALL; } memcpy((uint8_t*)destination->data + sizeof(uint8_t) * position, source, length); position += length; return NO_ERROR; } status_t Write(jr_exif_ptr destination, const void* source, size_t length, int &position) { memcpy((uint8_t*)destination->data + sizeof(uint8_t) * position, source, length); position += length; return NO_ERROR; } // If the EXIF package doesn't exist in the input JPEG, we'll create one with one entry // where the length is represented by this value. const size_t PSEUDO_EXIF_PACKAGE_LENGTH = 28; // If the EXIF package exists in the input JPEG, we'll add an "JR" entry where the length is // represented by this value. const size_t EXIF_J_R_ENTRY_LENGTH = 12; /* * Helper function * 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 - one entry * 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 - one element * 00 00 00 00 - empty data * 00 01 - Width Tag * 03 00 - 'Short' type * 01 00 00 00 - one entry * 00 05 00 00 - image with 0x500 */ status_t updateExif(jr_exif_ptr exif, jr_exif_ptr dest) { if (exif == nullptr || exif->data == nullptr) { uint8_t data[PSEUDO_EXIF_PACKAGE_LENGTH] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4A, 0x52, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; int pos = 0; Write(dest, data, PSEUDO_EXIF_PACKAGE_LENGTH, pos); return NO_ERROR; } int num_entry = 0; uint8_t num_entry_low = 0; uint8_t num_entry_high = 0; bool use_big_endian = false; if (reinterpret_cast<uint16_t*>(exif->data)[3] == 0x4949) { num_entry_low = reinterpret_cast<uint8_t*>(exif->data)[14]; num_entry_high = reinterpret_cast<uint8_t*>(exif->data)[15]; } else if (reinterpret_cast<uint16_t*>(exif->data)[3] == 0x4d4d) { use_big_endian = true; num_entry_high = reinterpret_cast<uint8_t*>(exif->data)[14]; num_entry_low = reinterpret_cast<uint8_t*>(exif->data)[15]; } else { return ERROR_JPEGR_METADATA_ERROR; } num_entry = (num_entry_high << 8) | num_entry_low; num_entry += 1; num_entry_low = num_entry & 0xff; num_entry_high = (num_entry << 8) & 0xff; int pos = 0; Write(dest, (uint8_t*)exif->data, 14, pos); if (use_big_endian) { Write(dest, &num_entry_high, 1, pos); Write(dest, &num_entry_low, 1, pos); uint8_t data[EXIF_J_R_ENTRY_LENGTH] = { 0x4A, 0x52, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; Write(dest, data, EXIF_J_R_ENTRY_LENGTH, pos); } else { Write(dest, &num_entry_low, 1, pos); Write(dest, &num_entry_high, 1, pos); uint8_t data[EXIF_J_R_ENTRY_LENGTH] = { 0x4A, 0x52, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; Write(dest, data, EXIF_J_R_ENTRY_LENGTH, pos); } Write(dest, (uint8_t*)exif->data + 16, exif->length - 16, pos); return NO_ERROR; } /* * Helper function copies the JPEG image from without EXIF. * Loading Loading
include/input/PrintTools.h +31 −1 Original line number Diff line number Diff line Loading @@ -16,18 +16,35 @@ #pragma once #include <bitset> #include <map> #include <optional> #include <set> #include <string> #include <vector> namespace android { template <size_t N> std::string bitsetToString(const std::bitset<N>& bitset) { return bitset.to_string(); } template <typename T> inline std::string constToString(const T& v) { return std::to_string(v); } template <> inline std::string constToString(const bool& value) { return value ? "true" : "false"; } template <> inline std::string constToString(const std::vector<bool>::reference& value) { return value ? "true" : "false"; } inline std::string constToString(const std::string& s) { return s; } Loading Loading @@ -70,6 +87,19 @@ std::string dumpMap(const std::map<K, V>& map, std::string (*keyToString)(const return out; } /** * Convert a vector to a string. The values of the vector should be of a type supported by * constToString. */ template <typename T> std::string dumpVector(std::vector<T> values) { std::string dump = constToString(values[0]); for (size_t i = 1; i < values.size(); i++) { dump += ", " + constToString(values[i]); } return dump; } const char* toString(bool value); /** Loading
libs/binder/TEST_MAPPING +3 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,9 @@ { "name": "memunreachable_binder_test" }, { "name": "resolv_integration_test" }, { "name": "libbinderthreadstateutils_test" }, Loading
libs/binder/ndk/parcel.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -700,6 +700,9 @@ binder_status_t AParcel_marshal(const AParcel* parcel, uint8_t* buffer, size_t s return STATUS_BAD_VALUE; } const uint8_t* internalBuffer = parcel->get()->data(); if (internalBuffer == nullptr) { return STATUS_UNEXPECTED_NULL; } memcpy(buffer, internalBuffer + start, len); return STATUS_OK; } Loading
libs/jpegrecoverymap/include/jpegrecoverymap/recoverymaputils.h +105 −6 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #ifndef ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #define ANDROID_JPEGRECOVERYMAP_RECOVERYMAPUTILS_H #include <jpegrecoverymap/recoverymap.h> #include <sstream> #include <stdint.h> #include <string> Loading @@ -26,6 +28,26 @@ namespace android::recoverymap { struct jpegr_metadata; // If the EXIF package doesn't exist in the input JPEG, we'll create one with one entry // where the length is represented by this value. const size_t PSEUDO_EXIF_PACKAGE_LENGTH = 28; // If the EXIF package exists in the input JPEG, we'll add an "JR" entry where the length is // represented by this value. const size_t EXIF_J_R_ENTRY_LENGTH = 12; /* * Helper function used for writing data to destination. * * @param destination destination of the data to be written. * @param source source of data being written. * @param length length of the data to be written. * @param position cursor in desitination where the data is to be written. * @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); /* * Parses XMP packet and fills metadata with data from XMP * Loading Loading @@ -56,8 +78,8 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* meta * <rdf:Seq> * <rdf:li> * <GContainer:Item * Item:Semantic="Primary" * Item:Mime="image/jpeg" * GContainer:ItemSemantic="Primary" * GContainer:ItemMime="image/jpeg" * RecoveryMap:Version=”1” * RecoveryMap:RangeScalingFactor=”1.25” * RecoveryMap:TransferFunction=”2”/> Loading @@ -68,9 +90,9 @@ bool getMetadataFromXMP(uint8_t* xmp_data, size_t xmp_size, jpegr_metadata* meta * </rdf:li> * <rdf:li> * <GContainer:Item * Item:Semantic="RecoveryMap" * Item:Mime="image/jpeg" * Item:Length="1000"/> * GContainer:ItemSemantic="RecoveryMap" * GContainer:ItemMime="image/jpeg" * GContainer:ItemLength="1000"/> * </rdf:li> * </rdf:Seq> * </GContainer:Directory> Loading @@ -83,6 +105,83 @@ 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/recoverymap.cpp +0 −129 Original line number Diff line number Diff line Loading @@ -93,135 +93,6 @@ int GetCPUCoreCount() { return cpuCoreCount; } /* * Helper function used for writing data to destination. * * @param destination destination of the data to be written. * @param source source of data being written. * @param length length of the data to be written. * @param position cursor in desitination where the data is to be written. * @return status of succeed or error code. */ status_t Write(jr_compressed_ptr destination, const void* source, size_t length, int &position) { if (position + length > destination->maxLength) { return ERROR_JPEGR_BUFFER_TOO_SMALL; } memcpy((uint8_t*)destination->data + sizeof(uint8_t) * position, source, length); position += length; return NO_ERROR; } status_t Write(jr_exif_ptr destination, const void* source, size_t length, int &position) { memcpy((uint8_t*)destination->data + sizeof(uint8_t) * position, source, length); position += length; return NO_ERROR; } // If the EXIF package doesn't exist in the input JPEG, we'll create one with one entry // where the length is represented by this value. const size_t PSEUDO_EXIF_PACKAGE_LENGTH = 28; // If the EXIF package exists in the input JPEG, we'll add an "JR" entry where the length is // represented by this value. const size_t EXIF_J_R_ENTRY_LENGTH = 12; /* * Helper function * 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 - one entry * 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 - one element * 00 00 00 00 - empty data * 00 01 - Width Tag * 03 00 - 'Short' type * 01 00 00 00 - one entry * 00 05 00 00 - image with 0x500 */ status_t updateExif(jr_exif_ptr exif, jr_exif_ptr dest) { if (exif == nullptr || exif->data == nullptr) { uint8_t data[PSEUDO_EXIF_PACKAGE_LENGTH] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x49, 0x49, 0x2A, 0x00, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00, 0x4A, 0x52, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; int pos = 0; Write(dest, data, PSEUDO_EXIF_PACKAGE_LENGTH, pos); return NO_ERROR; } int num_entry = 0; uint8_t num_entry_low = 0; uint8_t num_entry_high = 0; bool use_big_endian = false; if (reinterpret_cast<uint16_t*>(exif->data)[3] == 0x4949) { num_entry_low = reinterpret_cast<uint8_t*>(exif->data)[14]; num_entry_high = reinterpret_cast<uint8_t*>(exif->data)[15]; } else if (reinterpret_cast<uint16_t*>(exif->data)[3] == 0x4d4d) { use_big_endian = true; num_entry_high = reinterpret_cast<uint8_t*>(exif->data)[14]; num_entry_low = reinterpret_cast<uint8_t*>(exif->data)[15]; } else { return ERROR_JPEGR_METADATA_ERROR; } num_entry = (num_entry_high << 8) | num_entry_low; num_entry += 1; num_entry_low = num_entry & 0xff; num_entry_high = (num_entry << 8) & 0xff; int pos = 0; Write(dest, (uint8_t*)exif->data, 14, pos); if (use_big_endian) { Write(dest, &num_entry_high, 1, pos); Write(dest, &num_entry_low, 1, pos); uint8_t data[EXIF_J_R_ENTRY_LENGTH] = { 0x4A, 0x52, 0x07, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; Write(dest, data, EXIF_J_R_ENTRY_LENGTH, pos); } else { Write(dest, &num_entry_low, 1, pos); Write(dest, &num_entry_high, 1, pos); uint8_t data[EXIF_J_R_ENTRY_LENGTH] = { 0x4A, 0x52, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00}; Write(dest, data, EXIF_J_R_ENTRY_LENGTH, pos); } Write(dest, (uint8_t*)exif->data + 16, exif->length - 16, pos); return NO_ERROR; } /* * Helper function copies the JPEG image from without EXIF. * Loading