2011-10-28 18:19:04 +02:00
/**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* @ file ewolTexture . cpp
* @ brief ewol Texture loading system ( sources )
* @ author Edouard DUPIN
* @ date 28 / 10 / 2011
* @ par Project
* ewol
*
* @ par Copyright
* Copyright 2011 Edouard DUPIN , all right reserved
*
* This software is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY .
*
* Licence summary :
* You can modify and redistribute the sources code and binaries .
* You can send me the bug - fix
*
* Term of the licence in in the file licence . txt .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
# include <ewolTexture.h>
extern " C "
{
# pragma pack(push,1)
typedef struct
{
int16_t bfType ;
int32_t bfSize ;
int32_t bfReserved ;
int32_t bfOffBits ;
} bitmapFileHeader_ts ;
typedef struct
{
int32_t biSize ;
int32_t biWidth ;
int32_t biHeight ;
int16_t biPlanes ;
int16_t biBitCount ;
int32_t biCompression ;
int32_t biSizeImage ;
int32_t biXPelsPerMeter ;
int32_t biYPelsPerMeter ;
int32_t biClrUsed ;
int32_t biClrImportant ;
} bitmapInfoHeader_ts ;
# pragma pack(pop)
typedef enum {
BITS_16_R5G6B5 ,
BITS_16_X1R5G5B5 ,
BITS_24_R8G8B8 ,
BITS_32_X8R8G8B8 ,
BITS_32_A8R8G8B8
} modeBitmap_te ;
} ;
2011-10-30 14:52:55 +01:00
# undef __class__
# define __class__ "ewol::Bitmap"
2011-10-28 18:19:04 +02:00
class Bitmap
{
private :
modeBitmap_te m_dataMode ;
int32_t m_width ;
int32_t m_height ;
int32_t m_size ;
uint8_t * m_data ;
uint8_t * m_dataGenerate ;
bitmapFileHeader_ts m_FileHeader ;
bitmapInfoHeader_ts m_InfoHeader ;
public :
Bitmap ( etk : : File & fileName ) : m_data ( NULL ) , m_dataGenerate ( NULL )
{
m_dataMode = BITS_16_R5G6B5 ;
m_width = 0 ;
m_height = 0 ;
m_size = 0 ;
FILE * File = NULL ;
// Get the fileSize ...
2011-10-30 14:52:55 +01:00
if ( fileName . Size ( ) < ( int32_t ) ( sizeof ( bitmapFileHeader_ts ) + sizeof ( bitmapInfoHeader_ts ) ) ) {
2011-10-28 18:19:04 +02:00
EWOL_ERROR ( " not enought data in the file named= \" " < < fileName < < " \" " ) ;
return ;
}
File = fopen ( fileName . GetCompleateName ( ) . c_str ( ) , " rb " ) ;
if ( NULL = = File ) {
EWOL_ERROR ( " Can not find the file name= \" " < < fileName < < " \" " ) ;
return ;
}
// get the data :
if ( fread ( & m_FileHeader , sizeof ( bitmapFileHeader_ts ) , 1 , File ) ! = 1 ) {
EWOL_ERROR ( " error loading file header " ) ;
fclose ( File ) ;
return ;
}
if ( fread ( & m_InfoHeader , sizeof ( bitmapInfoHeader_ts ) , 1 , File ) ! = 1 ) {
EWOL_ERROR ( " error loading file header " ) ;
fclose ( File ) ;
return ;
}
// TODO : do otherwise ...
fseek ( File , m_FileHeader . bfOffBits , SEEK_SET ) ;
if ( ferror ( File ) ) {
EWOL_ERROR ( " error with the 'bfOffBits' in the file named= \" " < < fileName < < " \" " ) ;
fclose ( File ) ;
return ;
}
// Check the header error :
if ( m_FileHeader . bfType ! = 0x4D42 ) {
EWOL_ERROR ( " the file= \" " < < fileName < < " \" is not a bitmap file ... " ) ;
fclose ( File ) ;
return ;
}
if ( m_FileHeader . bfReserved ! = 0x00000000 ) {
EWOL_ERROR ( " the bfReserved feald is not at 0 ==> not supported format ... " ) ;
fclose ( File ) ;
return ;
}
if ( m_InfoHeader . biBitCount = = 16
& & m_InfoHeader . biCompression = = 0 )
{
m_dataMode = BITS_16_X1R5G5B5 ;
} else if ( m_InfoHeader . biBitCount = = 16
& & m_InfoHeader . biCompression = = 3 )
{
m_dataMode = BITS_16_R5G6B5 ;
} else if ( m_InfoHeader . biBitCount = = 24
& & m_InfoHeader . biCompression = = 0 )
{
m_dataMode = BITS_24_R8G8B8 ;
} else if ( m_InfoHeader . biBitCount = = 32
& & m_InfoHeader . biCompression = = 3 )
{
m_dataMode = BITS_32_X8R8G8B8 ;
} else if ( m_InfoHeader . biBitCount = = 32
& & m_InfoHeader . biCompression = = 0 )
{
m_dataMode = BITS_32_A8R8G8B8 ;
} else {
EWOL_ERROR ( " the biBitCount & biCompression fealds are unknow ==> not supported format ... " ) ;
fclose ( File ) ;
return ;
}
m_width = m_InfoHeader . biWidth ;
m_height = m_InfoHeader . biHeight ;
if ( 0 ! = m_InfoHeader . biSizeImage )
{
m_data = new uint8_t [ m_InfoHeader . biSizeImage ] ;
2011-10-30 14:52:55 +01:00
if ( fread ( m_data , m_InfoHeader . biSizeImage , 1 , File ) ! = 1 ) {
EWOL_CRITICAL ( " Can not read the file with the good size... " ) ;
}
2011-10-28 18:19:04 +02:00
// allocate the destination data ...
m_dataGenerate = new uint8_t [ m_width * m_height * 4 ] ;
}
fclose ( File ) ;
// need now to generate RGBA data ...
switch ( m_dataMode )
{
case BITS_16_R5G6B5 :
{
uint16_t * pointer = ( uint16_t * ) m_data ;
for ( int32_t yyy = 0 ; yyy < m_height ; yyy + + ) {
for ( int32_t xxx = 0 ; xxx < m_width ; xxx + + ) {
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 0 ] = ( int8_t ) ( ( * pointer & 0xF800 ) > > 8 ) ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 1 ] = ( int8_t ) ( ( * pointer & 0x07E0 ) > > 3 ) ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 2 ] = ( int8_t ) ( * pointer < < 3 ) ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 3 ] = 0xFF ;
pointer + + ;
}
}
}
break ;
case BITS_16_X1R5G5B5 :
{
uint16_t * pointer = ( uint16_t * ) m_data ;
for ( int32_t yyy = 0 ; yyy < m_height ; yyy + + ) {
for ( int32_t xxx = 0 ; xxx < m_width ; xxx + + ) {
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 0 ] = ( int8_t ) ( ( * pointer & 0x7C00 ) > > 7 ) ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 1 ] = ( int8_t ) ( ( * pointer & 0x03E0 ) > > 2 ) ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 2 ] = ( int8_t ) ( * pointer < < 3 ) ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 3 ] = 0xFF ;
pointer + + ;
}
}
}
break ;
case BITS_24_R8G8B8 :
{
uint8_t * pointer = m_data ;
for ( int32_t yyy = 0 ; yyy < m_height ; yyy + + ) {
for ( int32_t xxx = 0 ; xxx < m_width ; xxx + + ) {
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 0 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 1 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 2 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 3 ] = 0xFF ;
}
}
}
break ;
case BITS_32_X8R8G8B8 :
{
uint8_t * pointer = m_data ;
for ( int32_t yyy = 0 ; yyy < m_height ; yyy + + ) {
for ( int32_t xxx = 0 ; xxx < m_width ; xxx + + ) {
pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 0 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 1 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 2 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 3 ] = 0xFF ;
}
}
}
break ;
case BITS_32_A8R8G8B8 :
{
uint8_t * pointer = m_data ;
for ( int32_t yyy = 0 ; yyy < m_height ; yyy + + ) {
for ( int32_t xxx = 0 ; xxx < m_width ; xxx + + ) {
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 0 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 1 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 2 ] = * pointer + + ;
m_dataGenerate [ 4 * ( ( m_height - yyy - 1 ) * m_width + xxx ) + 3 ] = * pointer + + ;
}
}
}
break ;
default :
EWOL_DEBUG ( " mode = ERROR " ) ;
break ;
}
}
~ Bitmap ( void )
{
if ( NULL ! = m_data ) {
delete ( m_data ) ;
}
if ( NULL ! = m_dataGenerate ) {
delete ( m_dataGenerate ) ;
}
}
bool LoadOK ( void ) { if ( NULL ! = m_dataGenerate ) { return true ; } else { return false ; } } ;
int32_t Width ( void ) { return m_width ; } ;
int32_t Height ( void ) { return m_height ; } ;
uint8_t * Data ( void ) { return m_dataGenerate ; } ;
void Display ( void )
{
if ( NULL = = m_data ) {
EWOL_ERROR ( " Might loading error of this Bitmap ... " ) ;
return ;
}
EWOL_DEBUG ( " ----------------------------------------------------------- " ) ;
2011-10-29 17:32:11 +02:00
if ( false ) {
2011-10-28 18:19:04 +02:00
EWOL_DEBUG ( " Display caracteristic of the bitmap : " ) ;
EWOL_DEBUG ( " Header of file : " ) ;
EWOL_DEBUG ( " bfType = " < < m_FileHeader . bfType < < " 19778 : must always be set to 'BM' to declare that this is a .bmp-file. " ) ;
EWOL_DEBUG ( " bfSize = " < < m_FileHeader . bfSize < < " specifies the size of the file in bytes. " ) ;
EWOL_DEBUG ( " bfReserved= " < < m_FileHeader . bfReserved < < " must always be set to zero. " ) ;
EWOL_DEBUG ( " bfOffBits = " < < m_FileHeader . bfOffBits < < " 1078 : specifies the offset from the beginning of the file to the bitmap data. " ) ;
EWOL_DEBUG ( " info header of file : " ) ;
EWOL_DEBUG ( " biSize = " < < m_InfoHeader . biSize < < " specifies the size of the BITMAPINFOHEADER structure, in bytes. " ) ;
EWOL_DEBUG ( " biWidth = " < < m_InfoHeader . biWidth < < " specifies the width of the image, in pixels. " ) ;
EWOL_DEBUG ( " biHeight = " < < m_InfoHeader . biHeight < < " specifies the height of the image, in pixels. " ) ;
EWOL_DEBUG ( " biPlanes = " < < m_InfoHeader . biPlanes < < " specifies the number of planes of the target device, must be set to zero. " ) ;
EWOL_DEBUG ( " biBitCount = " < < m_InfoHeader . biBitCount < < " specifies the number of bits per pixel. " ) ;
EWOL_DEBUG ( " biCompression = " < < m_InfoHeader . biCompression < < " Specifies the type of compression, usually set to zero (no compression). " ) ;
EWOL_DEBUG ( " biSizeImage = " < < m_InfoHeader . biSizeImage < < " specifies the size of the image data, in bytes. If there is no compression, it is valid to set this member to zero. " ) ;
EWOL_DEBUG ( " biXPelsPerMeter= " < < m_InfoHeader . biXPelsPerMeter < < " specifies the the horizontal pixels per meter on the designated targer device, usually set to zero. " ) ;
EWOL_DEBUG ( " biYPelsPerMeter= " < < m_InfoHeader . biYPelsPerMeter < < " specifies the the vertical pixels per meter on the designated targer device, usually set to zero. " ) ;
2011-11-04 17:43:24 +01:00
EWOL_DEBUG ( " biClrUsed = " < < m_InfoHeader . biClrUsed < < " speglTexImage2Dcifies the number of colors used in the bitmap, if set to zero the number of colors is calculated using the biBitCount member. " ) ;
2011-10-28 18:19:04 +02:00
EWOL_DEBUG ( " biClrImportant = " < < m_InfoHeader . biClrImportant < < " specifies the number of color that are 'important' for the bitmap, if set to zero, all colors are important. " ) ;
}
EWOL_DEBUG ( " Bitmap : " < < m_width < < " x " < < m_height ) ;
switch ( m_dataMode )
{
case BITS_16_R5G6B5 :
EWOL_DEBUG ( " mode = 16 bits R5G6B5 " ) ;
break ;
case BITS_16_X1R5G5B5 :
EWOL_DEBUG ( " mode = 16 bits X1R5G5B5 " ) ;
break ;
case BITS_24_R8G8B8 :
EWOL_DEBUG ( " mode = 24 bits R8G8B8 " ) ;
break ;
case BITS_32_X8R8G8B8 :
EWOL_DEBUG ( " mode = 32 bits X8R8G8B8 " ) ;
break ;
2011-10-29 17:32:11 +02:00
case BITS_32_A8R8G8B8 :
EWOL_DEBUG ( " mode = 32 bits A8R8G8B8 " ) ;
break ;
2011-10-28 18:19:04 +02:00
default :
EWOL_DEBUG ( " mode = ERROR " ) ;
break ;
}
}
} ;
# include <GL/gl.h>
# include <GL/glu.h>
2011-10-30 14:52:55 +01:00
class LoadedTexture
{
public :
etk : : File m_filename ;
int32_t m_nbTimeLoaded ;
int32_t m_imageSize ; // must be x=y ...
uint32_t m_openGlTextureID ;
} ;
etk : : VectorType < LoadedTexture * > listLoadedTexture ;
# undef __class__
# define __class__ "ewol"
2011-10-29 17:32:11 +02:00
int32_t ewol : : LoadTexture ( etk : : File fileName )
2011-10-28 18:19:04 +02:00
{
2011-10-30 14:52:55 +01:00
if ( listLoadedTexture . Size ( ) ! = 0 ) {
for ( int32_t iii = 0 ; iii < listLoadedTexture . Size ( ) ; iii + + ) {
if ( listLoadedTexture [ iii ] - > m_filename = = fileName ) {
listLoadedTexture [ iii ] - > m_nbTimeLoaded + + ;
return listLoadedTexture [ iii ] - > m_openGlTextureID ;
}
}
}
2011-10-28 18:19:04 +02:00
etk : : String fileExtention = fileName . GetExtention ( ) ;
if ( fileExtention = = " bmp " ) {
if ( false = = fileName . Exist ( ) ) {
EWOL_ERROR ( " File does not Exist ... " < < fileName ) ;
return - 1 ;
}
Bitmap myBitmap ( fileName ) ;
myBitmap . Display ( ) ;
if ( myBitmap . LoadOK ( ) = = true ) {
2011-10-30 14:52:55 +01:00
if ( myBitmap . Width ( ) ! = myBitmap . Height ( ) ) {
EWOL_ERROR ( " Texture can not have Width= " < < myBitmap . Width ( ) < < " px different of height= " < < myBitmap . Height ( ) < < " px in file: " < < fileName ) ;
return - 1 ;
}
2011-10-28 18:19:04 +02:00
GLuint textureid ;
glGenTextures ( 1 , & textureid ) ;
glBindTexture ( GL_TEXTURE_2D , textureid ) ;
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
//--- mode nearest
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
//--- Mode linear
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGBA , myBitmap . Width ( ) , myBitmap . Height ( ) , 0 , GL_RGBA , GL_UNSIGNED_BYTE , myBitmap . Data ( ) ) ;
2011-10-30 14:52:55 +01:00
LoadedTexture * tmpTex = new LoadedTexture ( ) ;
if ( NULL ! = tmpTex ) {
tmpTex - > m_filename = fileName ;
tmpTex - > m_nbTimeLoaded = 1 ;
tmpTex - > m_imageSize = myBitmap . Width ( ) ;
tmpTex - > m_openGlTextureID = textureid ;
listLoadedTexture . PushBack ( tmpTex ) ;
} else {
EWOL_ERROR ( " Allocation ERROR... " ) ;
}
2011-10-28 18:19:04 +02:00
return textureid ;
} else {
return - 1 ;
}
} else {
2011-10-30 14:52:55 +01:00
EWOL_ERROR ( " Extention not managed " < < fileName < < " Sopported extention : .bmp " ) ;
2011-10-28 18:19:04 +02:00
return - 1 ;
}
}
2011-10-30 14:52:55 +01:00
void ewol : : UnLoadTexture ( uint32_t textureID )
2011-10-28 18:19:04 +02:00
{
2011-10-30 18:29:09 +01:00
for ( int32_t iii = 0 ; iii < listLoadedTexture . Size ( ) ; iii + + ) {
if ( listLoadedTexture [ iii ] - > m_openGlTextureID = = textureID ) {
listLoadedTexture [ iii ] - > m_nbTimeLoaded - - ;
if ( 0 = = listLoadedTexture [ iii ] - > m_nbTimeLoaded ) {
EWOL_DEBUG ( " Remove openGL texture ID= " < < textureID < < " file: " < < listLoadedTexture [ iii ] - > m_filename ) ;
glDeleteTextures ( 1 , & listLoadedTexture [ iii ] - > m_openGlTextureID ) ;
delete ( listLoadedTexture [ iii ] ) ;
listLoadedTexture [ iii ] = NULL ;
listLoadedTexture . Erase ( iii ) ;
2011-10-30 14:52:55 +01:00
}
2011-10-30 18:29:09 +01:00
return ;
2011-10-30 14:52:55 +01:00
}
}
EWOL_CRITICAL ( " Can not find TextureId= " < < textureID < < " in the list of texture loaded...==> to remove it ... " ) ;
2011-10-28 18:19:04 +02:00
}
2011-10-30 14:52:55 +01:00
int32_t ewol : : GetTextureSize ( uint32_t textureID )
{
2011-10-30 18:29:09 +01:00
for ( int32_t iii = 0 ; iii < listLoadedTexture . Size ( ) ; iii + + ) {
if ( listLoadedTexture [ iii ] - > m_openGlTextureID = = textureID ) {
return listLoadedTexture [ iii ] - > m_imageSize ;
2011-10-30 14:52:55 +01:00
}
}
EWOL_ERROR ( " Can not find TextureId= " < < textureID < < " in the list of texture loaded... " ) ;
return - 1 ;
}