Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginWebP.cpp view on Meta::CPAN
throw FI_MSG_ERROR_PARSING;
}
// fill the dib with the decoded data
const BYTE *src_bitmap = output_buffer->u.RGBA.rgba;
const unsigned src_pitch = (unsigned)output_buffer->u.RGBA.stride;
switch(bpp) {
case 24:
for(unsigned y = 0; y < height; y++) {
const BYTE *src_bits = src_bitmap + y * src_pitch;
BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, height-1-y);
for(unsigned x = 0; x < width; x++) {
dst_bits[FI_RGBA_BLUE] = src_bits[0]; // B
dst_bits[FI_RGBA_GREEN] = src_bits[1]; // G
dst_bits[FI_RGBA_RED] = src_bits[2]; // R
src_bits += 3;
dst_bits += 3;
}
}
break;
case 32:
for(unsigned y = 0; y < height; y++) {
const BYTE *src_bits = src_bitmap + y * src_pitch;
BYTE *dst_bits = (BYTE*)FreeImage_GetScanLine(dib, height-1-y);
for(unsigned x = 0; x < width; x++) {
dst_bits[FI_RGBA_BLUE] = src_bits[0]; // B
dst_bits[FI_RGBA_GREEN] = src_bits[1]; // G
dst_bits[FI_RGBA_RED] = src_bits[2]; // R
dst_bits[FI_RGBA_ALPHA] = src_bits[3]; // A
src_bits += 4;
dst_bits += 4;
}
}
break;
}
// Free the decoder
WebPFreeDecBuffer(output_buffer);
return dib;
} catch (const char *text) {
if(dib) {
FreeImage_Unload(dib);
}
WebPFreeDecBuffer(output_buffer);
if(NULL != text) {
FreeImage_OutputMessageProc(s_format_id, text);
}
return NULL;
}
}
static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
WebPMux *mux = NULL;
WebPMuxFrameInfo webp_frame = { 0 }; // raw image
WebPData color_profile; // ICC raw data
WebPData xmp_metadata; // XMP raw data
WebPData exif_metadata; // EXIF raw data
FIBITMAP *dib = NULL;
WebPMuxError error_status;
if(!handle) {
return NULL;
}
try {
// get the MUX object
mux = (WebPMux*)data;
if(!mux) {
throw (1);
}
// gets the feature flags from the mux object
uint32_t webp_flags = 0;
error_status = WebPMuxGetFeatures(mux, &webp_flags);
if(error_status != WEBP_MUX_OK) {
throw (1);
}
// get image data
error_status = WebPMuxGetFrame(mux, 1, &webp_frame);
if(error_status == WEBP_MUX_OK) {
// decode the data (can be limited to the header if flags uses FIF_LOAD_NOPIXELS)
dib = DecodeImage(&webp_frame.bitstream, flags);
if(!dib) {
throw (1);
}
// get ICC profile
if(webp_flags & ICCP_FLAG) {
error_status = WebPMuxGetChunk(mux, "ICCP", &color_profile);
if(error_status == WEBP_MUX_OK) {
FreeImage_CreateICCProfile(dib, (void*)color_profile.bytes, (long)color_profile.size);
}
}
// get XMP metadata
if(webp_flags & XMP_FLAG) {
error_status = WebPMuxGetChunk(mux, "XMP ", &xmp_metadata);
if(error_status == WEBP_MUX_OK) {
// create a tag
FITAG *tag = FreeImage_CreateTag();
if(tag) {
FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
FreeImage_SetTagLength(tag, (DWORD)xmp_metadata.size);
FreeImage_SetTagCount(tag, (DWORD)xmp_metadata.size);
FreeImage_SetTagType(tag, FIDT_ASCII);
FreeImage_SetTagValue(tag, xmp_metadata.bytes);
// store the tag
FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
// destroy the tag
FreeImage_DeleteTag(tag);
}
}
}
// get Exif metadata
if(webp_flags & EXIF_FLAG) {
error_status = WebPMuxGetChunk(mux, "EXIF", &exif_metadata);
if(error_status == WEBP_MUX_OK) {
// read the Exif raw data as a blob
jpeg_read_exif_profile_raw(dib, exif_metadata.bytes, (unsigned)exif_metadata.size);
// read and decode the Exif data
jpeg_read_exif_profile(dib, exif_metadata.bytes, (unsigned)exif_metadata.size);
}
}
}
WebPDataClear(&webp_frame.bitstream);
return dib;
} catch(int) {
WebPDataClear(&webp_frame.bitstream);
return NULL;
}
}
// --------------------------------------------------------------------------
/**
Encode a FIBITMAP to a WebP image
@param hmem Memory output stream, containing on return the encoded image
@param dib The FIBITMAP to encode
@param flags FreeImage save flags
@return Returns TRUE if successfull, returns FALSE otherwise
*/
static BOOL
EncodeImage(FIMEMORY *hmem, FIBITMAP *dib, int flags) {
WebPPicture picture; // Input buffer
WebPConfig config; // Coding parameters
BOOL bIsFlipped = FALSE;
try {
const unsigned width = FreeImage_GetWidth(dib);
const unsigned height = FreeImage_GetHeight(dib);
const unsigned bpp = FreeImage_GetBPP(dib);
const unsigned pitch = FreeImage_GetPitch(dib);
// check image type
FREE_IMAGE_TYPE image_type = FreeImage_GetImageType(dib);
if( !((image_type == FIT_BITMAP) && ((bpp == 24) || (bpp == 32))) ) {
throw FI_MSG_ERROR_UNSUPPORTED_FORMAT;
}
// check format limits
if(MAX(width, height) > WEBP_MAX_DIMENSION) {
FreeImage_OutputMessageProc(s_format_id, "Unsupported image size: width x height = %d x %d", width, height);
return FALSE;
}
// Initialize output I/O
if(WebPPictureInit(&picture) == 1) {
picture.writer = WebP_MemoryWriter;
picture.custom_ptr = hmem;
picture.width = (int)width;
picture.height = (int)height;
} else {
throw "Couldn't initialize WebPPicture";
}
// --- Set encoding parameters ---
// Initialize encoding parameters to default values
WebPConfigInit(&config);
// quality/speed trade-off (0=fast, 6=slower-better)
config.method = 6;
if((flags & WEBP_LOSSLESS) == WEBP_LOSSLESS) {
// lossless encoding
config.lossless = 1;
( run in 0.746 second using v1.01-cache-2.11-cpan-df04353d9ac )