[93] | 1 | /*
|
---|
| 2 | * File: ximamng.cpp
|
---|
| 3 | * Purpose: Platform Independent MNG Image Class Loader and Writer
|
---|
| 4 | * Author: 07/Aug/2001 Davide Pizzolato - www.xdp.it
|
---|
| 5 | * CxImage version 6.0.0 02/Feb/2008
|
---|
| 6 | */
|
---|
| 7 |
|
---|
| 8 | #include "ximamng.h"
|
---|
| 9 |
|
---|
| 10 | #if CXIMAGE_SUPPORT_MNG
|
---|
| 11 |
|
---|
| 12 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 13 | // callbacks for the mng decoder:
|
---|
| 14 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 15 |
|
---|
| 16 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 17 | // memory allocation; data must be zeroed
|
---|
| 18 | static mng_ptr
|
---|
| 19 | mymngalloc( mng_uint32 size )
|
---|
| 20 | {
|
---|
| 21 | return (mng_ptr)calloc(1, size);
|
---|
| 22 | }
|
---|
| 23 |
|
---|
| 24 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 25 | // memory deallocation
|
---|
| 26 | static void mymngfree(mng_ptr p, mng_uint32 size)
|
---|
| 27 | {
|
---|
| 28 | free(p);
|
---|
| 29 | }
|
---|
| 30 |
|
---|
| 31 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 32 | // Stream open/close:
|
---|
| 33 | // since the user is responsible for opening and closing the file,
|
---|
| 34 | // we leave the default implementation open
|
---|
| 35 | static mng_bool mymngopenstream(mng_handle mng) { return MNG_TRUE; }
|
---|
| 36 | static mng_bool mymngopenstreamwrite(mng_handle mng) { return MNG_TRUE; }
|
---|
| 37 | static mng_bool mymngclosestream(mng_handle mng) { return MNG_TRUE; }
|
---|
| 38 |
|
---|
| 39 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 40 | // feed data to the decoder
|
---|
| 41 | static mng_bool mymngreadstream(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread)
|
---|
| 42 | {
|
---|
| 43 | mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 44 | // read the requested amount of data from the file
|
---|
| 45 | *bytesread = mymng->file->Read( buffer, sizeof(BYTE), size);
|
---|
| 46 | return MNG_TRUE;
|
---|
| 47 | }
|
---|
| 48 |
|
---|
| 49 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 50 | static mng_bool mymngwritestream (mng_handle mng, mng_ptr pBuf, mng_uint32 iSize, mng_uint32 *iWritten)
|
---|
| 51 | {
|
---|
| 52 | mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 53 | // write it
|
---|
| 54 | *iWritten = mymng->file->Write (pBuf, 1, iSize);
|
---|
| 55 | return MNG_TRUE;
|
---|
| 56 | }
|
---|
| 57 |
|
---|
| 58 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 59 | // the header's been read. set up the display stuff
|
---|
| 60 | static mng_bool mymngprocessheader( mng_handle mng, mng_uint32 width, mng_uint32 height )
|
---|
| 61 | {
|
---|
| 62 | // normally the image buffer is allocated here,
|
---|
| 63 | // but in this module we don't know nothing about
|
---|
| 64 | // the final environment.
|
---|
| 65 |
|
---|
| 66 | mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 67 |
|
---|
| 68 | mymng->width = width;
|
---|
| 69 | mymng->height = height;
|
---|
| 70 | mymng->bpp = 24;
|
---|
| 71 | mymng->effwdt = ((((width * mymng->bpp) + 31) >> 5) << 2);
|
---|
| 72 |
|
---|
| 73 | if (mng->bUseBKGD){
|
---|
| 74 | mymng->nBkgndIndex = 0;
|
---|
| 75 | mymng->nBkgndColor.rgbRed = mng->iBGred >> 8;
|
---|
| 76 | mymng->nBkgndColor.rgbGreen =mng->iBGgreen >> 8;
|
---|
| 77 | mymng->nBkgndColor.rgbBlue = mng->iBGblue >> 8;
|
---|
| 78 | }
|
---|
| 79 |
|
---|
| 80 | mymng->image = (BYTE*)malloc(height * mymng->effwdt);
|
---|
| 81 |
|
---|
| 82 | // tell the mng decoder about our bit-depth choice
|
---|
| 83 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 84 | mng_set_canvasstyle( mng, MNG_CANVAS_RGB8_A8 );
|
---|
| 85 | mymng->alpha = (BYTE*)malloc(height * width);
|
---|
| 86 | #else
|
---|
| 87 | mng_set_canvasstyle( mng, MNG_CANVAS_BGR8);
|
---|
| 88 | mymng->alpha = NULL;
|
---|
| 89 | #endif
|
---|
| 90 | return MNG_TRUE;
|
---|
| 91 | }
|
---|
| 92 |
|
---|
| 93 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 94 | // return a row pointer for the decoder to fill
|
---|
| 95 | static mng_ptr mymnggetcanvasline( mng_handle mng, mng_uint32 line )
|
---|
| 96 | {
|
---|
| 97 | mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 98 | return (mng_ptr)(mymng->image + (mymng->effwdt * (mymng->height - 1 - line)));
|
---|
| 99 | }
|
---|
| 100 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 101 | // return a row pointer for the decoder to fill for alpha channel
|
---|
| 102 | static mng_ptr mymnggetalphaline( mng_handle mng, mng_uint32 line )
|
---|
| 103 | {
|
---|
| 104 | mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 105 | return (mng_ptr)(mymng->alpha + (mymng->width * (mymng->height - 1 - line)));
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 109 | // timer
|
---|
| 110 | static mng_uint32 mymnggetticks(mng_handle mng)
|
---|
| 111 | {
|
---|
| 112 | #ifdef WIN32
|
---|
| 113 | return (mng_uint32)GetTickCount();
|
---|
| 114 | #else
|
---|
| 115 | return 0;
|
---|
| 116 | #endif
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 120 | // Refresh: actual frame need to be updated (Invalidate)
|
---|
| 121 | static mng_bool mymngrefresh(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
|
---|
| 122 | {
|
---|
| 123 | // mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 124 | return MNG_TRUE;
|
---|
| 125 | }
|
---|
| 126 |
|
---|
| 127 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 128 | // interframe delay callback
|
---|
| 129 | static mng_bool mymngsettimer(mng_handle mng, mng_uint32 msecs)
|
---|
| 130 | {
|
---|
| 131 | mngstuff *mymng = (mngstuff *)mng_get_userdata(mng);
|
---|
| 132 | mymng->delay = msecs; // set the timer for when the decoder wants to be woken
|
---|
| 133 | return MNG_TRUE;
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 137 | static 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)
|
---|
| 138 | {
|
---|
| 139 | return mng_cleanup(&mng); //<Arkadiy Olovyannikov>
|
---|
| 140 | }
|
---|
| 141 |
|
---|
| 142 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 143 | // CxImage members
|
---|
| 144 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 145 | CxImageMNG::CxImageMNG(): CxImage(CXIMAGE_FORMAT_MNG)
|
---|
| 146 | {
|
---|
| 147 | hmng = NULL;
|
---|
| 148 | memset(&mnginfo,0,sizeof(mngstuff));
|
---|
| 149 | mnginfo.nBkgndIndex = -1;
|
---|
| 150 | mnginfo.speed = 1.0f;
|
---|
| 151 | }
|
---|
| 152 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 153 | CxImageMNG::~CxImageMNG()
|
---|
| 154 | {
|
---|
| 155 | // cleanup and return
|
---|
| 156 | if (mnginfo.thread){ //close the animation thread
|
---|
| 157 | mnginfo.animation_enabled=0;
|
---|
| 158 | ResumeThread(mnginfo.thread);
|
---|
| 159 | WaitForSingleObject(mnginfo.thread,500);
|
---|
| 160 | CloseHandle(mnginfo.thread);
|
---|
| 161 | }
|
---|
| 162 | // free objects
|
---|
| 163 | if (mnginfo.image) free(mnginfo.image);
|
---|
| 164 | if (mnginfo.alpha) free(mnginfo.alpha);
|
---|
| 165 | if (hmng) mng_cleanup(&hmng); //be sure it's not needed any more. (active timers ?)
|
---|
| 166 | }
|
---|
| 167 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 168 | void CxImageMNG::SetCallbacks(mng_handle mng)
|
---|
| 169 | {
|
---|
| 170 | // set the callbacks
|
---|
| 171 | mng_setcb_errorproc(mng, mymngerror);
|
---|
| 172 | mng_setcb_openstream(mng, mymngopenstream);
|
---|
| 173 | mng_setcb_closestream(mng, mymngclosestream);
|
---|
| 174 | mng_setcb_readdata(mng, mymngreadstream);
|
---|
| 175 | mng_setcb_processheader(mng, mymngprocessheader);
|
---|
| 176 | mng_setcb_getcanvasline(mng, mymnggetcanvasline);
|
---|
| 177 | mng_setcb_refresh(mng, mymngrefresh);
|
---|
| 178 | mng_setcb_gettickcount(mng, mymnggetticks);
|
---|
| 179 | mng_setcb_settimer(mng, mymngsettimer);
|
---|
| 180 | mng_setcb_refresh(mng, mymngrefresh);
|
---|
| 181 | mng_setcb_getalphaline(mng, mymnggetalphaline);
|
---|
| 182 | }
|
---|
| 183 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 184 | // can't use the CxImage implementation because it looses mnginfo
|
---|
| 185 | bool CxImageMNG::Load(const TCHAR * imageFileName){
|
---|
| 186 | FILE* hFile; //file handle to read the image
|
---|
| 187 | #ifdef WIN32
|
---|
| 188 | if ((hFile=_tfopen(imageFileName,_T("rb")))==NULL) return false; // For UNICODE support
|
---|
| 189 | #else
|
---|
| 190 | if ((hFile=fopen(imageFileName,"rb"))==NULL) return false;
|
---|
| 191 | #endif
|
---|
| 192 | bool bOK = Decode(hFile);
|
---|
| 193 | fclose(hFile);
|
---|
| 194 | return bOK;
|
---|
| 195 | }
|
---|
| 196 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 197 | #if CXIMAGE_SUPPORT_DECODE
|
---|
| 198 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 199 | bool CxImageMNG::Decode(CxFile *hFile)
|
---|
| 200 | {
|
---|
| 201 | if (hFile == NULL) return false;
|
---|
| 202 |
|
---|
| 203 | cx_try
|
---|
| 204 | {
|
---|
| 205 | // set up the mng decoder for our stream
|
---|
| 206 | hmng = mng_initialize(&mnginfo, mymngalloc, mymngfree, MNG_NULL);
|
---|
| 207 | if (hmng == NULL) cx_throw("could not initialize libmng");
|
---|
| 208 |
|
---|
| 209 | // set the file we want to play
|
---|
| 210 | mnginfo.file = hFile;
|
---|
| 211 |
|
---|
| 212 | // Set the colorprofile, lcms uses this:
|
---|
| 213 | mng_set_srgb(hmng, MNG_TRUE );
|
---|
| 214 | // Set white as background color:
|
---|
| 215 | WORD Red,Green,Blue;
|
---|
| 216 | Red = Green = Blue = (255 << 8) + 255;
|
---|
| 217 | mng_set_bgcolor(hmng, Red, Green, Blue );
|
---|
| 218 | // If PNG Background is available, use it:
|
---|
| 219 | mng_set_usebkgd(hmng, MNG_TRUE );
|
---|
| 220 |
|
---|
| 221 | // No need to store chunks:
|
---|
| 222 | mng_set_storechunks(hmng, MNG_FALSE);
|
---|
| 223 | // No need to wait: straight reading
|
---|
| 224 | mng_set_suspensionmode(hmng, MNG_FALSE);
|
---|
| 225 |
|
---|
| 226 | SetCallbacks(hmng);
|
---|
| 227 |
|
---|
| 228 | mng_datap pData = (mng_datap)hmng;
|
---|
| 229 |
|
---|
| 230 | // read in the image
|
---|
| 231 | info.nNumFrames=0;
|
---|
| 232 | int retval=MNG_NOERROR;
|
---|
| 233 |
|
---|
| 234 | retval = mng_readdisplay(hmng);
|
---|
| 235 |
|
---|
| 236 | if (retval != MNG_NOERROR && retval != MNG_NEEDTIMERWAIT){
|
---|
| 237 | mng_store_error(hmng,retval,0,0);
|
---|
| 238 | if (hmng->zErrortext){
|
---|
| 239 | cx_throw(hmng->zErrortext);
|
---|
| 240 | } else {
|
---|
| 241 | cx_throw("Error in MNG file");
|
---|
| 242 | }
|
---|
| 243 | }
|
---|
| 244 |
|
---|
| 245 | if (info.nEscape == -1) {
|
---|
| 246 | // Return output dimensions only
|
---|
| 247 | head.biWidth = hmng->iWidth;
|
---|
| 248 | head.biHeight = hmng->iHeight;
|
---|
| 249 | info.dwType = CXIMAGE_FORMAT_MNG;
|
---|
| 250 | return true;
|
---|
| 251 | }
|
---|
| 252 |
|
---|
| 253 | // read all
|
---|
| 254 | while(pData->bReading){
|
---|
| 255 | retval = mng_display_resume(hmng);
|
---|
| 256 | info.nNumFrames++;
|
---|
| 257 | }
|
---|
| 258 |
|
---|
| 259 | // single frame check:
|
---|
| 260 | if (retval != MNG_NEEDTIMERWAIT){
|
---|
| 261 | info.nNumFrames--;
|
---|
| 262 | } else {
|
---|
| 263 | mnginfo.animation=1;
|
---|
| 264 | }
|
---|
| 265 |
|
---|
| 266 | if (info.nNumFrames<=0) info.nNumFrames=1;
|
---|
| 267 |
|
---|
| 268 | if (mnginfo.animation_enabled==0){
|
---|
| 269 | // select the frame
|
---|
| 270 | if (info.nFrame>=0 && info.nFrame<info.nNumFrames){
|
---|
| 271 | for (int n=0;n<info.nFrame;n++) mng_display_resume(hmng);
|
---|
| 272 | } else cx_throw("Error: frame not present in MNG file");
|
---|
| 273 | }
|
---|
| 274 |
|
---|
| 275 | if (mnginfo.nBkgndIndex >= 0){
|
---|
| 276 | info.nBkgndIndex = mnginfo.nBkgndIndex;
|
---|
| 277 | info.nBkgndColor.rgbRed = mnginfo.nBkgndColor.rgbRed;
|
---|
| 278 | info.nBkgndColor.rgbGreen = mnginfo.nBkgndColor.rgbGreen;
|
---|
| 279 | info.nBkgndColor.rgbBlue = mnginfo.nBkgndColor.rgbBlue;
|
---|
| 280 | }
|
---|
| 281 |
|
---|
| 282 | //store the newly created image
|
---|
| 283 | if (Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG)){
|
---|
| 284 | memcpy(GetBits(), mnginfo.image, info.dwEffWidth * head.biHeight);
|
---|
| 285 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 286 | SwapRGB2BGR();
|
---|
| 287 | AlphaCreate();
|
---|
| 288 | if(AlphaIsValid() && mnginfo.alpha){
|
---|
| 289 | memcpy(AlphaGetPointer(),mnginfo.alpha,mnginfo.width * mnginfo.height);
|
---|
| 290 | }
|
---|
| 291 | #endif
|
---|
| 292 | } else cx_throw("CxImageMNG::Decode cannot create image");
|
---|
| 293 |
|
---|
| 294 |
|
---|
| 295 | } cx_catch {
|
---|
| 296 | if (strcmp(message,"")) strncpy(info.szLastError,message,255);
|
---|
| 297 | return false;
|
---|
| 298 | }
|
---|
| 299 | return true;
|
---|
| 300 | }
|
---|
| 301 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 302 | #endif //CXIMAGE_SUPPORT_DECODE
|
---|
| 303 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 304 | #if CXIMAGE_SUPPORT_ENCODE
|
---|
| 305 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 306 | bool CxImageMNG::Encode(CxFile *hFile)
|
---|
| 307 | {
|
---|
| 308 | if (EncodeSafeCheck(hFile)) return false;
|
---|
| 309 |
|
---|
| 310 | cx_try
|
---|
| 311 | {
|
---|
| 312 | if (head.biClrUsed != 0) cx_throw("MNG encoder can save only RGB images");
|
---|
| 313 | // set the file we want to play
|
---|
| 314 | mnginfo.file = hFile;
|
---|
| 315 | mnginfo.bpp = head.biBitCount;
|
---|
| 316 | mnginfo.effwdt = info.dwEffWidth;
|
---|
| 317 | mnginfo.height = head.biHeight;
|
---|
| 318 | mnginfo.width = head.biWidth;
|
---|
| 319 |
|
---|
| 320 | mnginfo.image = (BYTE*)malloc(head.biSizeImage);
|
---|
| 321 | if (mnginfo.image == NULL) cx_throw("could not allocate memory for MNG");
|
---|
| 322 | memcpy(mnginfo.image,info.pImage, head.biSizeImage);
|
---|
| 323 |
|
---|
| 324 | // set up the mng decoder for our stream
|
---|
| 325 | hmng = mng_initialize(&mnginfo, mymngalloc, mymngfree, MNG_NULL);
|
---|
| 326 | if (hmng == NULL) cx_throw("could not initialize libmng");
|
---|
| 327 |
|
---|
| 328 | mng_setcb_openstream(hmng, mymngopenstreamwrite );
|
---|
| 329 | mng_setcb_closestream(hmng, mymngclosestream);
|
---|
| 330 | mng_setcb_writedata(hmng, mymngwritestream);
|
---|
| 331 |
|
---|
| 332 | // Write File:
|
---|
| 333 | mng_create(hmng);
|
---|
| 334 | // Just a single Frame (save a normal PNG):
|
---|
| 335 | WritePNG(hmng, 0, 1 );
|
---|
| 336 | // Now write file:
|
---|
| 337 | mng_write(hmng);
|
---|
| 338 |
|
---|
| 339 | } cx_catch {
|
---|
| 340 | if (strcmp(message,"")) strncpy(info.szLastError,message,255);
|
---|
| 341 | return false;
|
---|
| 342 | }
|
---|
| 343 | return true;
|
---|
| 344 | }
|
---|
| 345 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 346 | // Writes a single PNG datastream
|
---|
| 347 | void CxImageMNG::WritePNG( mng_handle hMNG, int Frame, int FrameCount )
|
---|
| 348 | {
|
---|
| 349 | mngstuff *mymng = (mngstuff *)mng_get_userdata(hMNG);
|
---|
| 350 |
|
---|
| 351 | int OffsetX=0,OffsetY=0,OffsetW=mymng->width,OffsetH=mymng->height;
|
---|
| 352 |
|
---|
| 353 | BYTE *tmpbuffer = new BYTE[ (mymng->effwdt+1) * mymng->height];
|
---|
| 354 | if( tmpbuffer == 0 ) return;
|
---|
| 355 |
|
---|
| 356 | // Write DEFI chunk.
|
---|
| 357 | mng_putchunk_defi( hMNG, 0, 0, 0, MNG_TRUE, OffsetX, OffsetY, MNG_FALSE, 0, 0, 0, 0 );
|
---|
| 358 |
|
---|
| 359 | // Write Header:
|
---|
| 360 | mng_putchunk_ihdr(
|
---|
| 361 | hMNG,
|
---|
| 362 | OffsetW, OffsetH,
|
---|
| 363 | MNG_BITDEPTH_8,
|
---|
| 364 | MNG_COLORTYPE_RGB,
|
---|
| 365 | MNG_COMPRESSION_DEFLATE,
|
---|
| 366 | MNG_FILTER_ADAPTIVE,
|
---|
| 367 | MNG_INTERLACE_NONE
|
---|
| 368 | );
|
---|
| 369 |
|
---|
| 370 | // transfer data, add Filterbyte:
|
---|
| 371 | for( int Row=0; Row<OffsetH; Row++ ){
|
---|
| 372 | // First Byte in each Scanline is Filterbyte: Currently 0 -> No Filter.
|
---|
| 373 | tmpbuffer[Row*(mymng->effwdt+1)]=0;
|
---|
| 374 | // Copy the scanline: (reverse order)
|
---|
| 375 | memcpy(tmpbuffer+Row*(mymng->effwdt+1)+1,
|
---|
| 376 | mymng->image+((OffsetH-1-(OffsetY+Row))*(mymng->effwdt))+OffsetX,mymng->effwdt);
|
---|
| 377 | // swap red and blue components
|
---|
| 378 | RGBtoBGR(tmpbuffer+Row*(mymng->effwdt+1)+1,mymng->effwdt);
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 | // Compress data with ZLib (Deflate):
|
---|
| 382 | BYTE *dstbuffer = new BYTE[(mymng->effwdt+1)*OffsetH];
|
---|
| 383 | if( dstbuffer == 0 ) return;
|
---|
| 384 | DWORD dstbufferSize=(mymng->effwdt+1)*OffsetH;
|
---|
| 385 |
|
---|
| 386 | // Compress data:
|
---|
| 387 | if(Z_OK != compress2((Bytef *)dstbuffer,(ULONG *)&dstbufferSize,(const Bytef*)tmpbuffer,
|
---|
| 388 | (ULONG) (mymng->effwdt+1)*OffsetH,9 )) return;
|
---|
| 389 |
|
---|
| 390 | // Write Data into MNG File:
|
---|
| 391 | mng_putchunk_idat( hMNG, dstbufferSize, (mng_ptr*)dstbuffer);
|
---|
| 392 | mng_putchunk_iend(hMNG);
|
---|
| 393 |
|
---|
| 394 | // Free the stuff:
|
---|
| 395 | delete [] tmpbuffer;
|
---|
| 396 | delete [] dstbuffer;
|
---|
| 397 | }
|
---|
| 398 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 399 | long CxImageMNG::Resume()
|
---|
| 400 | {
|
---|
| 401 | if (MNG_NEEDTIMERWAIT == mng_display_resume(hmng)){
|
---|
| 402 | if (info.pImage==NULL){
|
---|
| 403 | Create(mnginfo.width,mnginfo.height,mnginfo.bpp, CXIMAGE_FORMAT_MNG);
|
---|
| 404 | }
|
---|
| 405 | if (IsValid()){
|
---|
| 406 | memcpy(GetBits(), mnginfo.image, info.dwEffWidth * head.biHeight);
|
---|
| 407 | #if CXIMAGE_SUPPORT_ALPHA
|
---|
| 408 | SwapRGB2BGR();
|
---|
| 409 | AlphaCreate();
|
---|
| 410 | if(AlphaIsValid() && mnginfo.alpha){
|
---|
| 411 | memcpy(AlphaGetPointer(),mnginfo.alpha,mnginfo.width * mnginfo.height);
|
---|
| 412 | }
|
---|
| 413 | #endif
|
---|
| 414 | }
|
---|
| 415 | } else {
|
---|
| 416 | mnginfo.animation_enabled = 0;
|
---|
| 417 | }
|
---|
| 418 | return mnginfo.animation_enabled;
|
---|
| 419 | }
|
---|
| 420 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 421 | void CxImageMNG::SetSpeed(float speed)
|
---|
| 422 | {
|
---|
| 423 | if (speed>10.0) mnginfo.speed = 10.0f;
|
---|
| 424 | else if (speed<0.1) mnginfo.speed = 0.1f;
|
---|
| 425 | else mnginfo.speed=speed;
|
---|
| 426 | }
|
---|
| 427 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 428 | #endif //CXIMAGE_SUPPORT_ENCODE
|
---|
| 429 | ////////////////////////////////////////////////////////////////////////////////
|
---|
| 430 | #endif // CXIMAGE_SUPPORT_MNG
|
---|