00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifndef NL_BITMAP_H
00027 #define NL_BITMAP_H
00028
00029 #ifdef USE_JPEG
00030 #define XMD_H
00031 #undef FAR
00032 extern "C"
00033 {
00034 #include <jpeglib.h>
00035 }
00036 #endif // USE_JPEG
00037
00038 #include "nel/misc/types_nl.h"
00039 #include "nel/misc/rgba.h"
00040 #include "nel/misc/debug.h"
00041 #include <vector>
00042
00043
00044 namespace NLMISC
00045 {
00046
00047
00048 class IStream;
00049
00050
00051
00052 #ifndef NL_MAKEFOURCC
00053 #define NL_MAKEFOURCC(ch0, ch1, ch2, ch3) \
00054 ((uint32)(uint8)(ch0) | ((uint32)(uint8)(ch1) << 8) | \
00055 ((uint32)(uint8)(ch2) << 16) | ((uint32)(uint8)(ch3) << 24 ))
00056 #endif
00057
00058 const uint32 DDS = NL_MAKEFOURCC('D', 'D', 'S', ' ');
00059 const uint32 DXT_ = NL_MAKEFOURCC('D','X', 'T', '\0');
00060
00061
00062
00063 #define DDSD_LINEARSIZE 0x00080000l
00064
00065
00066
00067
00068
00069 const uint8 MAX_MIPMAP = 16;
00070
00071
00072
00073
00074
00082
00083
00084
00085
00086 class CBitmap
00087 {
00088 protected :
00089 std::vector<uint8> _Data[MAX_MIPMAP];
00090
00091
00092 uint8 _MipMapCount;
00093 bool _LoadGrayscaleAsAlpha;
00094 uint32 _Width;
00095 uint32 _Height;
00096
00097 private :
00098
00099
00106 uint32 blend(uint32 &n0, uint32 &n1, uint32 coef0);
00107
00108
00117 uint8 readDDS(NLMISC::IStream &f, uint mipMapSkip);
00118
00119
00126 uint8 readTGA( NLMISC::IStream &f);
00127
00128
00129
00143
00144 bool convertToDXTC5();
00145
00146 bool convertToRGBA();
00147 bool luminanceToRGBA();
00148 bool alphaToRGBA();
00149 bool alphaLuminanceToRGBA();
00150
00151 bool convertToLuminance();
00152 bool rgbaToLuminance();
00153 bool alphaToLuminance();
00154 bool alphaLuminanceToLuminance();
00155
00156 bool convertToAlpha();
00157 bool rgbaToAlpha();
00158 bool luminanceToAlpha();
00159 bool alphaLuminanceToAlpha();
00160
00161 bool convertToAlphaLuminance();
00162 bool rgbaToAlphaLuminance();
00163 bool luminanceToAlphaLuminance();
00164 bool alphaToAlphaLuminance();
00165
00167
00172 bool decompressDXT1(bool alpha);
00173
00178 bool decompressDXT3();
00179
00180
00185 bool decompressDXT5();
00186
00187
00193 static void uncompress(uint16 color, NLMISC::CRGBA &);
00194
00195
00205 void resamplePicture32 (const NLMISC::CRGBA *pSrc, NLMISC::CRGBA *pDest,
00206 sint32 nSrcWidth, sint32 nSrcHeight,
00207 sint32 nDestWidth, sint32 nDestHeight);
00208
00209
00214 float getColorInterp (float x, float y, float xy00, float xy01, float xy10, float xy11) const;
00215
00216
00218
00219 static CRGBA getDXTCColorFromBlock(const uint8 *block, sint x, sint y);
00220 CRGBA getDXTC1Texel(sint x, sint y, uint32 numMipMap) const;
00221 CRGBA getDXTC3Texel(sint x, sint y, uint32 numMipMap) const;
00222 CRGBA getDXTC5Texel(sint x, sint y, uint32 numMipMap) const;
00224
00225
00226 CRGBA CBitmap::getRGBAPixel(sint x, sint y, uint32 numMipMap ) const;
00227
00228
00229
00230
00231 public:
00232
00233 enum TType
00234 {
00235 RGBA=0,
00236 Luminance,
00237 Alpha,
00238 AlphaLuminance,
00239 DXTC1,
00240 DXTC1Alpha,
00241 DXTC3,
00242 DXTC5,
00243 DsDt,
00244 ModeCount,
00245 DonTKnow=0xffffffff
00246 } PixelFormat;
00247
00248 static const uint32 bitPerPixels[ModeCount];
00249 static const uint32 DXTC1HEADER;
00250 static const uint32 DXTC3HEADER;
00251 static const uint32 DXTC5HEADER;
00252
00253 CBitmap()
00254 {
00255 _MipMapCount = 1;
00256 _Width = 0;
00257 _Height = 0;
00258 PixelFormat = RGBA;
00259 _LoadGrayscaleAsAlpha = true;
00260 }
00261
00262 virtual ~CBitmap() { }
00263
00273 uint8 load(NLMISC::IStream &f, uint mipMapSkip=0);
00274
00275
00286 static void loadSize(NLMISC::IStream &f, uint32 &width, uint32 &height);
00287
00288
00292 static void loadSize(const std::string &path, uint32 &retWidth, uint32 &retHeight);
00293
00294
00298 void makeDummy();
00299
00300
00306
00307 std::vector<uint8>& getPixels(uint32 numMipMap = 0)
00308 {
00309
00310 return _Data[numMipMap];
00311 }
00312 const std::vector<uint8>& getPixels(uint32 numMipMap = 0) const
00313 {
00314
00315 return _Data[numMipMap];
00316 }
00318
00319
00326 bool convertToType (TType type);
00327
00328
00329
00334 TType getPixelFormat() const
00335 {
00336 return PixelFormat;
00337 }
00338
00339
00345 virtual uint32 getWidth(uint32 numMipMap = 0) const;
00346
00347
00353 virtual uint32 getHeight(uint32 numMipMap = 0) const;
00354
00355
00361 uint32 getSize(uint32 numMipMap = 0) const;
00362
00363
00368 uint32 getMipMapCount() const
00369 {
00370 return _MipMapCount;
00371 }
00372
00373
00379 void rotateCCW();
00380
00386 void buildMipMaps();
00387
00393 void releaseMipMaps();
00394
00400 void reset(TType type=RGBA);
00401
00402
00409 void resample (sint32 nNewWidth, sint32 nNewHeight);
00410
00411
00420 void resize (sint32 nNewWidth, sint32 nNewHeight, TType newType=DonTKnow);
00421
00422
00432 void resizeMipMap (uint32 numMipMap, sint32 nNewWidth, sint32 nNewHeight);
00433
00434
00439 void setMipMapCount(uint32 mmc);
00440
00441
00451 bool writeTGA(NLMISC::IStream &f, uint32 d, bool upsideDown = false);
00452
00461 bool writeJPG(NLMISC::IStream &f, uint8 quality = 80);
00462
00469 void loadGrayscaleAsAlpha (bool loadAsAlpha)
00470 {
00471 _LoadGrayscaleAsAlpha=loadAsAlpha;
00472 }
00473
00474
00480 bool isGrayscaleAsAlpha () const
00481 {
00482 return _LoadGrayscaleAsAlpha;
00483 }
00484
00485
00494 bool blit(const CBitmap *src, sint32 x, sint32 y) ;
00495
00496
00502 CRGBAF getColor (float x,float y) const;
00503
00504
00509 CRGBA getPixelColor(sint x, sint y, uint32 numMipMap = 0) const;
00513 void flipH();
00514
00515
00519 void flipV();
00520
00524 void rot90CW();
00525
00529 void rot90CCW();
00530
00538 void blend(const CBitmap &Bm0, const CBitmap &Bm1, uint16 factor);
00539
00540 };
00541
00542
00543
00544
00545 #ifdef USE_JPEG
00546
00547 extern NLMISC::IStream *JPGStream;
00548 extern const uint32 JPGBufferSize = 1000;
00549 extern char JPGBuffer[JPGBufferSize];
00550
00551 static void jpgCompressInit(j_compress_ptr cinfo)
00552 {
00553 cinfo->dest->next_output_byte = (unsigned char *)JPGBuffer;
00554 cinfo->dest->free_in_buffer = JPGBufferSize;
00555 }
00556
00557 static boolean jpgCompressEmpty(j_compress_ptr cinfo)
00558 {
00559 JPGStream->serialBuffer((uint8*) JPGBuffer, JPGBufferSize);
00560 cinfo->dest->next_output_byte = (unsigned char *)JPGBuffer;
00561 cinfo->dest->free_in_buffer = JPGBufferSize;
00562 return TRUE;
00563 }
00564
00565 static void jpgCompressTerm(j_compress_ptr cinfo)
00566 {
00567 if(JPGBufferSize - cinfo->dest->free_in_buffer > 0)
00568 JPGStream->serialBuffer((uint8*) JPGBuffer, JPGBufferSize - cinfo->dest->free_in_buffer);
00569 }
00570
00571 static jpeg_destination_mgr jpgDestinationManager = { 0, 0, jpgCompressInit, jpgCompressEmpty, jpgCompressTerm };
00572
00573 inline bool CBitmap::writeJPG( NLMISC::IStream &f, uint8 quality)
00574 {
00575 if (f.isReading()) return false;
00576 if (PixelFormat != RGBA) return false;
00577
00578 JPGStream = &f;
00579
00580 struct jpeg_compress_struct cinfo;
00581 struct jpeg_error_mgr jerr;
00582 cinfo.err = jpeg_std_error(&jerr);
00583 jpeg_create_compress(&cinfo);
00584
00585 cinfo.image_width = _Width;
00586 cinfo.image_height = _Height;
00587 cinfo.input_components = 3;
00588 cinfo.in_color_space = JCS_RGB;
00589 cinfo.dest = &jpgDestinationManager;
00590 jpeg_set_defaults(&cinfo);
00591 jpeg_set_quality(&cinfo, quality, TRUE );
00592 jpeg_start_compress(&cinfo, TRUE);
00593
00594 JSAMPROW row_pointer[1];
00595 row_pointer[0] = new unsigned char[_Width*3];
00596
00597 while (cinfo.next_scanline < cinfo.image_height)
00598 {
00599 for (uint i = 0; i < _Width; i++)
00600 {
00601 row_pointer[0][i*3+0] = (unsigned char) _Data[0][cinfo.next_scanline * _Width*4 + i*4+0];
00602 row_pointer[0][i*3+1] = (unsigned char) _Data[0][cinfo.next_scanline * _Width*4 + i*4+1];
00603 row_pointer[0][i*3+2] = (unsigned char) _Data[0][cinfo.next_scanline * _Width*4 + i*4+2];
00604 }
00605 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
00606 }
00607 jpeg_finish_compress(&cinfo);
00608 jpeg_destroy_compress(&cinfo);
00609 delete row_pointer[0];
00610 row_pointer[0] = NULL;
00611 JPGStream = NULL;
00612
00613 return true;
00614 }
00615 #else // USE_JPEG
00616 inline bool CBitmap::writeJPG( NLMISC::IStream &f, uint8 quality)
00617 {
00618 nlwarning ("You must put #define USE_JPEG before all include in the file where you call writeJPG() if you want jpeg support");
00619 }
00620 #endif // USE_JPEG
00621
00622
00623
00624
00625 }
00626
00627
00628 #endif // NL_BITMAP_H
00629
00630