C'est un loader d'image BLP (utiliser par warcraft 3, warcraft 3 frozen trone, et wow, correspondant au revision 0, 1, 2)
ce loader implementes toutes les features du format, mais seulement le premier niveaux de mipmap est charger à cause de l'architecture d'irrlicht
de tout façon le mipmap peut-être régénéré quand l'image est transformaer en texture avec une feature du driver d'irrlicht
pour la compilation, je sugère d'ajouter le dossier jpeglib du dossier des sources d'irrlicht pour que les informations coincide avec le header
Code c++ :
#ifndef __C_BLP_IMAGE_LOADER_H_INCLUDED__
#define __C_BLP_IMAGE_LOADER_H_INCLUDED__
#include "IrrCompileConfig.h"
#define _IRR_COMPILE_WITH_BLP_LOADER_
#ifdef _IRR_COMPILE_WITH_BLP_LOADER_
#include <IImageLoader.h>
namespace irr{ namespace video { struct sharedheader
; class IVideoDriver; class CImageLoaderBLP
: public IImageLoader
{ protected: enum Compression
: int { JPG
= 0, BLP
= 1, RAW
= 2, DXT
= 3 }; public: CImageLoaderBLP
(IVideoDriver*); virtual ~CImageLoaderBLP
(); virtual bool isALoadableFileExtension
(const io::path
& filename
) const; virtual bool isALoadableFileFormat
(io::IReadFile* file
) const; virtual IImage* loadImage
(io::IReadFile* file
) const; protected: IImage* decompressBLP
(const sharedheader
&, char *, size_t
) const; IImage* decompressDXT
(const sharedheader
&, char *, size_t
) const; IImage* decompressRaw
(const sharedheader
&, char *, size_t
) const; IImage* decompressJpg
(const sharedheader
&, char *, size_t
) const; private: IVideoDriver *driver
; }; IImageLoader
* createImageLoaderBLP
(); }}#endif
#endif
Code c++ :
#include "CImageLoaderBLP.h"
#ifdef _IRR_COMPILE_WITH_BLP_LOADER_
#include <IVideoDriver.h>
#include <IReadFile.h>
#include <IImage.h>
#include <irrString.h>
#include <iostream>
#include "jpeglib.h"
namespace irr{ namespace video { struct sharedheader
{ u32 compression
; u32 flags
; u32 width
; u32 height
; u32 alpha_depth
; u32 mipmap_offsets
[16]; u32 mipmap_lengths
[16]; u32 palette
[265]; }; struct blpheader
{ u32 compression
; u32 flags
; u32 width
; u32 height
; u32 alpha_depth
; u32 pictureSubType
; u32 mipmap_offsets
[16]; u32 mipmap_lengths
[16]; }; struct blp2header
{ u32 type
; u8 compression
; u8 alpha_depth
; u8 alpha_type
; u8 has_mips
; u32 width
; u32 height
; u32 mipmap_offsets
[16]; u32 mipmap_lengths
[16]; }; CImageLoaderBLP
::CImageLoaderBLP
(irr::video::IVideoDriver *d
) : driver
(d
) { #ifdef _DEBUG
setDebugName
("CImageLoaderBLP"); #endif
} CImageLoaderBLP
::~CImageLoaderBLP
() { } bool CImageLoaderBLP
::isALoadableFileExtension
(const io::path
& filename
) const { return core::hasFileExtension
(filename
, "blp"); } bool CImageLoaderBLP
::isALoadableFileFormat
(io::IReadFile* file
) const { if(!file
) return false; char buf
[4]; file
->read
(buf
, 4); return buf
[0] == 'B' && buf
[1] == 'L' && buf
[2] == 'P' && (buf
[3] == '2' || buf
[3] == '1' || buf
[3] == '0'); } IImage* CImageLoaderBLP
::loadImage
(io::IReadFile* file
) const { if(!file
) return 0; char blpid
[4]; file
->read
(blpid
, 4); if(blpid
[0] != 'B' || blpid
[1] != 'L' || blpid
[2] != 'P' ||
!(blpid
[3] == '2' || blpid
[3] == '1' || blpid
[3] == '0')) return 0; sharedheader shd
; if(blpid
[3] < '2') { std
::cout
<< "war3 revision" << std
::endl
; blpheader header
; file
->read
(&header
, sizeof(blpheader
)); shd
.compression
= header
.compression
; shd
.flags
= header
.flags
; shd
.width
= header
.width
; shd
.height
= header
.height
; shd
.alpha_depth
= header
.alpha_depth
; for(int i
= 0; i
<16; ++i
) { shd
.mipmap_offsets
[i
] = header
.mipmap_offsets
[i
]; shd
.mipmap_lengths
[i
] = header
.mipmap_lengths
[i
]; } } else { std
::cout
<< "wow revision" << std
::endl
; blp2header header
; file
->read
(&header
, sizeof(blp2header
)); shd
.flags
= header
.alpha_type
; shd
.width
= header
.width
; shd
.height
= header
.height
; shd
.alpha_depth
= header
.alpha_depth
; for(int i
= 0; i
<16; ++i
) { shd
.mipmap_offsets
[i
] = header
.mipmap_offsets
[i
]; shd
.mipmap_lengths
[i
] = header
.mipmap_lengths
[i
]; } if(header
.type
== 0) shd
.compression
= JPG
; else { switch(header
.compression
) { case 1: shd
.compression
= BLP
; break; case 2: shd
.compression
= DXT
; break; default: shd
.compression
= RAW
; break; } shd
.flags
= header
.alpha_depth
; } } std
::cout
<< "compression: " << std
::to_string
(shd
.compression
) << std
::endl
; switch(shd
.compression
) { case JPG
: { u32 jpegHeaderSize
= 0; file
->read
(&jpegHeaderSize
, 4); char *data
= new char[shd
.mipmap_lengths
[0] + jpegHeaderSize
]; file
->read
(data
, jpegHeaderSize
); file
->seek
(shd
.mipmap_offsets
[0]); file
->read
(data
+jpegHeaderSize
, shd
.mipmap_lengths
[0]); return decompressJpg
(shd
, data
, shd
.mipmap_lengths
[0] + jpegHeaderSize
); } break; case BLP
: { file
->read
(shd
.palette
, 256*sizeof(u32
)); for(int i
= 0; i
<256; ++i
) { SColor c
= shd
.palette
[i
]; shd
.palette
[i
] = SColor( 255-c
.getRed
(), c
.getGreen
(), c
.getBlue
(), c
.getAlpha
() ).color
; } file
->seek
(shd
.mipmap_offsets
[0]); char *data
= new char[shd
.mipmap_lengths
[0]]; file
->read
(data
, shd
.mipmap_lengths
[0]); return decompressBLP
(shd
, data
, shd
.mipmap_lengths
[0]); } break; case DXT
: { file
->seek
(shd
.mipmap_offsets
[0]); char *data
= new char[shd
.mipmap_lengths
[0]]; file
->read
(data
, shd
.mipmap_lengths
[0]); return decompressDXT
(shd
, data
, shd
.mipmap_lengths
[0]); } break; default: { file
->seek
(shd
.mipmap_offsets
[0]); char *data
= new char[shd
.mipmap_lengths
[0]]; file
->read
(data
, shd
.mipmap_lengths
[0]); return decompressRaw
(shd
, data
, shd
.mipmap_lengths
[0]); } break; } return 0; } IImage* CImageLoaderBLP
::decompressBLP
(const sharedheader
&header
, char *data
, size_t size
) const { IImage *tmp
= driver
->createImage
( ECF_A8R8G8B8
, core::dimension2du
(header
.width
, header
.height
) ); for(int height
= 0; height
< header
.height
; ++height
) { for(int width
= 0; width
< header
.width
; ++width
) { unsigned char index
= (unsigned char)data
[width
+ header
.width
*height
]; tmp
->setPixel
(width
, height
, SColor(header
.palette
[index
])); } } if(header
.alpha_depth
== 3 || header
.alpha_depth
== 4) { char *alpha
= data
+ header
.width
*header
.height
; for(int height
= 0; height
< header
.height
; ++height
) { for(int width
= 0; width
< header
.width
; ++width
) { SColor c
(tmp
->getPixel
(width
, height
)); c
.setAlpha
(alpha
[width
+ header
.width
*height
]); tmp
->setPixel
(width
, height
, c
); } } } delete [] data
; return tmp
; } IImage* CImageLoaderBLP
::decompressDXT
(const sharedheader
&header
, char *data
, size_t size
) const { ECOLOR_FORMAT dxt
; if(header
.flags
== 0) dxt
= ECF_DXT1
; if(header
.flags
== 1) dxt
= ECF_DXT3
; if(header
.flags
== 7) dxt
= ECF_DXT5
; return driver
->createImageFromData
( dxt
, core::dimension2du
(header
.width
, header
.height
), data
, true, true ); } IImage* CImageLoaderBLP
::decompressRaw
(const sharedheader
&header
, char *data
, size_t size
) const { ECOLOR_FORMAT dxt
; if(header
.alpha_depth
== 0) dxt
= ECF_R8G8B8
; else dxt
= ECF_A8R8G8B8
; IImage *tmp
= driver
->createImageFromData
( ECF_A8R8G8B8
, core::dimension2du
(header
.width
, header
.height
), data
, true, true ); return tmp
; } IImage* CImageLoaderBLP
::decompressJpg
(const sharedheader
&header
, char *buffer
, size_t size
) const { struct jpeg_error_mgr jerr
; struct jpeg_decompress_struct cinfo
; cinfo
.err
= jpeg_std_error
(&jerr
); jpeg_create_decompress
(&cinfo
); jpeg_mem_src
(&cinfo
, (unsigned char*)buffer
, size
); if(jpeg_read_header
(&cinfo
, TRUE) != JPEG_HEADER_OK ||
!jpeg_start_decompress
(&cinfo
)) { jpeg_finish_decompress
(&cinfo
); jpeg_destroy_decompress
(&cinfo
); return 0; } IImage *tmp
= driver
->createImage
( ECF_A8R8G8B8
, core::dimension2du
(cinfo
.image_width
, cinfo
.image_height
) ); const JDIMENSION requiredScanlines
= cinfo
.output_height
; const JDIMENSION scanlineSize
= cinfo
.output_width
* cinfo
.output_components
; JSAMPARRAY scanlines
= (*cinfo
.mem
->alloc_sarray
)((j_common_ptr
) &cinfo
, JPOOL_IMAGE
, scanlineSize
, requiredScanlines
); while(cinfo
.output_scanline
< cinfo
.output_height
) { const JDIMENSION currentScanline
= cinfo
.output_scanline
; const JDIMENSION dimension
= jpeg_read_scanlines
(&cinfo
, scanlines
, requiredScanlines
); for(int height
= 0; height
< dimension
; ++height
) { int width
= 0; for(int component
= 0; component
< scanlineSize
; component
+= cinfo
.output_components
) { u32 argb
= ((u32
)scanlines
[height
][component
]) |
((u32
)scanlines
[height
][component
+ 1] << 8) |
((u32
)scanlines
[height
][component
+ 2] << 16); if(cinfo
.output_components
== 4) argb |
= ((u32
)(scanlines
[height
][component
+ 3]) << 24); tmp
->setPixel
(width
, height
+ currentScanline
, argb
); ++width
; } } } jpeg_finish_decompress
(&cinfo
); jpeg_destroy_decompress
(&cinfo
); return tmp
; } }}#endif
utilisation
Code c++ :
driver
->addExternalImageLoader
(new irr::video::CImageLoaderBLP
(driver
));driver
->getTexture
("CImageLoaderBLP");
fait attention pour les formats Raw et DXTC, il ne sont pas tester (faute de n'avoir pue trouver des fichier de test)
voud pouvez trouver des ressources sur http://www.hiveworkshop.com/forums/icons.php & http://www.hiveworkshop.com/forums/skins.php
post forum-off:
http://irrlicht.sourceforge.net/forum/v … mp;t=50551