summaryrefslogtreecommitdiff
path: root/plugins/freeimage/Source/FreeImage/PluginMNG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/freeimage/Source/FreeImage/PluginMNG.cpp')
-rw-r--r--plugins/freeimage/Source/FreeImage/PluginMNG.cpp312
1 files changed, 312 insertions, 0 deletions
diff --git a/plugins/freeimage/Source/FreeImage/PluginMNG.cpp b/plugins/freeimage/Source/FreeImage/PluginMNG.cpp
new file mode 100644
index 0000000000..775b126965
--- /dev/null
+++ b/plugins/freeimage/Source/FreeImage/PluginMNG.cpp
@@ -0,0 +1,312 @@
+// ==========================================================
+// MNG Loader
+//
+// Design and implementation by
+// - Floris van den Berg (flvdberg@wxs.nl)
+//
+// 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 "../LibMNG/libmng.h"
+//#include "../LibMNG/libmng_data.h"
+
+// ==========================================================
+// Plugin Interface
+// ==========================================================
+
+static int s_format_id;
+
+// ----------------------------------------------------------
+// Constants + headers
+// ----------------------------------------------------------
+
+typedef struct {
+ FIBITMAP *bitmap; // pointer to the bitmap data
+ FreeImageIO *io; // pointer to the io functions
+ fi_handle file; // pointer to the file we're decoding
+} mngstuff;
+
+// ----------------------------------------------------------
+// Callbacks for the mng decoder
+// ----------------------------------------------------------
+
+mng_ptr
+mymngalloc(mng_size_t size) {
+ return (mng_ptr)calloc(1, size);
+}
+
+void
+mymngfree(mng_ptr p, mng_size_t size) {
+ free(p);
+}
+
+mng_bool
+mymngopenstream(mng_handle mng) {
+ // since the user is responsible for opening and closing the file,
+ // we leave the default implementation open
+
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngclosestream(mng_handle mng) {
+ // since the user is responsible for opening and closing the file,
+ // we leave the default implementation open
+
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) {
+ mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
+
+ *bytesread = mymng->io->read_proc(buffer, 1, size, mymng->file);
+
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height) {
+ mngstuff *client_data = (mngstuff *)mng_get_userdata(mng);
+ BYTE bHasAlpha = mng_get_alphadepth(mng);
+
+#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_RGB
+ if(bHasAlpha) {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
+ } else {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_RGB8);
+ }
+#else
+ if(bHasAlpha) {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_BGRA8);
+ } else {
+ // allocate a bitmap with the given dimensions
+ FIBITMAP *bitmap = FreeImage_Allocate(width, height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+ client_data->bitmap = bitmap;
+ // tell the mng decoder about our bit-depth choice
+ mng_set_canvasstyle(mng, MNG_CANVAS_BGR8);
+ }
+#endif // FREEIMAGE_COLORORDER_RGB
+
+ return client_data->bitmap ? MNG_TRUE : MNG_FALSE;
+}
+
+mng_ptr
+mymnggetcanvasline(mng_handle mng, mng_uint32 line) {
+ FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(mng))->bitmap;
+
+ return FreeImage_GetScanLine(bitmap, FreeImage_GetHeight(bitmap) - line - 1);
+}
+
+mng_bool
+mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) {
+ return MNG_TRUE;
+}
+
+mng_uint32
+mymnggetticks(mng_handle mng) {
+ return 0;
+}
+
+mng_bool
+mymngsettimer(mng_handle mng, mng_uint32 msecs) {
+ return MNG_TRUE;
+}
+
+mng_bool
+mymngerror(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text) {
+ char msg[256];
+ if((code == MNG_SEQUENCEERROR) && (chunktype == MNG_UINT_TERM)) {
+ // ignore sequence error for TERM
+ return MNG_TRUE;
+ }
+ if(text) {
+ // text can be null depending on compiler options
+ sprintf(msg, "Error reported by libmng (%d)\r\n\r\n%s", code, text);
+ } else {
+ sprintf(msg, "Error %d reported by libmng", code);
+ }
+ FreeImage_OutputMessageProc(s_format_id, msg);
+ return MNG_FALSE;
+}
+
+// ==========================================================
+// Plugin Implementation
+// ==========================================================
+
+static const char * DLL_CALLCONV
+Format() {
+ return "MNG";
+}
+
+static const char * DLL_CALLCONV
+Description() {
+ return "Multiple Network Graphics";
+}
+
+static const char * DLL_CALLCONV
+Extension() {
+ return "mng";
+}
+
+static const char * DLL_CALLCONV
+RegExpr() {
+ return NULL;
+}
+
+static const char * DLL_CALLCONV
+MimeType() {
+ return "video/x-mng";
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportDepth(int depth) {
+ return FALSE;
+}
+
+static BOOL DLL_CALLCONV
+SupportsExportType(FREE_IMAGE_TYPE type) {
+ return FALSE;
+}
+
+// ----------------------------------------------------------
+
+static void * DLL_CALLCONV
+Open(FreeImageIO *io, fi_handle handle, BOOL read) {
+ mngstuff *mymng = (mngstuff *)calloc(1, sizeof(*mymng));
+ mymng->io = io;
+ mymng->file = handle;
+
+ return mymng;
+}
+
+static void DLL_CALLCONV
+Close(FreeImageIO *io, fi_handle handle, void *data) {
+ free((mngstuff *)data);
+}
+
+// ----------------------------------------------------------
+
+static FIBITMAP * DLL_CALLCONV
+Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
+ mng_handle hmng = NULL;
+
+ if (handle != NULL) {
+ try {
+ // allocate our stream data structure
+ mngstuff *mymng = (mngstuff *)data;
+
+ // set up the mng decoder for our stream
+ hmng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL);
+
+ if (hmng == MNG_NULL) {
+ throw "could not initialize libmng";
+ }
+
+ // set the colorprofile, lcms uses this
+ mng_set_srgb(hmng, MNG_TRUE );
+ // set white as background color
+ WORD wRed, wGreen, wBlue;
+ wRed = wGreen = wBlue = (255 << 8) + 255;
+ mng_set_bgcolor(hmng, wRed, wGreen, wBlue);
+ // if PNG Background is available, use it
+ mng_set_usebkgd(hmng, MNG_TRUE );
+ // no need to store chunks
+ mng_set_storechunks(hmng, MNG_FALSE);
+ // no need to wait: straight reading
+ mng_set_suspensionmode(hmng, MNG_FALSE);
+
+ // set the callbacks
+ mng_setcb_errorproc(hmng, mymngerror);
+ mng_setcb_openstream(hmng, mymngopenstream);
+ mng_setcb_closestream(hmng, mymngclosestream);
+ mng_setcb_readdata(hmng, mymngreadstream);
+ mng_setcb_processheader(hmng, mymngprocessheader);
+ mng_setcb_getcanvasline(hmng, mymnggetcanvasline);
+ mng_setcb_refresh(hmng, mymngrefresh);
+ mng_setcb_gettickcount(hmng, mymnggetticks);
+ mng_setcb_settimer(hmng, mymngsettimer);
+
+ // read in the bitmap
+ mng_readdisplay(hmng);
+
+ // read all bitmaps
+ int retval = MNG_NOERROR;
+ while(mng_status_reading(hmng)) {
+ retval = mng_display_resume(hmng);
+ if((mng_get_imagetype(hmng) != mng_it_jng) && (retval == MNG_NEEDTIMERWAIT) || (retval == MNG_FUNCTIONINVALID))
+ break;
+ }
+
+ // temp store the newly created bitmap
+ FIBITMAP *bitmap = mymng->bitmap;
+
+ // cleanup and return the temp stored bitmap
+ mng_cleanup(&hmng);
+
+ return bitmap;
+
+ } catch (const char *message) {
+ FIBITMAP *bitmap = ((mngstuff *)mng_get_userdata(hmng))->bitmap;
+ if(bitmap) {
+ FreeImage_Unload(bitmap);
+ }
+ mng_cleanup(&hmng);
+ FreeImage_OutputMessageProc(s_format_id, message);
+ }
+ }
+
+ return NULL;
+}
+
+// ==========================================================
+// Init
+// ==========================================================
+
+void DLL_CALLCONV
+InitMNG(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 = NULL;
+ plugin->validate_proc = NULL;
+ plugin->mime_proc = MimeType;
+ plugin->supports_export_bpp_proc = SupportsExportDepth;
+ plugin->supports_export_type_proc = SupportsExportType;
+ plugin->supports_icc_profiles_proc = NULL; // not implemented yet;
+}