CImageLoaderBLP initial release
This commit is contained in:
parent
03f40ffefe
commit
5aeccb7a77
310
src/Client/GUI/CImageLoaderBLP.cpp
Normal file
310
src/Client/GUI/CImageLoaderBLP.cpp
Normal file
@ -0,0 +1,310 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include "irrlicht/irrlicht.h"
|
||||
#include "SImage.h"
|
||||
#include "CImageLoaderBLP.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".tga")
|
||||
bool CImageLoaderBLP::isALoadableFileExtension(const c8* fileName) const
|
||||
{
|
||||
// std::cout << "Checking for file extension\n";
|
||||
return strstr(fileName, ".blp")!=0;
|
||||
}
|
||||
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
bool CImageLoaderBLP::isALoadableFileFormat(io::IReadFile* file) const
|
||||
{
|
||||
// std::cout <<"Checking if file is a BLP file\n";
|
||||
if (!file)
|
||||
{
|
||||
std::cout<<"No such file: "<<file->getFileName()<<"\n";
|
||||
return false;
|
||||
}
|
||||
std::string fileId;
|
||||
// Read the first few bytes of the BLP file
|
||||
if (file->read(&fileId[0], 4) != 4)
|
||||
{
|
||||
std::cout << "Cannot read BLP file header\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(fileId[0]=='B' && fileId[1]=='L' && fileId[2]=='P' && fileId[3]=='2')
|
||||
{
|
||||
std::cout << "Header is BLP2, file should be loadable\n";
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Header doesn't match, this is no BLP file\n";
|
||||
std::cout << "Expected:BLP2 Got:"<<fileId.c_str()<<"\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// load in the image data
|
||||
IImage* CImageLoaderBLP::loadImage(io::IReadFile* file) const
|
||||
{
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
BLPHeader header;
|
||||
// std::cout<<"Trying to load the image\n";
|
||||
// std::cout<<"Checking Header\n";
|
||||
file->read(&header,sizeof(BLPHeader));
|
||||
|
||||
// std::cout<<"Header data: "<<header.fileID<<"\n Alpha depth:"<<(u32)header.alpha_bitdepth<<"bit\nCompression:"<<(u32)header.compression<<"\n";
|
||||
// std::cout<<"Mystery factor:"<<(u32)header.alpha_unk<<"\n";
|
||||
// std::cout<<"X-Res: "<< header.x_res<<"\nY-Res:"<<header.y_res<<"\n";
|
||||
u32 usedMips=0;
|
||||
for(u32 i=0;i<16;i++)
|
||||
{
|
||||
if(header.mip_ofs[i]!=0&&header.mip_size[i]!=0)
|
||||
usedMips++;
|
||||
}
|
||||
// std::cout<<"Mip Levels:"<< usedMips<<"\n";
|
||||
core::array<PaletteColor> palette;
|
||||
PaletteColor tempColor;
|
||||
palette.reallocate(256);
|
||||
for(u32 i=0;i<256;i++)
|
||||
{
|
||||
file->read(&tempColor,sizeof(PaletteColor));
|
||||
palette.push_back(tempColor);
|
||||
}
|
||||
|
||||
|
||||
// std::cout<<"Loading Mip 0 Length is "<<header.mip_size[0]<<"\n";
|
||||
file->seek(header.mip_ofs[0]);
|
||||
|
||||
video::IImage* image = 0;
|
||||
image = new SImage(ECF_A8R8G8B8, core::dimension2d<s32>(header.x_res, header.y_res));
|
||||
|
||||
if(header.compression==2)
|
||||
{
|
||||
//Reading imageData for DXT1/3/5 (5 not really...)
|
||||
DXC5chunk tempChunk5;
|
||||
DXC3chunk tempChunk3;
|
||||
DXC1chunk tempChunk1;
|
||||
core::array<DXC5chunk> imagedata5;
|
||||
core::array<DXC3chunk> imagedata3;
|
||||
core::array<DXC1chunk> imagedata1;
|
||||
|
||||
for(u32 i=0;i<(header.mip_size[0]/8);i++)
|
||||
{
|
||||
if(header.compression==2&&header.alpha_bitdepth>1)
|
||||
{
|
||||
if(header.alpha_unk==7)//it is not absolutely necessary to divide DXT3 and 5 data here as both are 64bit blocks which have to be dissected later.
|
||||
{ // But this way it is somehow clearer for me
|
||||
file->read(&tempChunk5,sizeof(DXC5chunk));
|
||||
imagedata5.push_back(tempChunk5);
|
||||
}
|
||||
else
|
||||
{
|
||||
file->read(&tempChunk3,sizeof(DXC3chunk));
|
||||
imagedata3.push_back(tempChunk3);
|
||||
}
|
||||
}
|
||||
file->read(&tempChunk1,sizeof(DXC1chunk));
|
||||
imagedata1.push_back(tempChunk1);
|
||||
|
||||
}
|
||||
// std::cout << "Data read\n";
|
||||
u32 i=0;
|
||||
u32 alpha=255;
|
||||
u32 a[8];
|
||||
u32 r1, g1,b1,r2,g2,b2;
|
||||
u64 temptransp;
|
||||
bool transparency_bit=false;
|
||||
for(u32 y=0;y<header.y_res;y=y+4)
|
||||
{
|
||||
for(u32 x=0;x<header.x_res;x=x+4)
|
||||
{
|
||||
f32 rb=256/31;
|
||||
f32 g=256/63;
|
||||
r1 = (u32)rb*(imagedata1[i].color1 & 0xF800) >>11;
|
||||
g1 = (u32)g*(imagedata1[i].color1 & 0x07E0) >>5;
|
||||
b1 = (u32)rb*(imagedata1[i].color1 & 0x001F) ;
|
||||
r2 = (u32)rb*(imagedata1[i].color2 & 0xF800) >>11;
|
||||
g2 = (u32)g*(imagedata1[i].color2 & 0x07E0) >>5;
|
||||
b2 = (u32)rb*(imagedata1[i].color2 & 0x001F) ;
|
||||
if(imagedata1[i].color1>imagedata1[i].color2||header.alpha_bitdepth==8)
|
||||
{
|
||||
transparency_bit=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* std::cout << imagedata1[i].color1 <<","<<imagedata1[i].color2<<"\n";
|
||||
// f32 rgb=256/31;
|
||||
r1 = (u32)rgb*(imagedata1[i].color1 & 0xF800) >>11;
|
||||
g1 = (u32)rgb*(imagedata1[i].color1 & 0x07C0) >>6;
|
||||
b1 = (u32)rgb*(imagedata1[i].color1 & 0x003E) >>1;
|
||||
r2 = (u32)rgb*(imagedata1[i].color2 & 0xF800) >>11;
|
||||
g2 = (u32)rgb*(imagedata1[i].color2 & 0x07C0) >>6;
|
||||
b2 = (u32)rgb*(imagedata1[i].color2 & 0x003E) >>1;
|
||||
*/ transparency_bit=true;
|
||||
}
|
||||
|
||||
u32 tempbitmap=imagedata1[i].bitmap;
|
||||
if(header.alpha_bitdepth==8)
|
||||
{
|
||||
if(header.alpha_unk==7)
|
||||
{
|
||||
temptransp=(u64)imagedata5[i].bitmap[2]<<32|(u64)imagedata5[i].bitmap[1]<<16|imagedata5[i].bitmap[0];
|
||||
a[0]=imagedata5[i].alpha1;
|
||||
a[1]=imagedata5[i].alpha2;
|
||||
if (a[0] > a[1]) {
|
||||
// 8-alpha block: derive the other six alphas.
|
||||
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
|
||||
a[2] = (6 * a[0] + 1 * a[1]) / 7; // bit code 010
|
||||
a[3] = (5 * a[0] + 2 * a[1]) / 7; // bit code 011
|
||||
a[4] = (4 * a[0] + 3 * a[1]) / 7; // bit code 100
|
||||
a[5] = (3 * a[0] + 4 * a[1]) / 7; // bit code 101
|
||||
a[6] = (2 * a[0] + 5 * a[1]) / 7; // bit code 110
|
||||
a[7] = (1 * a[0] + 6 * a[1]) / 7; // bit code 111
|
||||
}
|
||||
else
|
||||
{
|
||||
// 6-alpha block.
|
||||
// Bit code 000 = a[0], 001 = a[1], others are interpolated.
|
||||
a[2] = (4 * a[0] + 1 * a[1]) / 5; // Bit code 010
|
||||
a[3] = (3 * a[0] + 2 * a[1]) / 5; // Bit code 011
|
||||
a[4] = (2 * a[0] + 3 * a[1]) / 5; // Bit code 100
|
||||
a[5] = (1 * a[0] + 4 * a[1]) / 5; // Bit code 101
|
||||
a[6] = 0; // Bit code 110
|
||||
a[7] = 255; // Bit code 111
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
temptransp=imagedata3[i].transparency_block;
|
||||
}
|
||||
}
|
||||
for(u32 ty=0;ty<4;ty++)
|
||||
{
|
||||
for(u32 tx=0;tx<4;tx++)
|
||||
{
|
||||
if(header.alpha_bitdepth==8)
|
||||
{
|
||||
if(header.alpha_unk==7)
|
||||
{
|
||||
alpha=a[(temptransp & 7)];
|
||||
}
|
||||
else
|
||||
{
|
||||
f32 a=256/15;
|
||||
alpha=(u32)a * (temptransp & 15);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alpha=255;
|
||||
}
|
||||
switch(tempbitmap & 3)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
image->setPixel(x+tx,y+ty,video::SColor(alpha,r1,g1,b1));
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
image->setPixel(x+tx,y+ty,video::SColor(alpha,r2,g2,b2));
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
if(transparency_bit==false)
|
||||
image->setPixel(x+tx,y+ty,video::SColor(alpha,(u32)(0.667f*r1+0.333f*r2),(u32)(0.667f*g1+0.333f*g2),(u32)(0.667f*b1+0.333f*b2)));
|
||||
else
|
||||
//image->setPixel(x+tx,y+ty,video::SColor(255,255,0,0));
|
||||
image->setPixel(x+tx,y+ty,video::SColor(255,(u32)(0.5f*r1+0.5f*r2),(u32)(0.5f*g1+0.5f*g2),(u32)(0.5f*b1+0.5f*b2)));
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
if(transparency_bit==false)
|
||||
image->setPixel(x+tx,y+ty,video::SColor(alpha,(u32)(0.333f*r1+0.667f*r2),(u32)(0.333f*g1+0.667f*g2),(u32)(0.333f*b1+0.667f*b2)));
|
||||
else
|
||||
if(header.alpha_bitdepth==1)
|
||||
image->setPixel(x+tx,y+ty,video::SColor(0,0,0,0));
|
||||
else
|
||||
image->setPixel(x+tx,y+ty,video::SColor(255,0,0,0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
tempbitmap=tempbitmap>>2;
|
||||
if(header.alpha_bitdepth==8)
|
||||
{
|
||||
if(header.alpha_unk==7)
|
||||
{
|
||||
temptransp=temptransp>>3;
|
||||
}
|
||||
else
|
||||
{
|
||||
temptransp=temptransp>>4;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else//Palette Images
|
||||
{
|
||||
u8 index;
|
||||
for(u32 y=0;y<header.y_res;y++)
|
||||
{
|
||||
for(u32 x=0;x<header.x_res;x++)
|
||||
{
|
||||
file->read(&index,sizeof(u8));
|
||||
image->setPixel(x,y,video::SColor(255,palette[index].R,palette[index].G,palette[index].B));
|
||||
}
|
||||
}
|
||||
if(header.alpha_bitdepth==1)//surely not the best way.
|
||||
{
|
||||
for(u32 y=0;y<header.y_res;y++)
|
||||
{
|
||||
video::SColor pixel;
|
||||
for(u32 x=0;x<header.x_res;x=x+8)
|
||||
{
|
||||
file->read(&index,sizeof(u8));
|
||||
for(u32 i=0;i<8;i++)
|
||||
{
|
||||
pixel =image->getPixel(x+i,y);
|
||||
pixel.setAlpha(255*(index & 1));
|
||||
image->setPixel(x+i,y,pixel);
|
||||
index =index >>1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(header.alpha_bitdepth==8)//surely not the best way.
|
||||
{
|
||||
for(u32 y=0;y<header.y_res;y++)
|
||||
{
|
||||
video::SColor pixel;
|
||||
for(u32 x=0;x<header.x_res;x++)
|
||||
{
|
||||
file->read(&index,sizeof(u8));
|
||||
pixel =image->getPixel(x,y);
|
||||
pixel.setAlpha(index);
|
||||
image->setPixel(x,y,pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
}//namespace video
|
||||
}//namespace irr
|
||||
63
src/Client/GUI/CImageLoaderBLP.h
Normal file
63
src/Client/GUI/CImageLoaderBLP.h
Normal file
@ -0,0 +1,63 @@
|
||||
#include <vector>
|
||||
#include "irrlicht/IImageLoader.h"
|
||||
typedef unsigned long long int u64;
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Surface Loader for BLP files
|
||||
class CImageLoaderBLP : public IImageLoader
|
||||
{
|
||||
public:
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
//! based on the file extension (e.g. ".blp")
|
||||
virtual bool isALoadableFileExtension(const c8* fileName) const;
|
||||
|
||||
//! returns true if the file maybe is able to be loaded by this class
|
||||
virtual bool isALoadableFileFormat(io::IReadFile* file) const;
|
||||
|
||||
//! creates a surface from the file
|
||||
virtual IImage* loadImage(io::IReadFile* file) const;
|
||||
private:
|
||||
struct BLPHeader
|
||||
{
|
||||
c8 fileID[4];
|
||||
u32 version;
|
||||
u8 compression;
|
||||
u8 alpha_bitdepth;
|
||||
u8 alpha_unk;
|
||||
u8 miplevel;
|
||||
u32 x_res;
|
||||
u32 y_res;
|
||||
u32 mip_ofs[16];
|
||||
u32 mip_size[16];
|
||||
};
|
||||
struct DXC1chunk
|
||||
{
|
||||
u16 color1;
|
||||
u16 color2;
|
||||
u32 bitmap;
|
||||
};
|
||||
struct DXC3chunk//This is kind of useless
|
||||
{
|
||||
u64 transparency_block;
|
||||
};
|
||||
struct DXC5chunk
|
||||
{
|
||||
u8 alpha1, alpha2;
|
||||
u16 bitmap[3];//how do i express an "u48"?
|
||||
};
|
||||
|
||||
struct PaletteColor//Not sure if an Irrlicht color can handle the changed color sequence
|
||||
{
|
||||
u8 B,G,R,A;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
306
src/Client/GUI/SImage.cpp
Normal file
306
src/Client/GUI/SImage.cpp
Normal file
@ -0,0 +1,306 @@
|
||||
#include "SImage.h"
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! constructor for empty image
|
||||
//! constructor
|
||||
SImage::SImage(ECOLOR_FORMAT format, const core::dimension2d<s32>& size): Size(size), Format(format), Data(0)
|
||||
{
|
||||
initData();
|
||||
}
|
||||
|
||||
void SImage::initData()
|
||||
{
|
||||
setBitMasks();
|
||||
BitsPerPixel = getBitsPerPixelFromFormat(Format);
|
||||
BytesPerPixel = BitsPerPixel / 8;
|
||||
|
||||
// Pitch should be aligned...
|
||||
Pitch = BytesPerPixel * Size.Width;
|
||||
|
||||
if (!Data)
|
||||
Data = new s8[Size.Height * Pitch];
|
||||
}
|
||||
|
||||
u32 SImage::getBitsPerPixelFromFormat(ECOLOR_FORMAT format)
|
||||
{
|
||||
switch(format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
return 16;
|
||||
case ECF_R5G6B5:
|
||||
return 16;
|
||||
case ECF_R8G8B8:
|
||||
return 24;
|
||||
case ECF_A8R8G8B8:
|
||||
return 32;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
SImage::~SImage()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//! Returns width and height of image data.
|
||||
const core::dimension2d<s32>& SImage::getDimension() const
|
||||
{
|
||||
return Size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Returns bits per pixel.
|
||||
u32 SImage::getBitsPerPixel() const
|
||||
{
|
||||
return BitsPerPixel;
|
||||
}
|
||||
|
||||
|
||||
//! Returns bytes per pixel
|
||||
u32 SImage::getBytesPerPixel() const
|
||||
{
|
||||
return BytesPerPixel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Returns image data size in bytes
|
||||
u32 SImage::getImageDataSizeInBytes() const
|
||||
{
|
||||
return Pitch * Size.Height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! Returns image data size in pixels
|
||||
u32 SImage::getImageDataSizeInPixels() const
|
||||
{
|
||||
return Size.Width * Size.Height;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns mask for red value of a pixel
|
||||
u32 SImage::getRedMask() const
|
||||
{
|
||||
return RedMask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns mask for green value of a pixel
|
||||
u32 SImage::getGreenMask() const
|
||||
{
|
||||
return GreenMask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns mask for blue value of a pixel
|
||||
u32 SImage::getBlueMask() const
|
||||
{
|
||||
return BlueMask;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//! returns mask for alpha value of a pixel
|
||||
u32 SImage::getAlphaMask() const
|
||||
{
|
||||
return AlphaMask;
|
||||
}
|
||||
|
||||
void SImage::setBitMasks()
|
||||
{
|
||||
switch(Format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
AlphaMask = 0x1<<15;
|
||||
RedMask = 0x1F<<10;
|
||||
GreenMask = 0x1F<<5;
|
||||
BlueMask = 0x1F;
|
||||
break;
|
||||
case ECF_R5G6B5:
|
||||
AlphaMask = 0x0;
|
||||
RedMask = 0x1F<<11;
|
||||
GreenMask = 0x3F<<5;
|
||||
BlueMask = 0x1F;
|
||||
break;
|
||||
case ECF_R8G8B8:
|
||||
AlphaMask = 0x0;
|
||||
RedMask = 0x00FF0000;
|
||||
GreenMask = 0x0000FF00;
|
||||
BlueMask = 0x000000FF;
|
||||
break;
|
||||
case ECF_A8R8G8B8:
|
||||
AlphaMask = 0xFF000000;
|
||||
RedMask = 0x00FF0000;
|
||||
GreenMask = 0x0000FF00;
|
||||
BlueMask = 0x000000FF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//! sets a pixel
|
||||
void SImage::setPixel(u32 x, u32 y, const SColor &color )
|
||||
{
|
||||
if (x >= (u32)Size.Width || y >= (u32)Size.Height)
|
||||
return;
|
||||
|
||||
switch(Format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
{
|
||||
u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 ));
|
||||
*dest = video::A8R8G8B8toA1R5G5B5 ( color.color );
|
||||
} break;
|
||||
|
||||
case ECF_R5G6B5:
|
||||
{
|
||||
u16 * dest = (u16*) ((u8*) Data + ( y * Pitch ) + ( x << 1 ));
|
||||
*dest = video::A8R8G8B8toR5G6B5 ( color.color );
|
||||
} break;
|
||||
|
||||
case ECF_R8G8B8:
|
||||
{
|
||||
u8* dest = (u8*) Data + ( y * Pitch ) + ( x * 3 );
|
||||
dest[0] = color.getRed();
|
||||
dest[1] = color.getGreen();
|
||||
dest[2] = color.getBlue();
|
||||
} break;
|
||||
|
||||
case ECF_A8R8G8B8:
|
||||
{
|
||||
u32 * dest = (u32*) ((u8*) Data + ( y * Pitch ) + ( x << 2 ));
|
||||
*dest = color.color;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns a pixel
|
||||
SColor SImage::getPixel(u32 x, u32 y) const
|
||||
{
|
||||
if (x >= (u32)Size.Width || y >= (u32)Size.Height)
|
||||
return SColor(0);
|
||||
|
||||
switch(Format)
|
||||
{
|
||||
case ECF_A1R5G5B5:
|
||||
return A1R5G5B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
|
||||
case ECF_R5G6B5:
|
||||
return R5G6B5toA8R8G8B8(((u16*)Data)[y*Size.Width + x]);
|
||||
case ECF_A8R8G8B8:
|
||||
return ((u32*)Data)[y*Size.Width + x];
|
||||
case ECF_R8G8B8:
|
||||
{
|
||||
u8* p = &((u8*)Data)[(y*3)*Size.Width + (x*3)];
|
||||
return SColor(255,p[0],p[1],p[2]);
|
||||
}
|
||||
}
|
||||
|
||||
return SColor(0);
|
||||
}
|
||||
|
||||
|
||||
//! returns the color format
|
||||
ECOLOR_FORMAT SImage::getColorFormat() const
|
||||
{
|
||||
return Format;
|
||||
}
|
||||
|
||||
//! copies this surface into another, scaling it to the target image size
|
||||
// note: this is very very slow. (i didn't want to write a fast version.
|
||||
// but hopefully, nobody wants to scale surfaces every frame.
|
||||
void SImage::copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format, u32 pitch)
|
||||
{
|
||||
if (!target || !width || !height)
|
||||
return;
|
||||
|
||||
const u32 bpp=getBitsPerPixelFromFormat(format)/8;
|
||||
if (0==pitch)
|
||||
pitch = width*bpp;
|
||||
|
||||
if (Format==format && Size.Width==width && Size.Height==height)
|
||||
{
|
||||
if (pitch==Pitch)
|
||||
{
|
||||
memcpy(target, Data, height*pitch);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8* tgtpos = (u8*) target;
|
||||
u8* dstpos = (u8*) Data;
|
||||
const u32 bwidth = width*bpp;
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
memcpy(target, Data, height*pitch);
|
||||
memset(tgtpos+width, 0, pitch-bwidth);
|
||||
tgtpos += pitch;
|
||||
dstpos += Pitch;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const f32 sourceXStep = (f32)Size.Width / (f32)width;
|
||||
const f32 sourceYStep = (f32)Size.Height / (f32)height;
|
||||
s32 yval=0, syval=0;
|
||||
f32 sy = 0.0f;
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
f32 sx = 0.0f;
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
// CColorConverter::convert_viaFormat(((u8*)Data)+ syval + ((s32)sx)*BytesPerPixel, Format, 1, ((u8*)target)+ yval + (x*bpp), format);
|
||||
sx+=sourceXStep;
|
||||
}
|
||||
sy+=sourceYStep;
|
||||
syval=((s32)sy)*Pitch;
|
||||
yval+=pitch;
|
||||
}
|
||||
}
|
||||
|
||||
//! copies this surface into another, scaling it to the target image size
|
||||
// note: this is very very slow. (i didn't want to write a fast version.
|
||||
// but hopefully, nobody wants to scale surfaces every frame.
|
||||
void SImage::copyToScaling(IImage* target)
|
||||
{
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
const core::dimension2d<s32>& targetSize = target->getDimension();
|
||||
|
||||
if (targetSize==Size)
|
||||
{
|
||||
copyTo(target);
|
||||
return;
|
||||
}
|
||||
|
||||
copyToScaling(target->lock(), targetSize.Width, targetSize.Height, target->getColorFormat());
|
||||
target->unlock();
|
||||
}
|
||||
|
||||
//! copies this surface into another
|
||||
void SImage::copyTo(IImage* target, const core::position2d<s32>& pos)
|
||||
{
|
||||
// Blit ( BLITTER_TEXTURE, target, 0, &pos, this, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
//! copies this surface into another
|
||||
void SImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect)
|
||||
{
|
||||
// Blit ( BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0 );
|
||||
}
|
||||
|
||||
|
||||
}//video
|
||||
}//irr
|
||||
|
||||
101
src/Client/GUI/SImage.h
Normal file
101
src/Client/GUI/SImage.h
Normal file
@ -0,0 +1,101 @@
|
||||
//most simplistic IImage Implementation, copypasted form irrlichts CImage
|
||||
#include "irrlicht/irrlicht.h"
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class SImage : public IImage
|
||||
{
|
||||
public:
|
||||
//! constructor for empty image
|
||||
SImage(ECOLOR_FORMAT format, const core::dimension2d<s32>& size);
|
||||
//! destructor
|
||||
virtual ~SImage();
|
||||
|
||||
//! returns a pixel
|
||||
virtual SColor getPixel(u32 x, u32 y) const;
|
||||
|
||||
//! sets a pixel
|
||||
virtual void setPixel(u32 x, u32 y, const SColor &color );
|
||||
|
||||
//! Lock function.
|
||||
virtual void* lock()
|
||||
{
|
||||
return Data;
|
||||
};
|
||||
|
||||
//! Unlock function.
|
||||
virtual void unlock() {};
|
||||
|
||||
//! Returns width and height of image data.
|
||||
virtual const core::dimension2d<s32>& getDimension() const;
|
||||
|
||||
//! Returns bits per pixel.
|
||||
virtual u32 getBitsPerPixel() const;
|
||||
|
||||
//! Returns bytes per pixel
|
||||
virtual u32 getBytesPerPixel() const;
|
||||
|
||||
//! Returns image data size in bytes
|
||||
virtual u32 getImageDataSizeInBytes() const;
|
||||
|
||||
//! Returns image data size in pixels
|
||||
virtual u32 getImageDataSizeInPixels() const;
|
||||
|
||||
//! returns mask for red value of a pixel
|
||||
virtual u32 getRedMask() const;
|
||||
|
||||
//! returns mask for green value of a pixel
|
||||
virtual u32 getGreenMask() const;
|
||||
|
||||
//! returns mask for blue value of a pixel
|
||||
virtual u32 getBlueMask() const;
|
||||
|
||||
//! returns mask for alpha value of a pixel
|
||||
virtual u32 getAlphaMask() const;
|
||||
|
||||
//! returns the color format
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! copies this surface into another
|
||||
void copyTo(IImage* target, const core::position2d<s32>& pos=core::position2d<s32>(0,0));
|
||||
|
||||
//! copies this surface into another
|
||||
void copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect=0);
|
||||
|
||||
//! copies this surface into another, scaling it to fit.
|
||||
void copyToScaling(void* target, s32 width, s32 height, ECOLOR_FORMAT format, u32 pitch=0);
|
||||
|
||||
//! copies this surface into another, scaling it to fit.
|
||||
void copyToScaling(IImage* target);
|
||||
|
||||
//! returns pitch of image
|
||||
virtual u32 getPitch() const
|
||||
{
|
||||
return Pitch;
|
||||
}
|
||||
|
||||
static u32 getBitsPerPixelFromFormat(ECOLOR_FORMAT format);
|
||||
private:
|
||||
|
||||
//! assumes format and size has been set and creates the rest
|
||||
void initData();
|
||||
|
||||
void setBitMasks();
|
||||
inline SColor getPixelBox ( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const;
|
||||
void* Data;
|
||||
core::dimension2d<s32> Size;
|
||||
u32 BitsPerPixel;
|
||||
u32 BytesPerPixel;
|
||||
u32 Pitch;
|
||||
ECOLOR_FORMAT Format;
|
||||
|
||||
u32 RedMask;
|
||||
u32 GreenMask;
|
||||
u32 BlueMask;
|
||||
u32 AlphaMask;
|
||||
};
|
||||
|
||||
}//video
|
||||
}//irr
|
||||
Loading…
x
Reference in New Issue
Block a user