bitmapMng.cpp
Engine/source/gfx/bitmap/loaders/bitmapMng.cpp
Classes:
class
class
Public Defines
define
define
define
define
define
define
Public Variables
struct _privateRegisterMNG
Public Functions
mng_ptr
mngCanvasLineFn(mng_handle mng, mng_uint32 line)
mng_bool
mngCloseDataFn(mng_handle mng)
mng_bool
mngFatalErrorFn(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text)
mng_uint32
mngGetTicksFn(mng_handle mng)
mng_ptr
mngMallocFn(mng_size_t size)
mng_bool
mngOpenDataFn(mng_handle mng)
mng_bool
mngProcessHeaderFn(mng_handle mng, mng_uint32 width, mng_uint32 height)
mng_bool
mngReadDataFn(mng_handle mng, mng_ptr data, mng_uint32 length, mng_uint32 * bytesread)
mng_bool
mngRefreshFn(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
mng_bool
mngSetTimerFn(mng_handle mng, mng_uint32 msecs)
Detailed Description
Public Defines
MNG_ACCESS_CHUNKS()
MNG_NO_CMS()
MNG_STORE_CHUNKS()
MNG_SUPPORT_DISPLAY()
MNG_SUPPORT_READ()
MNG_SUPPORT_WRITE()
Public Variables
struct _privateRegisterMNG sStaticRegisterMNG
Public Functions
mngCanvasLineFn(mng_handle mng, mng_uint32 line)
mngCloseDataFn(mng_handle mng)
mngFatalErrorFn(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text)
mngFreeFn(mng_ptr p, mng_size_t size)
mngGetTicksFn(mng_handle mng)
mngMallocFn(mng_size_t size)
mngOpenDataFn(mng_handle mng)
mngProcessHeaderFn(mng_handle mng, mng_uint32 width, mng_uint32 height)
mngReadDataFn(mng_handle mng, mng_ptr data, mng_uint32 length, mng_uint32 * bytesread)
mngRefreshFn(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h)
mngSetTimerFn(mng_handle mng, mng_uint32 msecs)
sReadMNG(Stream & stream, GBitmap * bitmap)
sWriteMNG(GBitmap * bitmap, Stream & stream, U32 compressionLevel)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "core/stream/stream.h" 25 26#include "gfx/bitmap/gBitmap.h" 27 28#include "core/color.h" 29 30#define MNG_NO_CMS 31#define MNG_SUPPORT_READ 32#define MNG_SUPPORT_WRITE 33#define MNG_SUPPORT_DISPLAY 34#define MNG_STORE_CHUNKS 35#define MNG_ACCESS_CHUNKS 36 37#include "lmng/libmng.h" 38 39 40 41static bool sReadMNG(Stream &stream, GBitmap *bitmap); 42static bool sWriteMNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel); 43 44static struct _privateRegisterMNG 45{ 46 _privateRegisterMNG() 47 { 48 GBitmap::Registration reg; 49 50 reg.extensions.push_back( "jng" ); 51 reg.extensions.push_back( "mng" ); 52 53 reg.readFunc = sReadMNG; 54 reg.writeFunc = sWriteMNG; 55 56 GBitmap::sRegisterFormat( reg ); 57 } 58} sStaticRegisterMNG; 59 60 61typedef struct 62{ 63 GBitmap* image; 64 Stream* stream; 65} mngstuff; 66 67static mng_ptr mngMallocFn(mng_size_t size) 68{ 69 mng_ptr data = dMalloc(size); 70 return dMemset(data, 0, size); 71} 72 73static void mngFreeFn(mng_ptr p, mng_size_t size) 74{ 75 dFree(p); 76} 77 78static mng_bool mngOpenDataFn(mng_handle mng) 79{ 80 return MNG_TRUE; 81} 82 83static mng_bool mngCloseDataFn(mng_handle mng) 84{ 85 return MNG_TRUE; 86} 87 88static mng_bool mngReadDataFn(mng_handle mng, mng_ptr data, mng_uint32 length, mng_uint32 *bytesread) 89{ 90 mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); 91 AssertFatal(mymng->stream != NULL, "No stream?"); 92 93 bool success = mymng->stream->read(length, data); 94 *bytesread = length; // stupid hack 95 96 AssertFatal(success, "MNG read catastrophic error!"); 97 if(success) 98 return MNG_TRUE; 99 else 100 return MNG_FALSE; 101} 102 103#if 0 104// CodeReview - until we can write these, get rid of warning by disabling method. 105static mng_bool mngWriteDataFn(mng_handle mng, mng_ptr data, mng_uint32 length, mng_uint32 *iWritten) 106{ 107 mngstuff *)mng_get_userdata(mng); 108 NULL, "No stream?"); 109 110 bool success = mymng->write(length, data); 111 *iWritten = length; // stupid hack 112 113 AssertFatal(success, "MNG write catastrophic error!"); 114 if(success) 115 return MNG_TRUE; 116 else 117 return MNG_FALSE; 118} 119#endif 120 121static mng_bool mngProcessHeaderFn(mng_handle mng, mng_uint32 width, mng_uint32 height) 122{ 123 mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); 124 125 GFXFormat format; 126 mng_uint8 colorType = mng_get_colortype(mng); 127 mng_uint8 alphaDepth = mng_get_alphadepth(mng); 128 switch(colorType) 129 { 130 case MNG_COLORTYPE_GRAY: 131 case MNG_COLORTYPE_JPEGGRAY: 132 format = GFXFormatR8G8B8; 133 mng_set_canvasstyle(mng, MNG_CANVAS_RGB8); 134 break; 135 136 case MNG_COLORTYPE_INDEXED: 137 if(alphaDepth >= 1) 138 { 139 format = GFXFormatR8G8B8A8; 140 mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8); 141 } 142 else 143 { 144 format = GFXFormatR8G8B8; 145 mng_set_canvasstyle(mng, MNG_CANVAS_RGB8); 146 } 147 148 case MNG_COLORTYPE_RGB: 149 case MNG_COLORTYPE_JPEGCOLOR: 150 if(alphaDepth >= 1) 151 { 152 format = GFXFormatR8G8B8A8; 153 mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8); 154 } 155 else 156 { 157 format = GFXFormatR8G8B8; 158 mng_set_canvasstyle(mng, MNG_CANVAS_RGB8); 159 } 160 break; 161 162 case MNG_COLORTYPE_RGBA: 163 case MNG_COLORTYPE_JPEGCOLORA: 164 format = GFXFormatR8G8B8A8; 165 mng_set_canvasstyle(mng, MNG_CANVAS_RGBA8); 166 break; 167 168 default: 169 // This case should never get hit, however it resolves a compiler 170 // warning 171 format = GFXFormat_FIRST; 172 AssertISV( false, "Unknown color format in bitmap MNG Loading" ); 173 } 174 175 mymng->image->allocateBitmap(width, height, false, format); 176 return MNG_TRUE; 177} 178 179static mng_ptr mngCanvasLineFn(mng_handle mng, mng_uint32 line) 180{ 181 mngstuff *mymng = (mngstuff *)mng_get_userdata(mng); 182 return (mng_ptr) mymng->image->getAddress(0, line); 183} 184 185static mng_bool mngRefreshFn(mng_handle mng, mng_uint32 x, mng_uint32 y, mng_uint32 w, mng_uint32 h) 186{ 187 return MNG_TRUE; 188} 189 190static mng_uint32 mngGetTicksFn(mng_handle mng) 191{ 192 return 0; 193} 194 195static mng_bool mngSetTimerFn(mng_handle mng, mng_uint32 msecs) 196{ 197 return MNG_TRUE; 198} 199 200static mng_bool mngFatalErrorFn(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, mng_int32 extra1, mng_int32 extra2, mng_pchar text) 201{ 202 mng_cleanup(&mng); 203 204 AssertISV(false, avar("Error reading MNG file:\n %s", (const char*)text)); 205 return MNG_FALSE; 206} 207 208static bool sReadMNG(Stream &stream, GBitmap *bitmap) 209{ 210 mngstuff mnginfo; 211 dMemset(&mnginfo, 0, sizeof(mngstuff)); 212 213 mng_handle mng = mng_initialize(&mnginfo, mngMallocFn, mngFreeFn, MNG_NULL); 214 if(mng == NULL) 215 return false; 216 217 // setup the callbacks 218 mng_setcb_errorproc(mng, mngFatalErrorFn); 219 mng_setcb_openstream(mng, mngOpenDataFn); 220 mng_setcb_closestream(mng, mngCloseDataFn); 221 mng_setcb_readdata(mng, mngReadDataFn); 222 mng_setcb_processheader(mng, mngProcessHeaderFn); 223 mng_setcb_getcanvasline(mng, mngCanvasLineFn); 224 mng_setcb_refresh(mng, mngRefreshFn); 225 mng_setcb_gettickcount(mng, mngGetTicksFn); 226 mng_setcb_settimer(mng, mngSetTimerFn); 227 228 mnginfo.image = bitmap; 229 mnginfo.stream = &stream; 230 231 mng_read(mng); 232 mng_display(mng); 233 234 // hacks :( 235 // libmng doesn't support returning data in gray/gray alpha format, 236 // so we grab as RGB/RGBA and just cut off the g and b 237 mng_uint8 colorType = mng_get_colortype(mng); 238 switch(colorType) 239 { 240 case MNG_COLORTYPE_GRAY: 241 case MNG_COLORTYPE_JPEGGRAY: 242 { 243 GBitmap temp(*bitmap); 244 bitmap->deleteImage(); 245 bitmap->allocateBitmap(temp.getWidth(), temp.getHeight(), false, GFXFormatA8); 246 247 // force getColor to read in in the same color value for each channel 248 // since the gray colortype has the real alpha in the first channel 249 temp.setFormat( GFXFormatA8 ); 250 251 ColorI color; 252 for(U32 row = 0; row < bitmap->getHeight(); row++) 253 { 254 for(U32 col = 0; col < bitmap->getWidth(); col++) 255 { 256 temp.getColor(col, row, color); 257 bitmap->setColor(col, row, color); 258 } 259 } 260 } 261 262 break; 263 } 264 265 mng_cleanup(&mng); 266 267 // Check this bitmap for transparency 268 bitmap->checkForTransparency(); 269 270 return true; 271} 272 273static bool sWriteMNG(GBitmap *bitmap, Stream &stream, U32 compressionLevel) 274{ 275 TORQUE_UNUSED( bitmap ); 276 TORQUE_UNUSED( stream ); 277 TORQUE_UNUSED( compressionLevel ); 278 279 return false; 280#if 0 281 // ONLY RGB bitmap writing supported at this time! 282 GFXFormatA8, "GBitmap::writeMNG: ONLY RGB bitmap writing supported at this time."); 283 if(getFormat() != GFXFormatA8) 284 return (false); 285 286 // maximum image size allowed 287 #define MAX_HEIGHT 4096 288 if(getHeight() >= MAX_HEIGHT) 289 return false; 290 291 mngstuff mnginfo; 292 mngstuff)); 293 mng_handle mng = mng_initialize(&mnginfo, mngMallocFn, mngFreeFn, MNG_NULL); 294 if(mng == NULL) { 295 return false; 296 } 297 298 // setup the callbacks 299 mng_setcb_openstream(mng, mngOpenDataFn); 300 mng_setcb_closestream(mng, mngCloseDataFn); 301 mng_setcb_writedata(mng, mngWriteDataFn); 302 303 // create the file in memory 304 mng_create(mng); 305 306 mng_putchunk_defi(mng, 0, 0, 0, MNG_FALSE, 0, 0, MNG_FALSE, 0, getWidth(), 0, getHeight()); 307 308 mnginfo.GBitmap*)this; 309 mnginfo.stream = &stream; 310 311 switch(getFormat()) { 312 case GFXFormatA8: 313 mng_putchunk_ihdr(mng, getWidth(), getHeight(), 314 MNG_BITDEPTH_8, 315 MNG_COLORTYPE_GRAY, 316 MNG_COMPRESSION_DEFLATE, 317 MNG_FILTER_ADAPTIVE, 318 MNG_INTERLACE_NONE); 319 320 // not implemented in lib yet 321 //mng_putimgdata_ihdr(mng, getWidth(), getHeight(), 322 // MNG_COLORTYPE_GRAY, 323 // MNG_BITDEPTH_8, 324 // MNG_COMPRESSION_DEFLATE, 325 // MNG_FILTER_ADAPTIVE, 326 // MNG_INTERLACE_NONE, 327 // MNG_CANVAS_GRAY8, mngCanvasLineFn); 328 break; 329 case GFXFormatR8G8B8: 330 mng_putchunk_ihdr(mng, getWidth(), getHeight(), 331 MNG_BITDEPTH_8, 332 MNG_COLORTYPE_RGB, 333 MNG_COMPRESSION_DEFLATE, 334 MNG_FILTER_ADAPTIVE, 335 MNG_INTERLACE_NONE); 336 337 // not implemented in lib yet 338 //mng_putimgdata_ihdr(mng, getWidth(), getHeight(), 339 // MNG_COLORTYPE_RGB, 340 // MNG_BITDEPTH_8, 341 // MNG_COMPRESSION_DEFLATE, 342 // MNG_FILTER_ADAPTIVE, 343 // MNG_INTERLACE_NONE, 344 // MNG_CANVAS_RGB8, mngCanvasLineFn); 345 break; 346 case GFXFormatR8G8B8A8: 347 mng_putchunk_ihdr(mng, getWidth(), getHeight(), 348 MNG_BITDEPTH_8, 349 MNG_COLORTYPE_RGBA, 350 MNG_COMPRESSION_DEFLATE, 351 MNG_FILTER_ADAPTIVE, 352 MNG_INTERLACE_NONE); 353 354 // not implemented in lib yet 355 //mng_putimgdata_ihdr(mng, getWidth(), getHeight(), 356 // MNG_COLORTYPE_RGBA, 357 // MNG_BITDEPTH_8, 358 // MNG_COMPRESSION_DEFLATE, 359 // MNG_FILTER_ADAPTIVE, 360 // MNG_INTERLACE_NONE, 361 // MNG_CANVAS_RGBA8, mngCanvasLineFn); 362 break; 363 } 364 365 366 // below is a hack until libmng is mature enough to handle this itself 367 //----------------------------------------------------------------------------- 368 369 370 U8[this->byteSize + getHeight()]; 371 if(tmpbuffer == 0) 372 { 373 mng_cleanup(&mng); 374 return false; 375 } 376 377 // transfer data, add filterbyte 378 U32 effwdt = getWidth() * this->bytesPerPixel; 379 for(U32 Row = 0; Row < getHeight(); Row++) 380 { 381 // first Byte in each scanline is filterbyte: currently 0 -> no filter 382 tmpbuffer[Row * (effwdt + 1)] = 0; 383 384 // copy the scanline 385 dMemcpy(tmpbuffer + Row * (effwdt + 1) + 1, getAddress(0, Row), effwdt); 386 } 387 388 // compress data with zlib 389 U8[this->byteSize + getHeight()]; 390 if(dstbuffer == 0) 391 { 392 delete [] tmpbuffer; 393 mng_cleanup(&mng); 394 return false; 395 } 396 397 U32 dstbufferSize = this->byteSize + getHeight(); 398 if(Z_OK != compress2((Bytef*)dstbuffer,(uLongf*)&dstbufferSize, (const Bytef*)tmpbuffer, dstbufferSize, 9)) 399 { 400 delete [] tmpbuffer; 401 delete [] dstbuffer; 402 mng_cleanup(&mng); 403 return false; 404 } 405 406 mng_putchunk_idat(mng, dstbufferSize, (mng_ptr*)dstbuffer); 407 408 409 //----------------------------------------------------------------------------- 410 411 412 mng_putchunk_iend(mng); 413 414 delete [] tmpbuffer; 415 delete [] dstbuffer; 416 417 mng_write(mng); 418 mng_cleanup(&mng); 419 420 return true; 421#endif 422} 423
