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 )