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 )