Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/Metadata/Exif.cpp  view on Meta::CPAN

				break;
			case TAG_JPEG_INTERCHANGE_FORMAT_LENGTH:
				// Tiff JPEGInterchangeFormatLength Tag
				thSize = offset;
				break;
			// ### X and Y Resolution ignored, orientation ignored
			case TAG_X_RESOLUTION:		// XResolution
			case TAG_Y_RESOLUTION:		// YResolution
			case TAG_RESOLUTION_UNIT:	// ResolutionUnit
			case TAG_ORIENTATION:		// Orientation
				break;
			default:
				break;
		}
	}
	
	if(/*thCompression != 6 ||*/ thOffset == 0 || thSize == 0) {
		return TRUE;
	}
	
	if(thOffset + thSize > dwLength) {
		return TRUE;
	}
	
	// load the thumbnail

	const BYTE *thLocation = tiffp + thOffset;
	
	FIMEMORY* hmem = FreeImage_OpenMemory(const_cast<BYTE*>(thLocation), thSize);
	FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem);
	FreeImage_CloseMemory(hmem);
	
	// store the thumbnail
	FreeImage_SetThumbnail(dib, thumbnail);
	// then delete it
	FreeImage_Unload(thumbnail);

	return TRUE;
}

// --------------------------------------------------------------------------

/**
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;
}

// ==========================================================
// Exif JPEG helper routines
// ==========================================================

/**
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_raw(FIBITMAP *dib, const BYTE *profile, unsigned length) {
    // marker identifying string for Exif = "Exif\0\0"
    BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };

	// verify the identifying string
	if(memcmp(exif_signature, profile, sizeof(exif_signature)) != 0) {
		// not an Exif profile
		return FALSE;
	}

	// create a tag
	FITAG *tag = FreeImage_CreateTag();
	if(tag) {
		FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName);
		FreeImage_SetTagLength(tag, (DWORD)length);
		FreeImage_SetTagCount(tag, (DWORD)length);
		FreeImage_SetTagType(tag, FIDT_BYTE);
		FreeImage_SetTagValue(tag, profile);

		// store the tag
		FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag);

		// destroy the tag
		FreeImage_DeleteTag(tag);

		return TRUE;
	}

	return FALSE;
}

// ==========================================================
// Exif JPEG-XR helper routines
// ==========================================================

/**
Read and decode JPEG-XR Exif IFD
@param dib Input FIBITMAP
@param profile Pointer to the Exif marker
@param length Exif marker 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_profile(FIBITMAP *dib, const BYTE *profile, unsigned length, unsigned file_offset) {
	// assume Little Endian order
	BOOL bBigEndian = FALSE;
	
	// process Exif specific IFD
	return jpeg_read_exif_dir(dib, profile, 0, length, file_offset, bBigEndian, TagLib::EXIF_EXIF);
}

/**
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;
	



( run in 1.186 second using v1.01-cache-2.11-cpan-119454b85a5 )