2
* psimng.cpp - QImageFormat for loading MNG animations at once
3
* Copyright (C) 2003 Michail Pishchagin
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23
#include <qdatetime.h>
26
#include <qasyncimageio.h>
27
#include <qiodevice.h>
29
// Define XMD_H prohibits the included headers of libmng.h to typedef INT32.
30
// This is needed for Borland with STL support, since in that case, INT32 is
31
// already defined by some Borland header.
33
#if defined(Q_OS_UNIXWARE)
34
# define HAVE_BOOLEAN // libjpeg under Unixware seems to need this
39
class PsiMNGFormat : public QImageFormat {
44
int decode(QImage& img, QImageConsumer *cons, const uchar *buf, int length);
48
bool readdata(mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32p pRead);
49
bool errorproc(mng_int32 iErrorcode, mng_int8 /*iSeverity*/, mng_chunkid iChunkname, mng_uint32 /*iChunkseq*/, mng_int32 iExtra1, mng_int32 iExtra2, mng_pchar zErrortext);
50
bool processheader(mng_uint32 iWidth, mng_uint32 iHeight);
51
mng_ptr getcanvasline(mng_uint32 iLinenr);
52
mng_bool refresh(mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h);
53
mng_uint32 gettickcount();
54
bool settimer(mng_uint32 iMsecs);
57
// Animation-level information
63
// Image-level information
69
// Temporary locals during single data-chunk processing
71
int dataSize, processedData;
73
QImageConsumer *consumer;
77
//----------------------------------------------------------------------------
78
// C-callback to C++-member-function conversion
79
//----------------------------------------------------------------------------
81
static mng_bool openstream( mng_handle handle )
83
return ((PsiMNGFormat*)mng_get_userdata(handle))->openstream();
85
static mng_bool closestream( mng_handle handle )
87
return ((PsiMNGFormat*)mng_get_userdata(handle))->closestream();
89
static mng_bool readdata( mng_handle handle, mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32p pRead )
91
return ((PsiMNGFormat*)mng_get_userdata(handle))->readdata(pBuf,iBuflen,pRead);
93
static mng_bool errorproc( mng_handle handle,
96
mng_chunkid iChunkname,
100
mng_pchar zErrortext )
102
return ((PsiMNGFormat*)mng_get_userdata(handle))->errorproc(iErrorcode,
103
iSeverity,iChunkname,iChunkseq,iExtra1,iExtra2,zErrortext);
105
static mng_bool processheader( mng_handle handle,
106
mng_uint32 iWidth, mng_uint32 iHeight )
108
return ((PsiMNGFormat*)mng_get_userdata(handle))->processheader(iWidth,iHeight);
110
static mng_ptr getcanvasline( mng_handle handle, mng_uint32 iLinenr )
112
return ((PsiMNGFormat*)mng_get_userdata(handle))->getcanvasline(iLinenr);
114
static mng_bool refresh( mng_handle handle,
120
return ((PsiMNGFormat*)mng_get_userdata(handle))->refresh(iTop,iLeft,iBottom,iRight);
122
static mng_uint32 gettickcount( mng_handle handle )
124
return ((PsiMNGFormat*)mng_get_userdata(handle))->gettickcount();
126
static mng_bool settimer( mng_handle handle, mng_uint32 iMsecs )
128
return ((PsiMNGFormat*)mng_get_userdata(handle))->settimer(iMsecs);
131
static mng_ptr memalloc( mng_size_t iLen )
133
return calloc(1,iLen);
135
static void memfree( mng_ptr iPtr, mng_size_t /*iLen*/ )
140
//----------------------------------------------------------------------------
142
PsiMNGFormat::PsiMNGFormat()
149
PsiMNGFormat::~PsiMNGFormat()
153
bool PsiMNGFormat::openstream()
158
bool PsiMNGFormat::closestream()
163
bool PsiMNGFormat::readdata(mng_ptr pBuf, mng_uint32 iBuflen, mng_uint32p pRead)
165
if ( iBuflen <= (uint)dataSize ) {
166
memcpy(pBuf, data + processedData, iBuflen);
170
processedData += iBuflen;
175
bool PsiMNGFormat::errorproc( mng_int32 iErrorcode, mng_int8 /*iSeverity*/, mng_chunkid iChunkname, mng_uint32 /*iChunkseq*/, mng_int32 iExtra1, mng_int32 iExtra2, mng_pchar zErrortext )
177
qWarning("MNG error %d: %s; chunk %c%c%c%c; subcode %d:%d",
178
iErrorcode,zErrortext,
179
(iChunkname>>24)&0xff,
180
(iChunkname>>16)&0xff,
181
(iChunkname>>8)&0xff,
182
(iChunkname>>0)&0xff,
187
bool PsiMNGFormat::processheader(mng_uint32 iWidth, mng_uint32 iHeight)
189
image->create(iWidth, iHeight, 32);
190
image->setAlphaBuffer(TRUE);
191
memset(image->bits(), 0, iWidth*iHeight*4);
192
consumer->setSize(iWidth, iHeight);
193
mng_set_canvasstyle(handle,
194
QImage::systemByteOrder() == QImage::LittleEndian
195
? MNG_CANVAS_BGRA8 : MNG_CANVAS_ARGB8 );
199
mng_ptr PsiMNGFormat::getcanvasline(mng_uint32 iLinenr)
201
return image->scanLine(iLinenr);
204
mng_bool PsiMNGFormat::refresh(mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
207
consumer->changed(r);
208
consumer->setFramePeriod(0);
209
consumer->frameDone();
213
mng_uint32 PsiMNGFormat::gettickcount()
218
bool PsiMNGFormat::settimer(mng_uint32 iMsecs)
220
consumer->setFramePeriod(iMsecs);
221
consumer->frameDone();
226
int PsiMNGFormat::decode(QImage &img, QImageConsumer *cons, const uchar *buf, int length)
228
//if ( !length ) // there's no more data then
238
if ( state == MovieStart ) {
239
handle = mng_initialize( (mng_ptr)this, ::memalloc, ::memfree, 0 );
240
//mng_set_suspensionmode( handle, MNG_FALSE );
241
mng_setcb_openstream( handle, ::openstream );
242
mng_setcb_closestream( handle, ::closestream );
243
mng_setcb_readdata( handle, ::readdata );
244
mng_setcb_errorproc( handle, ::errorproc );
245
mng_setcb_processheader( handle, ::processheader );
246
mng_setcb_getcanvasline( handle, ::getcanvasline );
247
mng_setcb_refresh( handle, ::refresh );
248
mng_setcb_gettickcount( handle, ::gettickcount );
249
mng_setcb_settimer( handle, ::settimer );
252
mng_readdisplay(handle);
255
mng_display_resume(handle);
259
return processedData;
262
//----------------------------------------------------------------------------
264
class PsiMNGFormatType : public QImageFormatType
266
QImageFormat *decoderFor(const uchar *buffer, int length)
271
if (buffer[0]==138 // MNG signature
279
return new PsiMNGFormat;
285
const char *formatName() const
291
static PsiMNGFormatType *globalMngFormatTypeObject = 0;
293
void cleanupPsiMngIO()
295
if ( globalMngFormatTypeObject ) {
296
delete globalMngFormatTypeObject;
297
globalMngFormatTypeObject = 0;
303
static bool done = FALSE;
306
globalMngFormatTypeObject = new PsiMNGFormatType;
307
qAddPostRoutine( cleanupPsiMngIO );