/** Write JPEG_APPD marker (IPTC or Adobe Photoshop profile) @return Returns TRUE if successful, FALSE otherwise */ static BOOL jpeg_write_iptc_profile(j_compress_ptr cinfo, FIBITMAP *dib) { //const char *ps_header = "Photoshop 3.0\x08BIM\x04\x04\x0\x0\x0\x0"; const unsigned tag_length = 26; #ifndef MINIMAL_FREEIMAGE_CODEC if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) { BYTE *profile = NULL; unsigned profile_size = 0; // create a binary profile if(write_iptc_profile(dib, &profile, &profile_size)) { // write the profile for(long i = 0; i < (long)profile_size; i += 65517L) { unsigned length = MIN((long)profile_size - i, 65517L); unsigned roundup = length & 0x01; // needed for Photoshop BYTE *iptc_profile = (BYTE*)malloc(length + roundup + tag_length); if(iptc_profile == NULL) break; // Photoshop identification string memcpy(&iptc_profile[0], "Photoshop 3.0\x0", 14); // 8BIM segment type memcpy(&iptc_profile[14], "8BIM\x04\x04\x0\x0\x0\x0", 10); // segment size iptc_profile[24] = (BYTE)(length >> 8); iptc_profile[25] = (BYTE)(length & 0xFF); // segment data memcpy(&iptc_profile[tag_length], &profile[i], length); if(roundup) iptc_profile[length + tag_length] = 0; jpeg_write_marker(cinfo, IPTC_MARKER, iptc_profile, length + roundup + tag_length); free(iptc_profile); } // release profile free(profile); return TRUE; } } #endif return FALSE; }
/** Write ICC, XMP, Exif, Exif-GPS, IPTC, descriptive (i.e. Exif-TIFF) metadata */ static ERR WriteMetadata(PKImageEncode *pIE, FIBITMAP *dib) { ERR error_code = 0; // error code as returned by the interface BYTE *profile = NULL; unsigned profile_size = 0; try { // write ICC profile { FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib); if(iccProfile->data) { error_code = pIE->SetColorContext(pIE, (U8*)iccProfile->data, iccProfile->size); JXR_CHECK(error_code); } } // write descriptive metadata if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib)) { error_code = WriteDescriptiveMetadata(pIE, dib); JXR_CHECK(error_code); } // write IPTC metadata if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) { // create a binary profile if(write_iptc_profile(dib, &profile, &profile_size)) { // write the profile error_code = PKImageEncode_SetIPTCNAAMetadata_WMP(pIE, profile, profile_size); JXR_CHECK(error_code); // release profile free(profile); profile = NULL; } } // write XMP metadata { FITAG *tag_xmp = NULL; if(FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp)) { error_code = PKImageEncode_SetXMPMetadata_WMP(pIE, (BYTE*)FreeImage_GetTagValue(tag_xmp), FreeImage_GetTagLength(tag_xmp)); JXR_CHECK(error_code); } } // write Exif metadata { if(tiff_get_ifd_profile(dib, FIMD_EXIF_EXIF, &profile, &profile_size)) { error_code = PKImageEncode_SetEXIFMetadata_WMP(pIE, profile, profile_size); JXR_CHECK(error_code); // release profile free(profile); profile = NULL; } } // write Exif GPS metadata { if(tiff_get_ifd_profile(dib, FIMD_EXIF_GPS, &profile, &profile_size)) { error_code = PKImageEncode_SetGPSInfoMetadata_WMP(pIE, profile, profile_size); JXR_CHECK(error_code); // release profile free(profile); profile = NULL; } } return WMP_errSuccess; } catch(...) { free(profile); return error_code; } }