summaryrefslogtreecommitdiff
path: root/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/AdvaImg/src/FreeImage/PluginWebP.cpp')
-rw-r--r--plugins/AdvaImg/src/FreeImage/PluginWebP.cpp698
1 files changed, 0 insertions, 698 deletions
diff --git a/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp b/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp
deleted file mode 100644
index 9fb0b69447..0000000000
--- a/plugins/AdvaImg/src/FreeImage/PluginWebP.cpp
+++ /dev/null
@@ -1,698 +0,0 @@
-// ==========================================================
-// Google WebP Loader & Writer
-//
-// Design and implementation by
-// - Herve Drolon (drolon@infonie.fr)
-//
-// This file is part of FreeImage 3
-//
-// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
-// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
-// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
-// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
-// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
-// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
-// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
-// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
-// THIS DISCLAIMER.
-//
-// Use at your own risk!
-// ==========================================================
-
-#include "FreeImage.h"
-#include "Utilities.h"
-
-#include "../Metadata/FreeImageTag.h"
-
-#include "../LibWebP/src/webp/decode.h"
-#include "../LibWebP/src/webp/encode.h"
-#include "../LibWebP/src/enc/vp8enci.h"
-#include "../LibWebP/src/webp/mux.h"
-
-// ==========================================================
-// Plugin Interface
-// ==========================================================
-
-static int s_format_id;
-
-// ----------------------------------------------------------
-// Helpers for the load function
-// ----------------------------------------------------------
-
-/**
-Read the whole file into memory
-*/
-static BOOL
-ReadFileToWebPData(FreeImageIO *io, fi_handle handle, WebPData * const bitstream) {
- uint8_t *raw_data = NULL;
-
- try {
- // Read the input file and put it in memory
- long start_pos = io->tell_proc(handle);
- io->seek_proc(handle, 0, SEEK_END);
- size_t file_length = (size_t)(io->tell_proc(handle) - start_pos);
- io->seek_proc(handle, start_pos, SEEK_SET);
- raw_data = (uint8_t*)malloc(file_length * sizeof(uint8_t));
- if(!raw_data) {
- throw FI_MSG_ERROR_MEMORY;
- }
- if(io->read_proc(raw_data, 1, (unsigned)file_length, handle) != file_length) {
- throw "Error while reading input stream";
- }
-
- // copy pointers (must be released later using free)
- bitstream->bytes = raw_data;
- bitstream->size = file_length;
-
- return TRUE;
-
- } catch(const char *text) {
- if(raw_data) {
- free(raw_data);
- }
- memset(bitstream, 0, sizeof(WebPData));
- if(NULL != text) {
- FreeImage_OutputMessageProc(s_format_id, text);
- }
- return FALSE;
- }
-}
-
-// ----------------------------------------------------------
-// Helpers for the save function
-// ----------------------------------------------------------
-
-/**
-Output function. Should return 1 if writing was successful.
-data/data_size is the segment of data to write, and 'picture' is for
-reference (and so one can make use of picture->custom_ptr).
-*/
-static int
-WebP_MemoryWriter(const BYTE *data, size_t data_size, const WebPPicture* const picture) {
- FIMEMORY *hmem = (FIMEMORY*)picture->custom_ptr;
- return data_size ? (FreeImage_WriteMemory(data, 1, (unsigned)data_size, hmem) == data_size) : 0;
-}
-
-// ==========================================================
-// Plugin Implementation
-// ==========================================================
-
-static const char * DLL_CALLCONV
-Format() {
- return "WebP";
-}
-
-static const char * DLL_CALLCONV
-Description() {
- return "Google WebP image format";
-}
-
-static const char * DLL_CALLCONV
-Extension() {
- return "webp";
-}
-
-static const char * DLL_CALLCONV
-RegExpr() {
- return NULL;
-}
-
-static const char * DLL_CALLCONV
-MimeType() {
- return "image/webp";
-}
-
-static BOOL DLL_CALLCONV
-Validate(FreeImageIO *io, fi_handle handle) {
- BYTE riff_signature[4] = { 0x52, 0x49, 0x46, 0x46 };
- BYTE webp_signature[4] = { 0x57, 0x45, 0x42, 0x50 };
- BYTE signature[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-
- io->read_proc(signature, 1, 12, handle);
-
- if(memcmp(riff_signature, signature, 4) == 0) {
- if(memcmp(webp_signature, signature + 8, 4) == 0) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-static BOOL DLL_CALLCONV
-SupportsExportDepth(int depth) {
- return (
- (depth == 24) ||
- (depth == 32)
- );
-}
-
-static BOOL DLL_CALLCONV
-SupportsExportType(FREE_IMAGE_TYPE type) {
- return (type == FIT_BITMAP) ? TRUE : FALSE;
-}
-
-static BOOL DLL_CALLCONV
-SupportsICCProfiles() {
- return TRUE;
-}
-
-static BOOL DLL_CALLCONV
-SupportsNoPixels() {
- return TRUE;
-}
-
-// ----------------------------------------------------------
-
-static void * DLL_CALLCONV
-Open(FreeImageIO *io, fi_handle handle, BOOL read) {
- WebPMux *mux = NULL;
- int copy_data = 1; // 1 : copy data into the mux, 0 : keep a link to local data
-
- if(read) {
- // create the MUX object from the input stream
- WebPData bitstream;
- // read the input file and put it in memory
- if(!ReadFileToWebPData(io, handle, &bitstream)) {
- return NULL;
- }
- // create the MUX object
- mux = WebPMuxCreate(&bitstream, copy_data);
- // no longer needed since copy_data == 1
- free((void*)bitstream.bytes);
- if(mux == NULL) {
- FreeImage_OutputMessageProc(s_format_id, "Failed to create mux object from file");
- return NULL;
- }
- } else {
- // creates an empty mux object
- mux = WebPMuxNew();
- if(mux == NULL) {
- FreeImage_OutputMessageProc(s_format_id, "Failed to create empty mux object");
- return NULL;
- }
- }
-
- return mux;
-}
-
-static void DLL_CALLCONV
-Close(FreeImageIO *io, fi_handle handle, void *data) {
- WebPMux *mux = (WebPMux*)data;
- if(mux != NULL) {
- // free the MUX object
- WebPMuxDelete(mux);
- }
-}
-
-// ----------------------------------------------------------
-
-/**
-Decode a WebP image and returns a FIBITMAP image
-@param webp_image Raw WebP image
-@param flags FreeImage load flags
-@return Returns a dib if successfull, returns NULL otherwise
-*/
-static FIBITMAP *
-DecodeImage(WebPData *webp_image, int flags) {
- FIBITMAP *dib = NULL;
-
- 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
- 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;
- picture.use_argb = 1;
- } else if((flags & 0x7F) > 0) {
- // lossy encoding
- config.lossless = 0;
- // quality is between 1 (smallest file) and 100 (biggest) - default to 75
- config.quality = (float)(flags & 0x7F);
- if(config.quality > 100) {
- config.quality = 100;
- }
- }
-
- // validate encoding parameters
- if(WebPValidateConfig(&config) == 0) {
- throw "Failed to initialize encoder";
- }
-
- // --- Perform encoding ---
-
- // Invert dib scanlines
- bIsFlipped = FreeImage_FlipVertical(dib);
-
-
- // convert dib buffer to output stream
-
- const BYTE *bits = FreeImage_GetBits(dib);
-
-#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
- switch(bpp) {
- case 24:
- WebPPictureImportBGR(&picture, bits, pitch);
- break;
- case 32:
- WebPPictureImportBGRA(&picture, bits, pitch);
- break;
- }
-#else
- switch(bpp) {
- case 24:
- WebPPictureImportRGB(&picture, bits, pitch);
- break;
- case 32:
- WebPPictureImportRGBA(&picture, bits, pitch);
- break;
- }
-
-#endif // FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
-
- if(!WebPEncode(&config, &picture)) {
- throw "Failed to encode image";
- }
-
- WebPPictureFree(&picture);
-
- if(bIsFlipped) {
- // invert dib scanlines
- FreeImage_FlipVertical(dib);
- }
-
- return TRUE;
-
- } catch (const char* text) {
-
- WebPPictureFree(&picture);
-
- if(bIsFlipped) {
- // invert dib scanlines
- FreeImage_FlipVertical(dib);
- }
-
- if(NULL != text) {
- FreeImage_OutputMessageProc(s_format_id, text);
- }
- }
-
- return FALSE;
-}
-
-static BOOL DLL_CALLCONV
-Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
- WebPMux *mux = NULL;
- FIMEMORY *hmem = NULL;
- WebPData webp_image;
- WebPData output_data = { 0 };
- WebPMuxError error_status;
-
- int copy_data = 1; // 1 : copy data into the mux, 0 : keep a link to local data
-
- if(!dib || !handle || !data) {
- return FALSE;
- }
-
- try {
-
- // get the MUX object
- mux = (WebPMux*)data;
- if(!mux) {
- return FALSE;
- }
-
- // --- prepare image data ---
-
- // encode image as a WebP blob
- hmem = FreeImage_OpenMemory();
- if(!hmem || !EncodeImage(hmem, dib, flags)) {
- throw (1);
- }
- // store the blob into the mux
- BYTE *data = NULL;
- DWORD data_size = 0;
- FreeImage_AcquireMemory(hmem, &data, &data_size);
- webp_image.bytes = data;
- webp_image.size = data_size;
- error_status = WebPMuxSetImage(mux, &webp_image, copy_data);
- // no longer needed since copy_data == 1
- FreeImage_CloseMemory(hmem);
- hmem = NULL;
- if(error_status != WEBP_MUX_OK) {
- throw (1);
- }
-
- // --- set metadata ---
-
- // set ICC color profile
- {
- FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
- if (iccProfile->size && iccProfile->data) {
- WebPData icc_profile;
- icc_profile.bytes = (uint8_t*)iccProfile->data;
- icc_profile.size = (size_t)iccProfile->size;
- error_status = WebPMuxSetChunk(mux, "ICCP", &icc_profile, copy_data);
- if(error_status != WEBP_MUX_OK) {
- throw (1);
- }
- }
- }
-
- // set XMP metadata
- {
- FITAG *tag = NULL;
- if(FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag)) {
- WebPData xmp_profile;
- xmp_profile.bytes = (uint8_t*)FreeImage_GetTagValue(tag);
- xmp_profile.size = (size_t)FreeImage_GetTagLength(tag);
- error_status = WebPMuxSetChunk(mux, "XMP ", &xmp_profile, copy_data);
- if(error_status != WEBP_MUX_OK) {
- throw (1);
- }
- }
- }
-
- // set Exif metadata
- {
- FITAG *tag = NULL;
- if(FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag)) {
- WebPData exif_profile;
- exif_profile.bytes = (uint8_t*)FreeImage_GetTagValue(tag);
- exif_profile.size = (size_t)FreeImage_GetTagLength(tag);
- error_status = WebPMuxSetChunk(mux, "EXIF", &exif_profile, copy_data);
- if(error_status != WEBP_MUX_OK) {
- throw (1);
- }
- }
- }
-
- // get data from mux in WebP RIFF format
- error_status = WebPMuxAssemble(mux, &output_data);
- if(error_status != WEBP_MUX_OK) {
- FreeImage_OutputMessageProc(s_format_id, "Failed to create webp output file");
- throw (1);
- }
-
- // write the file to the output stream
- if(io->write_proc((void*)output_data.bytes, 1, (unsigned)output_data.size, handle) != output_data.size) {
- FreeImage_OutputMessageProc(s_format_id, "Failed to write webp output file");
- throw (1);
- }
-
- // free WebP output file
- WebPDataClear(&output_data);
-
- return TRUE;
-
- } catch(int) {
- if(hmem) {
- FreeImage_CloseMemory(hmem);
- }
-
- WebPDataClear(&output_data);
-
- return FALSE;
- }
-}
-
-// ==========================================================
-// Init
-// ==========================================================
-
-void DLL_CALLCONV
-InitWEBP(Plugin *plugin, int format_id) {
- s_format_id = format_id;
-
- plugin->format_proc = Format;
- plugin->description_proc = Description;
- plugin->extension_proc = Extension;
- plugin->regexpr_proc = RegExpr;
- plugin->open_proc = Open;
- plugin->close_proc = Close;
- plugin->pagecount_proc = NULL;
- plugin->pagecapability_proc = NULL;
- plugin->load_proc = Load;
- plugin->save_proc = Save;
- plugin->validate_proc = Validate;
- plugin->mime_proc = MimeType;
- plugin->supports_export_bpp_proc = SupportsExportDepth;
- plugin->supports_export_type_proc = SupportsExportType;
- plugin->supports_icc_profiles_proc = SupportsICCProfiles;
- plugin->supports_no_pixels_proc = SupportsNoPixels;
-}
-