/** Read and decode JPEG-XR Exif-GPS IFD @param dib Input FIBITMAP @param profile Pointer to the Exif-GPS profile @param length Exif-GPS profile length @param file_offset Reference offset in the original file of each tag value whose length is > 4 @return Returns TRUE if successful, FALSE otherwise */ BOOL jpegxr_read_exif_gps_profile(FIBITMAP *dib, const BYTE *profile, unsigned length, unsigned file_offset) { // assume Little Endian order BOOL bBigEndian = FALSE; // process Exif GPS IFD return jpeg_read_exif_dir(dib, profile, 0, length, file_offset, bBigEndian, TagLib::EXIF_GPS); }
/** Read JPEG_APP1 marker (Exif profile) @param dib Input FIBITMAP @param dataptr Pointer to the APP1 marker @param datalen APP1 marker length @return Returns TRUE if successful, FALSE otherwise */ BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { // marker identifying string for Exif = "Exif\0\0" BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; BYTE lsb_first[4] = { 0x49, 0x49, 0x2A, 0x00 }; // Intel order BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Motorola order unsigned int length = datalen; BYTE *profile = (BYTE*)dataptr; // verify the identifying string if(memcmp(exif_signature, profile, sizeof(exif_signature)) == 0) { // Exif profile profile += sizeof(exif_signature); length -= sizeof(exif_signature); // check the endianess order BOOL bMotorolaOrder = TRUE; if(memcmp(profile, lsb_first, sizeof(lsb_first)) == 0) { // Exif section in Intel order bMotorolaOrder = FALSE; } else { if(memcmp(profile, msb_first, sizeof(msb_first)) == 0) { // Exif section in Motorola order bMotorolaOrder = TRUE; } else { // Invalid Exif alignment marker return FALSE; } } // this is the offset to the first IFD unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4); if (first_offset < 8 || first_offset > 16) { // This is usually set to 8 // but PENTAX Optio 230 has it set differently, and uses it as offset. FreeImage_OutputMessageProc(FIF_JPEG, "Exif: Suspicious offset of first IFD value"); return FALSE; } // process Exif directories return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder); } return FALSE; }
/** Read and decode JPEG_APP1 marker (Exif profile) @param dib Input FIBITMAP @param dataptr Pointer to the APP1 marker @param datalen APP1 marker length @return Returns TRUE if successful, FALSE otherwise */ BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) { // marker identifying string for Exif = "Exif\0\0" BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; BYTE lsb_first[4] = { 0x49, 0x49, 0x2A, 0x00 }; // Intel order BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Motorola order unsigned int length = datalen; BYTE *profile = (BYTE*)dataptr; // verify the identifying string if(memcmp(exif_signature, profile, sizeof(exif_signature)) == 0) { // Exif profile - TIFF header with 2 IFDs. 0th - the image attributes, 1st - may be used for thumbnail profile += sizeof(exif_signature); length -= sizeof(exif_signature); // read the TIFF header (8 bytes) // check the endianess order BOOL bMotorolaOrder = TRUE; if(memcmp(profile, lsb_first, sizeof(lsb_first)) == 0) { // Exif section in Intel order bMotorolaOrder = FALSE; } else { if(memcmp(profile, msb_first, sizeof(msb_first)) == 0) { // Exif section in Motorola order bMotorolaOrder = TRUE; } else { // Invalid Exif alignment marker return FALSE; } } // this is the offset to the first IFD (Image File Directory) unsigned long first_offset = ReadUint32(bMotorolaOrder, profile + 4); if (first_offset > length) { // bad Exif data return FALSE; } /* Note: as FreeImage 3.14.0, this test is no longer needed for images with similar suspicious offset => tested with Pentax Optio 230, FujiFilm SP-2500 and Canon EOS 300D if (first_offset < 8 || first_offset > 16) { // This is usually set to 8 // but PENTAX Optio 230 has it set differently, and uses it as offset. FreeImage_OutputMessageProc(FIF_JPEG, "Exif: Suspicious offset of first IFD value"); return FALSE; } */ // process Exif directories return jpeg_read_exif_dir(dib, profile, first_offset, length, bMotorolaOrder); } return FALSE; }
/** Read and decode JPEG_APP1 marker (Exif profile) @param dib Input FIBITMAP @param data Pointer to the APP1 marker @param length APP1 marker length @return Returns TRUE if successful, FALSE otherwise */ BOOL jpeg_read_exif_profile(FIBITMAP *dib, const BYTE *data, unsigned length) { // marker identifying string for Exif = "Exif\0\0" BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; BYTE lsb_first[4] = { 0x49, 0x49, 0x2A, 0x00 }; // Classic TIFF signature - little-endian order BYTE msb_first[4] = { 0x4D, 0x4D, 0x00, 0x2A }; // Classic TIFF signature - big-endian order // profile size is up to 32-bit DWORD dwProfileLength = (DWORD)length; BYTE *pbProfile = (BYTE*)data; // verify the identifying string if(memcmp(exif_signature, pbProfile, sizeof(exif_signature)) == 0) { // This is an Exif profile // should contain a TIFF header with up to 2 IFDs (IFD stands for 'Image File Directory') // 0th IFD : the image attributes, 1st IFD : may be used for thumbnail pbProfile += sizeof(exif_signature); dwProfileLength -= sizeof(exif_signature); // read the TIFF header (8 bytes) // check the endianess order BOOL bBigEndian = TRUE; if(memcmp(pbProfile, lsb_first, sizeof(lsb_first)) == 0) { // Exif section is in little-endian order bBigEndian = FALSE; } else { if(memcmp(pbProfile, msb_first, sizeof(msb_first)) == 0) { // Exif section is in big-endian order bBigEndian = TRUE; } else { // Invalid Exif alignment marker return FALSE; } } // this is the offset to the first IFD (Image File Directory) DWORD dwFirstOffset = ReadUint32(bBigEndian, pbProfile + 4); if (dwFirstOffset > dwProfileLength) { // bad Exif data return FALSE; } /* Note: as FreeImage 3.14.0, this test is no longer needed for images with similar suspicious offset => tested with Pentax Optio 230, FujiFilm SP-2500 and Canon EOS 300D if (dwFirstOffset < 8 || dwFirstOffset > 16) { // This is usually set to 8 // but PENTAX Optio 230 has it set differently, and uses it as offset. FreeImage_OutputMessageProc(FIF_JPEG, "Exif: Suspicious offset of first IFD value"); return FALSE; } */ // process Exif directories, starting with Exif-TIFF IFD return jpeg_read_exif_dir(dib, pbProfile, dwFirstOffset, dwProfileLength, 0, bBigEndian, TagLib::EXIF_MAIN); } return FALSE; }