Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginJPEG.cpp view on Meta::CPAN
FITAG *tag_exif = NULL;
FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif);
if(tag_exif) {
const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif);
// verify the identifying string
if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) {
// not an Exif profile
return FALSE;
}
if(NULL != tag_value) {
DWORD tag_length = FreeImage_GetTagLength(tag_exif);
BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE));
if(profile == NULL) return FALSE;
for(DWORD i = 0; i < tag_length; i += 65504L) {
unsigned length = MIN((long)(tag_length - i), 65504L);
memcpy(profile, tag_value + i, length);
jpeg_write_marker(cinfo, EXIF_MARKER, profile, length);
}
free(profile);
return TRUE;
}
}
return FALSE;
}
/**
Write thumbnail (JFXX segment, JPEG compressed)
*/
static BOOL
jpeg_write_jfxx(j_compress_ptr cinfo, FIBITMAP *dib) {
// get the thumbnail to be stored
FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib);
if(!thumbnail) {
return TRUE;
}
// check for a compatible output format
if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 8) && (FreeImage_GetBPP(thumbnail) != 24)) {
FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL);
return FALSE;
}
// stores the thumbnail as a baseline JPEG into a memory block
// return the memory block only if its size is within JFXX marker size limit!
FIMEMORY *stream = FreeImage_OpenMemory();
if(FreeImage_SaveToMemory(FIF_JPEG, thumbnail, stream, JPEG_BASELINE)) {
// check that the memory block size is within JFXX marker size limit
FreeImage_SeekMemory(stream, 0, SEEK_END);
const long eof = FreeImage_TellMemory(stream);
if(eof > MAX_JFXX_THUMB_SIZE) {
FreeImage_OutputMessageProc(s_format_id, "Warning: attached thumbnail is %d bytes larger than maximum supported size - Thumbnail saving aborted", eof - MAX_JFXX_THUMB_SIZE);
FreeImage_CloseMemory(stream);
return FALSE;
}
} else {
FreeImage_CloseMemory(stream);
return FALSE;
}
BYTE* thData = NULL;
DWORD thSize = 0;
FreeImage_AcquireMemory(stream, &thData, &thSize);
BYTE id_length = 5; //< "JFXX"
BYTE type = JFXX_TYPE_JPEG;
DWORD totalsize = id_length + sizeof(type) + thSize;
jpeg_write_m_header(cinfo, JPEG_APP0, totalsize);
jpeg_write_m_byte(cinfo, 'J');
jpeg_write_m_byte(cinfo, 'F');
jpeg_write_m_byte(cinfo, 'X');
jpeg_write_m_byte(cinfo, 'X');
jpeg_write_m_byte(cinfo, '\0');
jpeg_write_m_byte(cinfo, type);
// write thumbnail to destination.
// We "cram it straight into the data destination module", because write_m_byte is slow
freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
BYTE* & out = dest->pub.next_output_byte;
size_t & bufRemain = dest->pub.free_in_buffer;
const BYTE *thData_end = thData + thSize;
while(thData < thData_end) {
*(out)++ = *(thData)++;
if (--bufRemain == 0) {
// buffer full - flush
if (!dest->pub.empty_output_buffer(cinfo)) {
break;
}
}
}
FreeImage_CloseMemory(stream);
return TRUE;
}
/**
Write JPEG special markers
*/
static BOOL
write_markers(j_compress_ptr cinfo, FIBITMAP *dib) {
// write thumbnail as a JFXX marker
jpeg_write_jfxx(cinfo, dib);
( run in 1.215 second using v1.01-cache-2.11-cpan-4991d5b9bd9 )