summaryrefslogtreecommitdiffstats
path: root/kernel/kls_mng/fmt_codec_mng.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kls_mng/fmt_codec_mng.cpp')
-rw-r--r--kernel/kls_mng/fmt_codec_mng.cpp372
1 files changed, 372 insertions, 0 deletions
diff --git a/kernel/kls_mng/fmt_codec_mng.cpp b/kernel/kls_mng/fmt_codec_mng.cpp
new file mode 100644
index 0000000..3d72f76
--- /dev/null
+++ b/kernel/kls_mng/fmt_codec_mng.cpp
@@ -0,0 +1,372 @@
+/* This file is part of ksquirrel-libs (http://ksquirrel.sf.net)
+
+ Copyright (c) 2005 Dmitry Baryshev <ksquirrel@tut.by>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation;
+ either version 2 of the License, or (at your option) any later
+ version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <iostream>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ksquirrel-libs/fmt_types.h"
+#include "ksquirrel-libs/fileio.h"
+#include "ksquirrel-libs/fmt_utils.h"
+
+#include <libmng.h>
+
+#include "fmt_codec_mng_defs.h"
+#include "fmt_codec_mng.h"
+
+#include "ksquirrel-libs/error.h"
+
+#include "../xpm/codec_mng.xpm"
+
+/* structure for keeping track of our mng stream inside the callbacks */
+struct mngstuff
+{
+ FILE *file; /* pointer to the file we're decoding */
+ std::string filename; /* pointer to the file's path/name */
+ fmt_codec *codec;
+};
+
+/*
+ *
+ * MNG (Multiple-image Network Graphics) is the animation extension of the popular PNG image-format.
+ * PNG (Portable Network Graphics) is an extensible file format for the lossless, portable,
+ * well-compressed storage of raster images.
+ *
+ * MNG has advanced animation features which make it very useful as a full replacement
+ * for GIF animations. These features allow animations that are impossible with GIF or
+ * result in much smaller files as GIF.
+ *
+ * As MNG builds on the same structure as PNG, it is robust, extensible and free of
+ * patents. It retains the same clever file integrity checks as in PNG.
+ *
+ * MNG also embraces the lossy JPEG image-format in a sub-format named JNG, which
+ * allows for alpha-transparency and color-correction on highly compressed (photographic) images.
+ *
+ */
+
+/* ******************************************************************** */
+/* callbacks from mngplay.c (C) Ralph Giles <giles@ashlu.bc.ca> */
+/* ******************************************************************** */
+
+/* memory allocation; data must be zeroed */
+mng_ptr mymngalloc(mng_size_t size)
+{
+ // libmng requires calloc...
+ return (mng_ptr)calloc(1, size);
+}
+
+/* memory deallocation */
+void mymngfree(mng_ptr p, mng_size_t /*size*/)
+{
+ free(p);
+}
+
+mng_bool mymngopenstream(mng_handle mng)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff*)mng_get_userdata(mng);
+
+ /* open the file */
+ mymng->file = fopen(mymng->filename.c_str(), "rb");
+
+ if(mymng->file == NULL)
+ return MNG_FALSE;
+
+ return MNG_TRUE;
+}
+
+mng_bool mymngprocesstext(mng_handle mng, mng_uint8 /*iType*/, mng_pchar zKeyword, mng_pchar zText,
+ mng_pchar /*zLanguage*/, mng_pchar /*zTranslation*/)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *)mng_get_userdata(mng);
+
+ if(zKeyword && zText)
+ {
+ fmt_metaentry mt;
+
+ mt.group = zKeyword;
+ mt.data = zText;
+
+ mymng->codec->addmeta(mt);
+ }
+
+ return MNG_TRUE;
+}
+
+mng_bool mymngclosestream(mng_handle mng)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *)mng_get_userdata(mng);
+
+ /* close the file */
+ fclose(mymng->file);
+ mymng->file = NULL;/* for safety */
+
+ mymng->filename.clear();
+
+ return MNG_TRUE;
+}
+
+/* feed data to the decoder */
+mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread)
+{
+ mngstuff *mymng;
+
+ /* look up our stream struct */
+ mymng = (mngstuff *)mng_get_userdata(mng);
+
+ /* read the requested amount of data from the file */
+ *bytesread = fread(buffer, 1, size, mymng->file);
+
+ return MNG_TRUE;
+}
+
+/* the header's been read. set up the display stuff */
+mng_bool mymngprocessheader(mng_handle mng, mng_uint32 width, mng_uint32 height)
+{
+ mngstuff *mymng;
+
+ mymng = (mngstuff *)mng_get_userdata(mng);
+
+ mymng->codec->priv.w = width;
+
+ mymng->codec->priv.frame = new RGBA [width * height];
+
+ return (!mymng->codec->priv.frame) ? MNG_FALSE : MNG_TRUE;
+}
+
+/* return a row pointer for the decoder to fill */
+mng_ptr mymnggetcanvasline(mng_handle mng, mng_uint32 line)
+{
+ mngstuff *mymng;
+ mng_ptr row;
+
+ mymng = (mngstuff *)mng_get_userdata(mng);
+
+ row = mymng->codec->priv.frame + line * mymng->codec->priv.w;
+
+ return row;
+}
+
+/* timer */
+mng_uint32 mymnggetticks(mng_handle /*mng*/)
+{
+ return 0;
+}
+
+mng_bool mymngrefresh(mng_handle /*mng*/, mng_uint32 /*x*/, mng_uint32 /*y*/, mng_uint32 /*w*/, mng_uint32 /*h*/)
+{
+ return MNG_TRUE;
+}
+
+/* interframe delay callback */
+mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs)
+{
+ mngstuff *mymng;
+
+ mymng = (mngstuff *)mng_get_userdata(mng);
+
+ mymng->codec->priv.ms = (msecs == 1) ? 100 : msecs;
+
+ return MNG_TRUE;
+}
+
+/* ******************************************************************** */
+
+fmt_codec::fmt_codec() : fmt_codec_base()
+{}
+
+fmt_codec::~fmt_codec()
+{}
+
+void fmt_codec::options(codec_options *o)
+{
+ o->version = "0.3.4";
+ o->name = "Multiple Network Graphics";
+
+#ifdef MNG_INCLUDE_JNG
+ o->filter = "*.mng *.jng ";
+ o->mimetype = "video/x-mng;image/x-jng";
+#else
+ o->filter = "*.mng ";
+ o->mimetype = "video/x-mng";
+#endif
+
+ o->config = "";
+ o->mime = "";
+ o->pixmap = codec_mng;
+ o->readable = true;
+ o->canbemultiple = true;
+ o->writestatic = false;
+ o->writeanimated = false;
+ o->needtempfile = false;
+}
+
+s32 fmt_codec::read_init(const std::string &file)
+{
+ frs.open(file.c_str(), ios::binary | ios::in);
+
+ if(!frs.good())
+ return SQE_R_NOFILE;
+
+ frs.close();
+
+ currentImage = -1;
+ read_error = false;
+
+ finfo.animated = false;
+
+ // allocate our stream data structure
+ mymng = new mngstuff;
+
+ if(!mymng)
+ return SQE_R_NOMEMORY;
+
+ mymng->filename = file;
+ mymng->codec = this;
+ priv.frame = 0;
+ priv.ms = 10;
+
+ /* set up the mng decoder for our stream */
+ mng = mng_initialize(mymng, mymngalloc, mymngfree, MNG_NULL);
+
+ if (mng == MNG_NULL)
+ return SQE_R_NOMEMORY;
+
+ /* set the callbacks */
+ mng_setcb_openstream(mng, ::mymngopenstream);
+ mng_setcb_closestream(mng, ::mymngclosestream);
+ mng_setcb_readdata(mng, ::mymngreadstream);
+ mng_setcb_gettickcount(mng, ::mymnggetticks);
+ mng_setcb_settimer(mng, ::mymngsettimer);
+ mng_setcb_processheader(mng, ::mymngprocessheader);
+ mng_setcb_getcanvasline(mng, ::mymnggetcanvasline);
+ mng_setcb_refresh(mng, ::mymngrefresh);
+ mng_setcb_processtext(mng, ::mymngprocesstext);
+ mng_set_suspensionmode(mng, MNG_TRUE);
+ mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8);
+
+ total = 0;
+
+ return SQE_OK;
+}
+
+s32 fmt_codec::read_next()
+{
+ currentImage++;
+
+ if((total && currentImage == total) || (!total && currentImage))
+ return SQE_NOTOK;
+
+ int myretcode;
+
+ if(!currentImage)
+ {
+ myretcode = mng_read(mng);
+
+ if(myretcode != MNG_NOERROR)
+ return SQE_R_BADFILE;
+
+ total = mng_get_totallayers(mng);
+
+ if(total > 1) total--;
+
+ myretcode = mng_display(mng);
+
+ if(myretcode != MNG_NOERROR && myretcode != MNG_NEEDTIMERWAIT)
+ return SQE_R_BADFILE;
+ }
+ else
+ {
+ myretcode = mng_display_resume(mng);
+
+ if(myretcode != MNG_NOERROR && myretcode != MNG_NEEDTIMERWAIT)
+ return SQE_R_BADFILE;
+
+ finfo.animated = true;
+ }
+
+ fmt_image image;
+
+ image.w = mng_get_imagewidth(mng);
+ image.h = mng_get_imageheight(mng);
+ image.bpp = 32;
+ image.compression = (mng_get_imagetype(mng) == MNG_IMAGETYPE_PNG) ? "Deflate method 8, 32K window" : "JPEG";
+ image.hasalpha = true;
+
+ int cc = mng_get_colortype(mng);
+
+ switch(cc)
+ {
+ case MNG_COLORTYPE_GRAY: image.colorspace = "Grayscale"; break;
+ case MNG_COLORTYPE_RGB: image.colorspace = "RGB"; break;
+ case MNG_COLORTYPE_INDEXED: image.colorspace = "Indexed"; break;
+ case MNG_COLORTYPE_GRAYA: image.colorspace = "Grayscale with alpha"; break;
+ case MNG_COLORTYPE_RGBA: image.colorspace = "RGBA"; break;
+
+ default: image.colorspace = "Unknown";
+ }
+
+ image.delay = priv.ms;
+
+ finfo.image.push_back(image);
+
+ line = -1;
+
+ return SQE_OK;
+}
+
+s32 fmt_codec::read_next_pass()
+{
+ return SQE_OK;
+}
+
+s32 fmt_codec::read_scanline(RGBA *scan)
+{
+ line++;
+ fmt_image *im = image(currentImage);
+ fmt_utils::fillAlpha(scan, im->w);
+
+ memcpy(scan, priv.frame+im->w*line, im->w*sizeof(RGBA));
+
+ return SQE_OK;
+}
+
+void fmt_codec::read_close()
+{
+ finfo.meta.clear();
+ finfo.image.clear();
+
+ mng_cleanup(&mng);
+
+ delete [] priv.frame;
+ priv.frame = 0;
+}
+
+#include "fmt_codec_cd_func.h"