Alien-FreeImage

 view release on metacpan or  search on metacpan

src/Source/FreeImage/PluginPNG.cpp  view on Meta::CPAN

// Metadata routines
// ==========================================================

static BOOL 
ReadMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
	// XMP keyword
	const char *g_png_xmp_keyword = "XML:com.adobe.xmp";

	FITAG *tag = NULL;
	png_textp text_ptr = NULL;
	png_timep mod_time = NULL;
	int num_text = 0;

	// iTXt/tEXt/zTXt chuncks
	if(png_get_text(png_ptr, info_ptr, &text_ptr, &num_text) > 0) {
		for(int i = 0; i < num_text; i++) {
			// create a tag
			tag = FreeImage_CreateTag();
			if(!tag) return FALSE;

			DWORD tag_length = (DWORD) MAX(text_ptr[i].text_length, text_ptr[i].itxt_length);

			FreeImage_SetTagLength(tag, tag_length);
			FreeImage_SetTagCount(tag, tag_length);
			FreeImage_SetTagType(tag, FIDT_ASCII);
			FreeImage_SetTagValue(tag, text_ptr[i].text);

			if(strcmp(text_ptr[i].key, g_png_xmp_keyword) == 0) {
				// store the tag as XMP
				FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
				FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
			} else {
				// store the tag as a comment
				FreeImage_SetTagKey(tag, text_ptr[i].key);
				FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
			}
			
			// destroy the tag
			FreeImage_DeleteTag(tag);
		}
	}

	// timestamp chunk
	if(png_get_tIME(png_ptr, info_ptr, &mod_time)) {
		char timestamp[32];
		// create a tag
		tag = FreeImage_CreateTag();
		if(!tag) return FALSE;

		// convert as 'yyyy:MM:dd hh:mm:ss'
		sprintf(timestamp, "%4d:%02d:%02d %2d:%02d:%02d", mod_time->year, mod_time->month, mod_time->day, mod_time->hour, mod_time->minute, mod_time->second);

		DWORD tag_length = (DWORD)strlen(timestamp) + 1;
		FreeImage_SetTagLength(tag, tag_length);
		FreeImage_SetTagCount(tag, tag_length);
		FreeImage_SetTagType(tag, FIDT_ASCII);
		FreeImage_SetTagID(tag, TAG_DATETIME);
		FreeImage_SetTagValue(tag, timestamp);

		// store the tag as Exif-TIFF
		FreeImage_SetTagKey(tag, "DateTime");
		FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, FreeImage_GetTagKey(tag), tag);

		// destroy the tag
		FreeImage_DeleteTag(tag);
	}

	return TRUE;
}

static BOOL 
WriteMetadata(png_structp png_ptr, png_infop info_ptr, FIBITMAP *dib) {
	// XMP keyword
	const char *g_png_xmp_keyword = "XML:com.adobe.xmp";

	FITAG *tag = NULL;
	FIMETADATA *mdhandle = NULL;
	BOOL bResult = TRUE;

	png_text text_metadata;
	png_time mod_time;

	// set the 'Comments' metadata as iTXt chuncks

	mdhandle = FreeImage_FindFirstMetadata(FIMD_COMMENTS, dib, &tag);

	if(mdhandle) {
		do {
			memset(&text_metadata, 0, sizeof(png_text));
			text_metadata.compression = 1;							// iTXt, none
			text_metadata.key = (char*)FreeImage_GetTagKey(tag);	// keyword, 1-79 character description of "text"
			text_metadata.text = (char*)FreeImage_GetTagValue(tag);	// comment, may be an empty string (ie "")
			text_metadata.text_length = FreeImage_GetTagLength(tag);// length of the text string
			text_metadata.itxt_length = FreeImage_GetTagLength(tag);// length of the itxt string
			text_metadata.lang = 0;		 // language code, 0-79 characters or a NULL pointer
			text_metadata.lang_key = 0;	 // keyword translated UTF-8 string, 0 or more chars or a NULL pointer

			// set the tag 
			png_set_text(png_ptr, info_ptr, &text_metadata, 1);

		} while(FreeImage_FindNextMetadata(mdhandle, &tag));

		FreeImage_FindCloseMetadata(mdhandle);
		bResult &= TRUE;
	}

	// set the 'XMP' metadata as iTXt chuncks
	tag = NULL;
	FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag);
	if(tag && FreeImage_GetTagLength(tag)) {
		memset(&text_metadata, 0, sizeof(png_text));
		text_metadata.compression = 1;							// iTXt, none
		text_metadata.key = (char*)g_png_xmp_keyword;			// keyword, 1-79 character description of "text"
		text_metadata.text = (char*)FreeImage_GetTagValue(tag);	// comment, may be an empty string (ie "")
		text_metadata.text_length = FreeImage_GetTagLength(tag);// length of the text string
		text_metadata.itxt_length = FreeImage_GetTagLength(tag);// length of the itxt string
		text_metadata.lang = 0;		 // language code, 0-79 characters or a NULL pointer
		text_metadata.lang_key = 0;	 // keyword translated UTF-8 string, 0 or more chars or a NULL pointer

		// set the tag 
		png_set_text(png_ptr, info_ptr, &text_metadata, 1);
		bResult &= TRUE;
	}

	// set the Exif-TIFF 'DateTime' metadata as a tIME chunk
	tag = NULL;
	FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, "DateTime", &tag);
	if(tag && FreeImage_GetTagLength(tag)) {
		int year, month, day, hour, minute, second;
		const char *value = (char*)FreeImage_GetTagValue(tag);
		if(sscanf(value, "%4d:%02d:%02d %2d:%02d:%02d", &year, &month, &day, &hour, &minute, &second) == 6) {
			mod_time.year	= (png_uint_16)year;
			mod_time.month	= (png_byte)month;
			mod_time.day	= (png_byte)day;
			mod_time.hour	= (png_byte)hour;
			mod_time.minute	= (png_byte)minute;
			mod_time.second	= (png_byte)second;
			png_set_tIME (png_ptr, info_ptr, &mod_time);
		}
	}

	return bResult;
}

// ==========================================================
// Plugin Interface
// ==========================================================

static int s_format_id;

// ==========================================================
// Plugin Implementation
// ==========================================================

static const char * DLL_CALLCONV
Format() {
	return "PNG";
}

static const char * DLL_CALLCONV
Description() {
	return "Portable Network Graphics";
}

static const char * DLL_CALLCONV
Extension() {
	return "png";
}

static const char * DLL_CALLCONV
RegExpr() {
	return "^.PNG\r";
}

static const char * DLL_CALLCONV
MimeType() {
	return "image/png";
}

static BOOL DLL_CALLCONV
Validate(FreeImageIO *io, fi_handle handle) {
	BYTE png_signature[8] = { 137, 80, 78, 71, 13, 10, 26, 10 };
	BYTE signature[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };

	io->read_proc(&signature, 1, 8, handle);

	return (memcmp(png_signature, signature, 8) == 0);



( run in 0.805 second using v1.01-cache-2.11-cpan-5623c5533a1 )