Alien-FreeImage
view release on metacpan or search on metacpan
src/Source/FreeImage/PluginWebP.cpp view on Meta::CPAN
const uint8_t* data = webp_image->bytes; // raw image data
const size_t data_size = webp_image->size; // raw image size
VP8StatusCode webp_status = VP8_STATUS_OK;
BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
// Main object storing the configuration for advanced decoding
WebPDecoderConfig decoder_config;
// Output buffer
WebPDecBuffer* const output_buffer = &decoder_config.output;
// Features gathered from the bitstream
WebPBitstreamFeatures* const bitstream = &decoder_config.input;
try {
// Initialize the configuration as empty
// This function must always be called first, unless WebPGetFeatures() is to be called
if(!WebPInitDecoderConfig(&decoder_config)) {
throw "Library version mismatch";
}
// Retrieve features from the bitstream
// The bitstream structure is filled with information gathered from the bitstream
webp_status = WebPGetFeatures(data, data_size, bitstream);
if(webp_status != VP8_STATUS_OK) {
throw FI_MSG_ERROR_PARSING;
}
// Allocate output dib
unsigned bpp = bitstream->has_alpha ? 32 : 24;
unsigned width = (unsigned)bitstream->width;
unsigned height = (unsigned)bitstream->height;
dib = FreeImage_AllocateHeader(header_only, width, height, bpp, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
if(!dib) {
throw FI_MSG_ERROR_DIB_MEMORY;
}
if(header_only) {
WebPFreeDecBuffer(output_buffer);
return dib;
}
// --- Set decoding options ---
// use multi-threaded decoding
decoder_config.options.use_threads = 1;
// set output color space
output_buffer->colorspace = bitstream->has_alpha ? MODE_BGRA : MODE_BGR;
// ---
// decode the input stream, taking 'config' into account.
webp_status = WebPDecode(data, data_size, &decoder_config);
if(webp_status != VP8_STATUS_OK) {
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
( run in 0.939 second using v1.01-cache-2.11-cpan-8450f2e95f3 )