@ -141,6 +141,17 @@ Image LoadImage(const char *fileName)
else if ( strcmp ( GetExtension ( fileName ) , " ktx " ) = = 0 ) image = LoadKTX ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " ktx " ) = = 0 ) image = LoadKTX ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " pvr " ) = = 0 ) image = LoadPVR ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " pvr " ) = = 0 ) image = LoadPVR ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " astc " ) = = 0 ) image = LoadASTC ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " astc " ) = = 0 ) image = LoadASTC ( fileName ) ;
else if ( strcmp ( GetExtension ( fileName ) , " rres " ) = = 0 )
{
RRESData rres = LoadResource ( fileName ) ;
/ / NOTE : Parameters for RRES_IMAGE type are : width , height , format , mipmaps
if ( rres . type = = RRES_IMAGE ) image = LoadImagePro ( rres . data , rres . param1 , rres . param2 , rres . param3 ) ;
else TraceLog ( WARNING , " [%s] Resource file does not contain image data " , fileName ) ;
UnloadResource ( rres ) ;
}
if ( image . data ! = NULL ) TraceLog ( INFO , " [%s] Image loaded successfully (%ix%i) " , fileName , image . width , image . height ) ;
if ( image . data ! = NULL ) TraceLog ( INFO , " [%s] Image loaded successfully (%ix%i) " , fileName , image . width , image . height ) ;
else TraceLog ( WARNING , " [%s] Image could not be loaded " , fileName ) ;
else TraceLog ( WARNING , " [%s] Image could not be loaded " , fileName ) ;
@ -176,18 +187,20 @@ Image LoadImageEx(Color *pixels, int width, int height)
}
}
/ / Load image from raw data with parameters
/ / Load image from raw data with parameters
/ / NOTE : This functions does not make a copy of data
/ / NOTE : This functions makes a copy of provided data
Image LoadImagePro ( void * data , int width , int height , int format )
Image LoadImagePro ( void * data , int width , int height , int format )
{
{
Image image ;
Image srcImage = { 0 } ;
srcImage . data = data ;
srcImage . width = width ;
srcImage . height = height ;
srcImage . mipmaps = 1 ;
srcImage . format = format ;
image . data = data ;
image . width = width ;
image . height = height ;
image . mipmaps = 1 ;
image . format = format ;
Image dstImage = ImageCopy ( srcImage ) ;
return i mage;
return dstImage ;
}
}
/ / Load an image from RAW file data
/ / Load an image from RAW file data
@ -669,11 +682,11 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
/ / NOTE : We will store the dithered data as unsigned short ( 16 bpp )
/ / NOTE : We will store the dithered data as unsigned short ( 16 bpp )
image - > data = ( unsigned short * ) malloc ( image - > width * image - > height * sizeof ( unsigned short ) ) ;
image - > data = ( unsigned short * ) malloc ( image - > width * image - > height * sizeof ( unsigned short ) ) ;
Color oldp ixel = WHITE ;
Color newp ixel = WHITE ;
Color oldP ixel = WHITE ;
Color newP ixel = WHITE ;
int error_r , error_g , error_b ;
unsigned short pixel_r , pixel_g , pixel_b , pixel_a ; / / Used for 16 bit pixel composition
int rError , gError , bError ;
unsigned short rPixel , gPixel , bPixel , aPixel ; / / Used for 16 bit pixel composition
# define MIN(a,b) (((a)<(b))?(a):(b))
# define MIN(a,b) (((a)<(b))?(a):(b))
@ -681,57 +694,57 @@ void ImageDither(Image *image, int rBpp, int gBpp, int bBpp, int aBpp)
{
{
for ( int x = 0 ; x < image - > width ; x + + )
for ( int x = 0 ; x < image - > width ; x + + )
{
{
oldp ixel = pixels [ y * image - > width + x ] ;
oldP ixel = pixels [ y * image - > width + x ] ;
/ / NOTE : New pixel obtained by bits truncate , it would be better to round values ( check ImageFormat ( ) )
/ / NOTE : New pixel obtained by bits truncate , it would be better to round values ( check ImageFormat ( ) )
newp ixel . r = oldp ixel . r > > ( 8 - rBpp ) ; / / R bits
newp ixel . g = oldp ixel . g > > ( 8 - gBpp ) ; / / G bits
newp ixel . b = oldp ixel . b > > ( 8 - bBpp ) ; / / B bits
newp ixel . a = oldp ixel . a > > ( 8 - aBpp ) ; / / A bits ( not used on dithering )
newP ixel . r = oldP ixel . r > > ( 8 - rBpp ) ; / / R bits
newP ixel . g = oldP ixel . g > > ( 8 - gBpp ) ; / / G bits
newP ixel . b = oldP ixel . b > > ( 8 - bBpp ) ; / / B bits
newP ixel . a = oldP ixel . a > > ( 8 - aBpp ) ; / / A bits ( not used on dithering )
/ / NOTE : Error must be computed between new and old pixel but using same number of bits !
/ / NOTE : Error must be computed between new and old pixel but using same number of bits !
/ / We want to know how much color precision we have lost . . .
/ / We want to know how much color precision we have lost . . .
error_ r = ( int ) oldp ixel . r - ( int ) ( newp ixel . r < < ( 8 - rBpp ) ) ;
error_g = ( int ) oldp ixel . g - ( int ) ( newp ixel . g < < ( 8 - gBpp ) ) ;
error_b = ( int ) oldp ixel . b - ( int ) ( newp ixel . b < < ( 8 - bBpp ) ) ;
rErro r = ( int ) oldP ixel . r - ( int ) ( newP ixel . r < < ( 8 - rBpp ) ) ;
gError = ( int ) oldP ixel . g - ( int ) ( newP ixel . g < < ( 8 - gBpp ) ) ;
bError = ( int ) oldP ixel . b - ( int ) ( newP ixel . b < < ( 8 - bBpp ) ) ;
pixels [ y * image - > width + x ] = newp ixel ;
pixels [ y * image - > width + x ] = newP ixel ;
/ / NOTE : Some cases are out of the array and should be ignored
/ / NOTE : Some cases are out of the array and should be ignored
if ( x < ( image - > width - 1 ) )
if ( x < ( image - > width - 1 ) )
{
{
pixels [ y * image - > width + x + 1 ] . r = MIN ( ( int ) pixels [ y * image - > width + x + 1 ] . r + ( int ) ( ( float ) error_ r* 7.0f / 16 ) , 0xff ) ;
pixels [ y * image - > width + x + 1 ] . g = MIN ( ( int ) pixels [ y * image - > width + x + 1 ] . g + ( int ) ( ( float ) error_g * 7.0f / 16 ) , 0xff ) ;
pixels [ y * image - > width + x + 1 ] . b = MIN ( ( int ) pixels [ y * image - > width + x + 1 ] . b + ( int ) ( ( float ) error_b * 7.0f / 16 ) , 0xff ) ;
pixels [ y * image - > width + x + 1 ] . r = MIN ( ( int ) pixels [ y * image - > width + x + 1 ] . r + ( int ) ( ( float ) rErro r* 7.0f / 16 ) , 0xff ) ;
pixels [ y * image - > width + x + 1 ] . g = MIN ( ( int ) pixels [ y * image - > width + x + 1 ] . g + ( int ) ( ( float ) gError * 7.0f / 16 ) , 0xff ) ;
pixels [ y * image - > width + x + 1 ] . b = MIN ( ( int ) pixels [ y * image - > width + x + 1 ] . b + ( int ) ( ( float ) bError * 7.0f / 16 ) , 0xff ) ;
}
}
if ( ( x > 0 ) & & ( y < ( image - > height - 1 ) ) )
if ( ( x > 0 ) & & ( y < ( image - > height - 1 ) ) )
{
{
pixels [ ( y + 1 ) * image - > width + x - 1 ] . r = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x - 1 ] . r + ( int ) ( ( float ) error_ r* 3.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x - 1 ] . g = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x - 1 ] . g + ( int ) ( ( float ) error_g * 3.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x - 1 ] . b = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x - 1 ] . b + ( int ) ( ( float ) error_b * 3.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x - 1 ] . r = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x - 1 ] . r + ( int ) ( ( float ) rErro r* 3.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x - 1 ] . g = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x - 1 ] . g + ( int ) ( ( float ) gError * 3.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x - 1 ] . b = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x - 1 ] . b + ( int ) ( ( float ) bError * 3.0f / 16 ) , 0xff ) ;
}
}
if ( y < ( image - > height - 1 ) )
if ( y < ( image - > height - 1 ) )
{
{
pixels [ ( y + 1 ) * image - > width + x ] . r = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x ] . r + ( int ) ( ( float ) error_ r* 5.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x ] . g = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x ] . g + ( int ) ( ( float ) error_g * 5.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x ] . b = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x ] . b + ( int ) ( ( float ) error_b * 5.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x ] . r = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x ] . r + ( int ) ( ( float ) rErro r* 5.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x ] . g = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x ] . g + ( int ) ( ( float ) gError * 5.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x ] . b = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x ] . b + ( int ) ( ( float ) bError * 5.0f / 16 ) , 0xff ) ;
}
}
if ( ( x < ( image - > width - 1 ) ) & & ( y < ( image - > height - 1 ) ) )
if ( ( x < ( image - > width - 1 ) ) & & ( y < ( image - > height - 1 ) ) )
{
{
pixels [ ( y + 1 ) * image - > width + x + 1 ] . r = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x + 1 ] . r + ( int ) ( ( float ) error_ r* 1.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x + 1 ] . g = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x + 1 ] . g + ( int ) ( ( float ) error_g * 1.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x + 1 ] . b = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x + 1 ] . b + ( int ) ( ( float ) error_b * 1.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x + 1 ] . r = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x + 1 ] . r + ( int ) ( ( float ) rErro r* 1.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x + 1 ] . g = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x + 1 ] . g + ( int ) ( ( float ) gError * 1.0f / 16 ) , 0xff ) ;
pixels [ ( y + 1 ) * image - > width + x + 1 ] . b = MIN ( ( int ) pixels [ ( y + 1 ) * image - > width + x + 1 ] . b + ( int ) ( ( float ) bError * 1.0f / 16 ) , 0xff ) ;
}
}
pixel_r = ( unsigned short ) newp ixel . r ;
pixel_g = ( unsigned short ) newp ixel . g ;
pixel_b = ( unsigned short ) newp ixel . b ;
pixel_a = ( unsigned short ) newp ixel . a ;
rPixel = ( unsigned short ) newP ixel . r ;
gPixel = ( unsigned short ) newP ixel . g ;
bPixel = ( unsigned short ) newP ixel . b ;
aPixel = ( unsigned short ) newP ixel . a ;
( ( unsigned short * ) image - > data ) [ y * image - > width + x ] = ( pixel_r < < ( gBpp + bBpp + aBpp ) ) | ( pixel_g < < ( bBpp + aBpp ) ) | ( pixel_b < < aBpp ) | pixel_a ;
( ( unsigned short * ) image - > data ) [ y * image - > width + x ] = ( rPixel < < ( gBpp + bBpp + aBpp ) ) | ( gPixel < < ( bBpp + aBpp ) ) | ( bPixel < < aBpp ) | aPixel ;
}
}
}
}
@ -788,24 +801,37 @@ Image ImageCopy(Image image)
{
{
Image newImage ;
Image newImage ;
int s ize = image . width * image . height ;
int byteS ize = image . width * image . height ;
switch ( image . format )
switch ( image . format )
{
{
case UNCOMPRESSED_GRAYSCALE : newImage . data = ( unsigned char * ) malloc ( size ) ; break ; / / 8 bit per pixel ( no alpha )
case UNCOMPRESSED_GRAY_ALPHA : newImage . data = ( unsigned char * ) malloc ( size * 2 ) ; size * = 2 ; break ; / / 16 bpp ( 2 channels )
case UNCOMPRESSED_R5G6B5 : newImage . data = ( unsigned short * ) malloc ( size ) ; size * = 2 ; break ; / / 16 bpp
case UNCOMPRESSED_R8G8B8 : newImage . data = ( unsigned char * ) malloc ( size * 3 ) ; size * = 3 ; break ; / / 24 bpp
case UNCOMPRESSED_R5G5B5A1 : newImage . data = ( unsigned short * ) malloc ( size ) ; size * = 2 ; break ; / / 16 bpp ( 1 bit alpha )
case UNCOMPRESSED_R4G4B4A4 : newImage . data = ( unsigned short * ) malloc ( size ) ; size * = 2 ; break ; / / 16 bpp ( 4 bit alpha )
case UNCOMPRESSED_R8G8B8A8 : newImage . data = ( unsigned char * ) malloc ( size * 4 ) ; size * = 4 ; break ; / / 32 bpp
default : TraceLog ( WARNING , " Image format not suported for copy " ) ; break ;
case UNCOMPRESSED_GRAYSCALE : break ; / / 8 bpp ( 1 byte )
case UNCOMPRESSED_GRAY_ALPHA : / / 16 bpp
case UNCOMPRESSED_R5G6B5 : / / 16 bpp
case UNCOMPRESSED_R5G5B5A1 : / / 16 bpp
case UNCOMPRESSED_R4G4B4A4 : byteSize * = 2 ; break ; / / 16 bpp ( 2 bytes )
case UNCOMPRESSED_R8G8B8 : byteSize * = 3 ; break ; / / 24 bpp ( 3 bytes )
case UNCOMPRESSED_R8G8B8A8 : byteSize * = 4 ; break ; / / 32 bpp ( 4 bytes )
case COMPRESSED_DXT3_RGBA :
case COMPRESSED_DXT5_RGBA :
case COMPRESSED_ETC2_EAC_RGBA :
case COMPRESSED_ASTC_4x4_RGBA : break ; / / 8 bpp ( 1 byte )
case COMPRESSED_DXT1_RGB :
case COMPRESSED_DXT1_RGBA :
case COMPRESSED_ETC1_RGB :
case COMPRESSED_ETC2_RGB :
case COMPRESSED_PVRT_RGB :
case COMPRESSED_PVRT_RGBA : byteSize / = 2 ; break ; / / 4 bpp
case COMPRESSED_ASTC_8x8_RGBA : byteSize / = 4 ; break ; / / 2 bpp
default : TraceLog ( WARNING , " Image format not recognized " ) ; break ;
}
}
newImage . data = malloc ( byteSize ) ;
if ( newImage . data ! = NULL )
if ( newImage . data ! = NULL )
{
{
/ / NOTE : Size must be provided in bytes
/ / NOTE : Size must be provided in bytes
memcpy ( newImage . data , image . data , size ) ;
memcpy ( newImage . data , image . data , byteS ize) ;
newImage . width = image . width ;
newImage . width = image . width ;
newImage . height = image . height ;
newImage . height = image . height ;
@ -1524,7 +1550,7 @@ static Image LoadDDS(const char *fileName)
unsigned int gBitMask ;
unsigned int gBitMask ;
unsigned int bBitMask ;
unsigned int bBitMask ;
unsigned int aBitMask ;
unsigned int aBitMask ;
} dds PixelFormat;
} DDS PixelFormat;
/ / DDS Header ( 124 bytes )
/ / DDS Header ( 124 bytes )
typedef struct {
typedef struct {
@ -1536,13 +1562,13 @@ static Image LoadDDS(const char *fileName)
unsigned int depth ;
unsigned int depth ;
unsigned int mipmapCount ;
unsigned int mipmapCount ;
unsigned int reserved1 [ 11 ] ;
unsigned int reserved1 [ 11 ] ;
dds PixelFormat ddspf ;
DDS PixelFormat ddspf ;
unsigned int caps ;
unsigned int caps ;
unsigned int caps2 ;
unsigned int caps2 ;
unsigned int caps3 ;
unsigned int caps3 ;
unsigned int caps4 ;
unsigned int caps4 ;
unsigned int reserved2 ;
unsigned int reserved2 ;
} dds Header;
} DDS Header;
Image image ;
Image image ;
@ -1571,33 +1597,33 @@ static Image LoadDDS(const char *fileName)
}
}
else
else
{
{
ddsHeader h eader;
DDSHeader ddsH eader;
/ / Get the image header
/ / Get the image header
fread ( & h eader, sizeof ( dds Header) , 1 , ddsFile ) ;
fread ( & ddsH eader, sizeof ( DDS Header) , 1 , ddsFile ) ;
TraceLog ( DEBUG , " [%s] DDS file header size: %i " , fileName , sizeof ( dds Header) ) ;
TraceLog ( DEBUG , " [%s] DDS file pixel format size: %i " , fileName , h eader. ddspf . size ) ;
TraceLog ( DEBUG , " [%s] DDS file pixel format flags: 0x%x " , fileName , h eader. ddspf . flags ) ;
TraceLog ( DEBUG , " [%s] DDS file format: 0x%x " , fileName , h eader. ddspf . fourCC ) ;
TraceLog ( DEBUG , " [%s] DDS file bit count: 0x%x " , fileName , h eader. ddspf . rgbBitCount ) ;
TraceLog ( DEBUG , " [%s] DDS file header size: %i " , fileName , sizeof ( DDS Header) ) ;
TraceLog ( DEBUG , " [%s] DDS file pixel format size: %i " , fileName , ddsH eader. ddspf . size ) ;
TraceLog ( DEBUG , " [%s] DDS file pixel format flags: 0x%x " , fileName , ddsH eader. ddspf . flags ) ;
TraceLog ( DEBUG , " [%s] DDS file format: 0x%x " , fileName , ddsH eader. ddspf . fourCC ) ;
TraceLog ( DEBUG , " [%s] DDS file bit count: 0x%x " , fileName , ddsH eader. ddspf . rgbBitCount ) ;
image . width = h eader. width ;
image . height = h eader. height ;
image . mipmaps = 1 ; / / Default value , could be changed ( h eader. mipmapCount )
image . width = ddsH eader. width ;
image . height = ddsH eader. height ;
image . mipmaps = 1 ; / / Default value , could be changed ( ddsH eader. mipmapCount )
if ( h eader. ddspf . rgbBitCount = = 16 ) / / 16 bit mode , no compressed
if ( ddsH eader. ddspf . rgbBitCount = = 16 ) / / 16 bit mode , no compressed
{
{
if ( h eader. ddspf . flags = = 0x40 ) / / no alpha channel
if ( ddsH eader. ddspf . flags = = 0x40 ) / / no alpha channel
{
{
image . data = ( unsigned short * ) malloc ( image . width * image . height * sizeof ( unsigned short ) ) ;
image . data = ( unsigned short * ) malloc ( image . width * image . height * sizeof ( unsigned short ) ) ;
fread ( image . data , image . width * image . height * sizeof ( unsigned short ) , 1 , ddsFile ) ;
fread ( image . data , image . width * image . height * sizeof ( unsigned short ) , 1 , ddsFile ) ;
image . format = UNCOMPRESSED_R5G6B5 ;
image . format = UNCOMPRESSED_R5G6B5 ;
}
}
else if ( h eader. ddspf . flags = = 0x41 ) / / with alpha channel
else if ( ddsH eader. ddspf . flags = = 0x41 ) / / with alpha channel
{
{
if ( h eader. ddspf . aBitMask = = 0x8000 ) / / 1 bit alpha
if ( ddsH eader. ddspf . aBitMask = = 0x8000 ) / / 1 bit alpha
{
{
image . data = ( unsigned short * ) malloc ( image . width * image . height * sizeof ( unsigned short ) ) ;
image . data = ( unsigned short * ) malloc ( image . width * image . height * sizeof ( unsigned short ) ) ;
fread ( image . data , image . width * image . height * sizeof ( unsigned short ) , 1 , ddsFile ) ;
fread ( image . data , image . width * image . height * sizeof ( unsigned short ) , 1 , ddsFile ) ;
@ -1614,7 +1640,7 @@ static Image LoadDDS(const char *fileName)
image . format = UNCOMPRESSED_R5G5B5A1 ;
image . format = UNCOMPRESSED_R5G5B5A1 ;
}
}
else if ( h eader. ddspf . aBitMask = = 0xf000 ) / / 4 bit alpha
else if ( ddsH eader. ddspf . aBitMask = = 0xf000 ) / / 4 bit alpha
{
{
image . data = ( unsigned short * ) malloc ( image . width * image . height * sizeof ( unsigned short ) ) ;
image . data = ( unsigned short * ) malloc ( image . width * image . height * sizeof ( unsigned short ) ) ;
fread ( image . data , image . width * image . height * sizeof ( unsigned short ) , 1 , ddsFile ) ;
fread ( image . data , image . width * image . height * sizeof ( unsigned short ) , 1 , ddsFile ) ;
@ -1633,7 +1659,7 @@ static Image LoadDDS(const char *fileName)
}
}
}
}
}
}
if ( h eader. ddspf . flags = = 0x40 & & h eader. ddspf . rgbBitCount = = 24 ) / / DDS_RGB , no compressed
if ( ddsH eader. ddspf . flags = = 0x40 & & ddsH eader. ddspf . rgbBitCount = = 24 ) / / DDS_RGB , no compressed
{
{
/ / NOTE : not sure if this case exists . . .
/ / NOTE : not sure if this case exists . . .
image . data = ( unsigned char * ) malloc ( image . width * image . height * 3 * sizeof ( unsigned char ) ) ;
image . data = ( unsigned char * ) malloc ( image . width * image . height * 3 * sizeof ( unsigned char ) ) ;
@ -1641,7 +1667,7 @@ static Image LoadDDS(const char *fileName)
image . format = UNCOMPRESSED_R8G8B8 ;
image . format = UNCOMPRESSED_R8G8B8 ;
}
}
else if ( h eader. ddspf . flags = = 0x41 & & h eader. ddspf . rgbBitCount = = 32 ) / / DDS_RGBA , no compressed
else if ( ddsH eader. ddspf . flags = = 0x41 & & ddsH eader. ddspf . rgbBitCount = = 32 ) / / DDS_RGBA , no compressed
{
{
image . data = ( unsigned char * ) malloc ( image . width * image . height * 4 * sizeof ( unsigned char ) ) ;
image . data = ( unsigned char * ) malloc ( image . width * image . height * 4 * sizeof ( unsigned char ) ) ;
fread ( image . data , image . width * image . height * 4 , 1 , ddsFile ) ;
fread ( image . data , image . width * image . height * 4 , 1 , ddsFile ) ;
@ -1660,27 +1686,27 @@ static Image LoadDDS(const char *fileName)
image . format = UNCOMPRESSED_R8G8B8A8 ;
image . format = UNCOMPRESSED_R8G8B8A8 ;
}
}
else if ( ( ( h eader. ddspf . flags = = 0x04 ) | | ( h eader. ddspf . flags = = 0x05 ) ) & & ( h eader. ddspf . fourCC > 0 ) ) / / Compressed
else if ( ( ( ddsH eader. ddspf . flags = = 0x04 ) | | ( ddsH eader. ddspf . flags = = 0x05 ) ) & & ( ddsH eader. ddspf . fourCC > 0 ) ) / / Compressed
{
{
int bufsize ;
int bufsize ;
/ / Calculate data size , including all mipmaps
/ / Calculate data size , including all mipmaps
if ( h eader. mipmapCount > 1 ) bufsize = h eader. pitchOrLinearSize * 2 ;
else bufsize = h eader. pitchOrLinearSize ;
if ( ddsH eader. mipmapCount > 1 ) bufsize = ddsH eader. pitchOrLinearSize * 2 ;
else bufsize = ddsH eader. pitchOrLinearSize ;
TraceLog ( DEBUG , " Pitch or linear size: %i " , h eader. pitchOrLinearSize ) ;
TraceLog ( DEBUG , " Pitch or linear size: %i " , ddsH eader. pitchOrLinearSize ) ;
image . data = ( unsigned char * ) malloc ( bufsize * sizeof ( unsigned char ) ) ;
image . data = ( unsigned char * ) malloc ( bufsize * sizeof ( unsigned char ) ) ;
fread ( image . data , 1 , bufsize , ddsFile ) ;
fread ( image . data , 1 , bufsize , ddsFile ) ;
image . mipmaps = h eader. mipmapCount ;
image . mipmaps = ddsH eader. mipmapCount ;
switch ( h eader. ddspf . fourCC )
switch ( ddsH eader. ddspf . fourCC )
{
{
case FOURCC_DXT1 :
case FOURCC_DXT1 :
{
{
if ( h eader. ddspf . flags = = 0x04 ) image . format = COMPRESSED_DXT1_RGB ;
if ( ddsH eader. ddspf . flags = = 0x04 ) image . format = COMPRESSED_DXT1_RGB ;
else image . format = COMPRESSED_DXT1_RGBA ;
else image . format = COMPRESSED_DXT1_RGBA ;
} break ;
} break ;
case FOURCC_DXT3 : image . format = COMPRESSED_DXT3_RGBA ; break ;
case FOURCC_DXT3 : image . format = COMPRESSED_DXT3_RGBA ; break ;
@ -1719,7 +1745,7 @@ static Image LoadPKM(const char *fileName)
unsigned short height ; / / Texture height ( big - endian ) ( origHeight rounded to multiple of 4 )
unsigned short height ; / / Texture height ( big - endian ) ( origHeight rounded to multiple of 4 )
unsigned short origWidth ; / / Original width ( big - endian )
unsigned short origWidth ; / / Original width ( big - endian )
unsigned short origHeight ; / / Original height ( big - endian )
unsigned short origHeight ; / / Original height ( big - endian )
} pkm Header;
} PKM Header;
/ / Formats list
/ / Formats list
/ / version 10 : format : 0 = ETC1_RGB , [ 1 = ETC1_RGBA , 2 = ETC1_RGB_MIP , 3 = ETC1_RGBA_MIP ] ( not used )
/ / version 10 : format : 0 = ETC1_RGB , [ 1 = ETC1_RGBA , 2 = ETC1_RGB_MIP , 3 = ETC1_RGBA_MIP ] ( not used )
@ -1744,32 +1770,32 @@ static Image LoadPKM(const char *fileName)
}
}
else
else
{
{
pkmHeader h eader;
PKMHeader pkmH eader;
/ / Get the image header
/ / Get the image header
fread ( & h eader, sizeof ( pkm Header) , 1 , pkmFile ) ;
fread ( & pkmH eader, sizeof ( PKM Header) , 1 , pkmFile ) ;
if ( strncmp ( h eader. id , " PKM " , 4 ) ! = 0 )
if ( strncmp ( pkmH eader. id , " PKM " , 4 ) ! = 0 )
{
{
TraceLog ( WARNING , " [%s] PKM file does not seem to be a valid image " , fileName ) ;
TraceLog ( WARNING , " [%s] PKM file does not seem to be a valid image " , fileName ) ;
}
}
else
else
{
{
/ / NOTE : format , width and height come as big - endian , data must be swapped to little - endian
/ / NOTE : format , width and height come as big - endian , data must be swapped to little - endian
h eader. format = ( ( h eader. format & 0x00FF ) < < 8 ) | ( ( h eader. format & 0xFF00 ) > > 8 ) ;
h eader. width = ( ( h eader. width & 0x00FF ) < < 8 ) | ( ( h eader. width & 0xFF00 ) > > 8 ) ;
h eader. height = ( ( h eader. height & 0x00FF ) < < 8 ) | ( ( h eader. height & 0xFF00 ) > > 8 ) ;
pkmH eader. format = ( ( pkmH eader. format & 0x00FF ) < < 8 ) | ( ( pkmH eader. format & 0xFF00 ) > > 8 ) ;
pkmH eader. width = ( ( pkmH eader. width & 0x00FF ) < < 8 ) | ( ( pkmH eader. width & 0xFF00 ) > > 8 ) ;
pkmH eader. height = ( ( pkmH eader. height & 0x00FF ) < < 8 ) | ( ( pkmH eader. height & 0xFF00 ) > > 8 ) ;
TraceLog ( DEBUG , " PKM (ETC) image width: %i " , h eader. width ) ;
TraceLog ( DEBUG , " PKM (ETC) image height: %i " , h eader. height ) ;
TraceLog ( DEBUG , " PKM (ETC) image format: %i " , h eader. format ) ;
TraceLog ( DEBUG , " PKM (ETC) image width: %i " , pkmH eader. width ) ;
TraceLog ( DEBUG , " PKM (ETC) image height: %i " , pkmH eader. height ) ;
TraceLog ( DEBUG , " PKM (ETC) image format: %i " , pkmH eader. format ) ;
image . width = h eader. width ;
image . height = h eader. height ;
image . width = pkmH eader. width ;
image . height = pkmH eader. height ;
image . mipmaps = 1 ;
image . mipmaps = 1 ;
int bpp = 4 ;
int bpp = 4 ;
if ( h eader. format = = 3 ) bpp = 8 ;
if ( pkmH eader. format = = 3 ) bpp = 8 ;
int size = image . width * image . height * bpp / 8 ; / / Total data size in bytes
int size = image . width * image . height * bpp / 8 ; / / Total data size in bytes
@ -1777,9 +1803,9 @@ static Image LoadPKM(const char *fileName)
fread ( image . data , 1 , size , pkmFile ) ;
fread ( image . data , 1 , size , pkmFile ) ;
if ( h eader. format = = 0 ) image . format = COMPRESSED_ETC1_RGB ;
else if ( h eader. format = = 1 ) image . format = COMPRESSED_ETC2_RGB ;
else if ( h eader. format = = 3 ) image . format = COMPRESSED_ETC2_EAC_RGBA ;
if ( pkmH eader. format = = 0 ) image . format = COMPRESSED_ETC1_RGB ;
else if ( pkmH eader. format = = 1 ) image . format = COMPRESSED_ETC2_RGB ;
else if ( pkmH eader. format = = 3 ) image . format = COMPRESSED_ETC2_EAC_RGBA ;
}
}
fclose ( pkmFile ) ; / / Close file pointer
fclose ( pkmFile ) ; / / Close file pointer
@ -1817,7 +1843,7 @@ static Image LoadKTX(const char *fileName)
unsigned int faces ; / / Cubemap faces , for no - cubemap = 1
unsigned int faces ; / / Cubemap faces , for no - cubemap = 1
unsigned int mipmapLevels ; / / Non - mipmapped textures = 1
unsigned int mipmapLevels ; / / Non - mipmapped textures = 1
unsigned int keyValueDataSize ; / / Used to encode any arbitrary data . . .
unsigned int keyValueDataSize ; / / Used to encode any arbitrary data . . .
} ktx Header;
} KTX Header;
/ / NOTE : Before start of every mipmap data block , we have : unsigned int dataSize
/ / NOTE : Before start of every mipmap data block , we have : unsigned int dataSize
@ -1836,31 +1862,31 @@ static Image LoadKTX(const char *fileName)
}
}
else
else
{
{
ktxHeader h eader;
KTXHeader ktxH eader;
/ / Get the image header
/ / Get the image header
fread ( & h eader, sizeof ( ktx Header) , 1 , ktxFile ) ;
fread ( & ktxH eader, sizeof ( KTX Header) , 1 , ktxFile ) ;
if ( ( h eader. id [ 1 ] ! = ' K ' ) | | ( h eader. id [ 2 ] ! = ' T ' ) | | ( h eader. id [ 3 ] ! = ' X ' ) | |
( h eader. id [ 4 ] ! = ' ' ) | | ( h eader. id [ 5 ] ! = ' 1 ' ) | | ( h eader. id [ 6 ] ! = ' 1 ' ) )
if ( ( ktxH eader. id [ 1 ] ! = ' K ' ) | | ( ktxH eader. id [ 2 ] ! = ' T ' ) | | ( ktxH eader. id [ 3 ] ! = ' X ' ) | |
( ktxH eader. id [ 4 ] ! = ' ' ) | | ( ktxH eader. id [ 5 ] ! = ' 1 ' ) | | ( ktxH eader. id [ 6 ] ! = ' 1 ' ) )
{
{
TraceLog ( WARNING , " [%s] KTX file does not seem to be a valid file " , fileName ) ;
TraceLog ( WARNING , " [%s] KTX file does not seem to be a valid file " , fileName ) ;
}
}
else
else
{
{
image . width = h eader. width ;
image . height = h eader. height ;
image . mipmaps = h eader. mipmapLevels ;
image . width = ktxH eader. width ;
image . height = ktxH eader. height ;
image . mipmaps = ktxH eader. mipmapLevels ;
TraceLog ( DEBUG , " KTX (ETC) image width: %i " , h eader. width ) ;
TraceLog ( DEBUG , " KTX (ETC) image height: %i " , h eader. height ) ;
TraceLog ( DEBUG , " KTX (ETC) image format: 0x%x " , h eader. glInternalFormat ) ;
TraceLog ( DEBUG , " KTX (ETC) image width: %i " , ktxH eader. width ) ;
TraceLog ( DEBUG , " KTX (ETC) image height: %i " , ktxH eader. height ) ;
TraceLog ( DEBUG , " KTX (ETC) image format: 0x%x " , ktxH eader. glInternalFormat ) ;
unsigned char unused ;
unsigned char unused ;
if ( h eader. keyValueDataSize > 0 )
if ( ktxH eader. keyValueDataSize > 0 )
{
{
for ( int i = 0 ; i < h eader. keyValueDataSize ; i + + ) fread ( & unused , 1 , 1 , ktxFile ) ;
for ( int i = 0 ; i < ktxH eader. keyValueDataSize ; i + + ) fread ( & unused , 1 , 1 , ktxFile ) ;
}
}
int dataSize ;
int dataSize ;
@ -1870,9 +1896,9 @@ static Image LoadKTX(const char *fileName)
fread ( image . data , 1 , dataSize , ktxFile ) ;
fread ( image . data , 1 , dataSize , ktxFile ) ;
if ( h eader. glInternalFormat = = 0x8D64 ) image . format = COMPRESSED_ETC1_RGB ;
else if ( h eader. glInternalFormat = = 0x9274 ) image . format = COMPRESSED_ETC2_RGB ;
else if ( h eader. glInternalFormat = = 0x9278 ) image . format = COMPRESSED_ETC2_EAC_RGBA ;
if ( ktxH eader. glInternalFormat = = 0x8D64 ) image . format = COMPRESSED_ETC1_RGB ;
else if ( ktxH eader. glInternalFormat = = 0x9274 ) image . format = COMPRESSED_ETC2_RGB ;
else if ( ktxH eader. glInternalFormat = = 0x9278 ) image . format = COMPRESSED_ETC2_EAC_RGBA ;
}
}
fclose ( ktxFile ) ; / / Close file pointer
fclose ( ktxFile ) ; / / Close file pointer
@ -1908,7 +1934,7 @@ static Image LoadPVR(const char *fileName)
unsigned int bitmaskAlpha ;
unsigned int bitmaskAlpha ;
unsigned int pvrTag ;
unsigned int pvrTag ;
unsigned int numSurfs ;
unsigned int numSurfs ;
} pvr HeaderV2;
} PVR HeaderV2;
# endif
# endif
/ / PVR file v3 Header ( 52 bytes )
/ / PVR file v3 Header ( 52 bytes )
@ -1927,7 +1953,7 @@ static Image LoadPVR(const char *fileName)
unsigned int numFaces ;
unsigned int numFaces ;
unsigned int numMipmaps ;
unsigned int numMipmaps ;
unsigned int metaDataSize ;
unsigned int metaDataSize ;
} pvr HeaderV3;
} PVR HeaderV3;
#if 0 / / N o t u s e d . . .
#if 0 / / N o t u s e d . . .
/ / Metadata ( usually 15 bytes )
/ / Metadata ( usually 15 bytes )
@ -1936,7 +1962,7 @@ static Image LoadPVR(const char *fileName)
unsigned int key ;
unsigned int key ;
unsigned int dataSize ; / / Not used ?
unsigned int dataSize ; / / Not used ?
unsigned char * data ; / / Not used ?
unsigned char * data ; / / Not used ?
} pvr Metadata;
} PVR Metadata;
# endif
# endif
Image image ;
Image image ;
@ -1963,44 +1989,49 @@ static Image LoadPVR(const char *fileName)
/ / Load different PVR data formats
/ / Load different PVR data formats
if ( pvrVersion = = 0x50 )
if ( pvrVersion = = 0x50 )
{
{
pvrHeaderV3 h eader;
PVRHeaderV3 pvrH eader;
/ / Get PVR image header
/ / Get PVR image header
fread ( & h eader, sizeof ( pvr HeaderV3) , 1 , pvrFile ) ;
fread ( & pvrH eader, sizeof ( PVR HeaderV3) , 1 , pvrFile ) ;
if ( ( h eader. id [ 0 ] ! = ' P ' ) | | ( h eader. id [ 1 ] ! = ' V ' ) | | ( h eader. id [ 2 ] ! = ' R ' ) | | ( h eader. id [ 3 ] ! = 3 ) )
if ( ( pvrH eader. id [ 0 ] ! = ' P ' ) | | ( pvrH eader. id [ 1 ] ! = ' V ' ) | | ( pvrH eader. id [ 2 ] ! = ' R ' ) | | ( pvrH eader. id [ 3 ] ! = 3 ) )
{
{
TraceLog ( WARNING , " [%s] PVR file does not seem to be a valid image " , fileName ) ;
TraceLog ( WARNING , " [%s] PVR file does not seem to be a valid image " , fileName ) ;
}
}
else
else
{
{
image . width = h eader. width ;
image . height = h eader. height ;
image . mipmaps = h eader. numMipmaps ;
image . width = pvrH eader. width ;
image . height = pvrH eader. height ;
image . mipmaps = pvrH eader. numMipmaps ;
/ / Check data format
/ / Check data format
if ( ( ( header . channels [ 0 ] = = ' l ' ) & & ( header . channels [ 1 ] = = 0 ) ) & & ( header . channelDepth [ 0 ] = = 8 ) ) image . format = UNCOMPRESSED_GRAYSCALE ;
else if ( ( ( header . channels [ 0 ] = = ' l ' ) & & ( header . channels [ 1 ] = = ' a ' ) ) & & ( ( header . channelDepth [ 0 ] = = 8 ) & & ( header . channelDepth [ 1 ] = = 8 ) ) ) image . format = UNCOMPRESSED_GRAY_ALPHA ;
else if ( ( header . channels [ 0 ] = = ' r ' ) & & ( header . channels [ 1 ] = = ' g ' ) & & ( header . channels [ 2 ] = = ' b ' ) )
if ( ( ( pvrHeader . channels [ 0 ] = = ' l ' ) & & ( pvrHeader . channels [ 1 ] = = 0 ) ) & & ( pvrHeader . channelDepth [ 0 ] = = 8 ) )
image . format = UNCOMPRESSED_GRAYSCALE ;
else if ( ( ( pvrHeader . channels [ 0 ] = = ' l ' ) & & ( pvrHeader . channels [ 1 ] = = ' a ' ) ) & & ( ( pvrHeader . channelDepth [ 0 ] = = 8 ) & & ( pvrHeader . channelDepth [ 1 ] = = 8 ) ) )
image . format = UNCOMPRESSED_GRAY_ALPHA ;
else if ( ( pvrHeader . channels [ 0 ] = = ' r ' ) & & ( pvrHeader . channels [ 1 ] = = ' g ' ) & & ( pvrHeader . channels [ 2 ] = = ' b ' ) )
{
{
if ( header . channels [ 3 ] = = ' a ' )
if ( pvrH eader. channels [ 3 ] = = ' a ' )
{
{
if ( ( header . channelDepth [ 0 ] = = 5 ) & & ( header . channelDepth [ 1 ] = = 5 ) & & ( header . channelDepth [ 2 ] = = 5 ) & & ( header . channelDepth [ 3 ] = = 1 ) ) image . format = UNCOMPRESSED_R5G5B5A1 ;
else if ( ( header . channelDepth [ 0 ] = = 4 ) & & ( header . channelDepth [ 1 ] = = 4 ) & & ( header . channelDepth [ 2 ] = = 4 ) & & ( header . channelDepth [ 3 ] = = 4 ) ) image . format = UNCOMPRESSED_R4G4B4A4 ;
else if ( ( header . channelDepth [ 0 ] = = 8 ) & & ( header . channelDepth [ 1 ] = = 8 ) & & ( header . channelDepth [ 2 ] = = 8 ) & & ( header . channelDepth [ 3 ] = = 8 ) ) image . format = UNCOMPRESSED_R8G8B8A8 ;
if ( ( pvrHeader . channelDepth [ 0 ] = = 5 ) & & ( pvrHeader . channelDepth [ 1 ] = = 5 ) & & ( pvrHeader . channelDepth [ 2 ] = = 5 ) & & ( pvrHeader . channelDepth [ 3 ] = = 1 ) )
image . format = UNCOMPRESSED_R5G5B5A1 ;
else if ( ( pvrHeader . channelDepth [ 0 ] = = 4 ) & & ( pvrHeader . channelDepth [ 1 ] = = 4 ) & & ( pvrHeader . channelDepth [ 2 ] = = 4 ) & & ( pvrHeader . channelDepth [ 3 ] = = 4 ) )
image . format = UNCOMPRESSED_R4G4B4A4 ;
else if ( ( pvrHeader . channelDepth [ 0 ] = = 8 ) & & ( pvrHeader . channelDepth [ 1 ] = = 8 ) & & ( pvrHeader . channelDepth [ 2 ] = = 8 ) & & ( pvrHeader . channelDepth [ 3 ] = = 8 ) )
image . format = UNCOMPRESSED_R8G8B8A8 ;
}
}
else if ( header . channels [ 3 ] = = 0 )
else if ( pvrH eader. channels [ 3 ] = = 0 )
{
{
if ( ( h eader. channelDepth [ 0 ] = = 5 ) & & ( h eader. channelDepth [ 1 ] = = 6 ) & & ( h eader. channelDepth [ 2 ] = = 5 ) ) image . format = UNCOMPRESSED_R5G6B5 ;
else if ( ( h eader. channelDepth [ 0 ] = = 8 ) & & ( h eader. channelDepth [ 1 ] = = 8 ) & & ( h eader. channelDepth [ 2 ] = = 8 ) ) image . format = UNCOMPRESSED_R8G8B8 ;
if ( ( pvrH eader. channelDepth [ 0 ] = = 5 ) & & ( pvrH eader. channelDepth [ 1 ] = = 6 ) & & ( pvrH eader. channelDepth [ 2 ] = = 5 ) ) image . format = UNCOMPRESSED_R5G6B5 ;
else if ( ( pvrH eader. channelDepth [ 0 ] = = 8 ) & & ( pvrH eader. channelDepth [ 1 ] = = 8 ) & & ( pvrH eader. channelDepth [ 2 ] = = 8 ) ) image . format = UNCOMPRESSED_R8G8B8 ;
}
}
}
}
else if ( h eader. channels [ 0 ] = = 2 ) image . format = COMPRESSED_PVRT_RGB ;
else if ( h eader. channels [ 0 ] = = 3 ) image . format = COMPRESSED_PVRT_RGBA ;
else if ( pvrH eader. channels [ 0 ] = = 2 ) image . format = COMPRESSED_PVRT_RGB ;
else if ( pvrH eader. channels [ 0 ] = = 3 ) image . format = COMPRESSED_PVRT_RGBA ;
/ / Skip meta data header
/ / Skip meta data header
unsigned char unused = 0 ;
unsigned char unused = 0 ;
for ( int i = 0 ; i < h eader. metaDataSize ; i + + ) fread ( & unused , sizeof ( unsigned char ) , 1 , pvrFile ) ;
for ( int i = 0 ; i < pvrH eader. metaDataSize ; i + + ) fread ( & unused , sizeof ( unsigned char ) , 1 , pvrFile ) ;
/ / Calculate data size ( depends on format )
/ / Calculate data size ( depends on format )
int bpp = 0 ;
int bpp = 0 ;
@ -2054,7 +2085,7 @@ static Image LoadASTC(const char *fileName)
unsigned char width [ 3 ] ; / / Image width in pixels ( 24 bit value )
unsigned char width [ 3 ] ; / / Image width in pixels ( 24 bit value )
unsigned char height [ 3 ] ; / / Image height in pixels ( 24 bit value )
unsigned char height [ 3 ] ; / / Image height in pixels ( 24 bit value )
unsigned char lenght [ 3 ] ; / / Image Z - size ( 1 for 2 D images )
unsigned char lenght [ 3 ] ; / / Image Z - size ( 1 for 2 D images )
} astc Header;
} ASTC Header;
Image image ;
Image image ;
@ -2072,30 +2103,30 @@ static Image LoadASTC(const char *fileName)
}
}
else
else
{
{
astcHeader h eader;
ASTCHeader astcH eader;
/ / Get ASTC image header
/ / Get ASTC image header
fread ( & h eader, sizeof ( astc Header) , 1 , astcFile ) ;
fread ( & astcH eader, sizeof ( ASTC Header) , 1 , astcFile ) ;
if ( ( h eader. id [ 3 ] ! = 0x5c ) | | ( h eader. id [ 2 ] ! = 0xa1 ) | | ( h eader. id [ 1 ] ! = 0xab ) | | ( h eader. id [ 0 ] ! = 0x13 ) )
if ( ( astcH eader. id [ 3 ] ! = 0x5c ) | | ( astcH eader. id [ 2 ] ! = 0xa1 ) | | ( astcH eader. id [ 1 ] ! = 0xab ) | | ( astcH eader. id [ 0 ] ! = 0x13 ) )
{
{
TraceLog ( WARNING , " [%s] ASTC file does not seem to be a valid image " , fileName ) ;
TraceLog ( WARNING , " [%s] ASTC file does not seem to be a valid image " , fileName ) ;
}
}
else
else
{
{
/ / NOTE : Assuming Little Endian ( could it be wrong ? )
/ / NOTE : Assuming Little Endian ( could it be wrong ? )
image . width = 0x00000000 | ( ( int ) h eader. width [ 2 ] < < 16 ) | ( ( int ) h eader. width [ 1 ] < < 8 ) | ( ( int ) h eader. width [ 0 ] ) ;
image . height = 0x00000000 | ( ( int ) h eader. height [ 2 ] < < 16 ) | ( ( int ) h eader. height [ 1 ] < < 8 ) | ( ( int ) h eader. height [ 0 ] ) ;
image . width = 0x00000000 | ( ( int ) astcH eader. width [ 2 ] < < 16 ) | ( ( int ) astcH eader. width [ 1 ] < < 8 ) | ( ( int ) astcH eader. width [ 0 ] ) ;
image . height = 0x00000000 | ( ( int ) astcH eader. height [ 2 ] < < 16 ) | ( ( int ) astcH eader. height [ 1 ] < < 8 ) | ( ( int ) astcH eader. height [ 0 ] ) ;
/ / NOTE : ASTC format only contains one mipmap level
/ / NOTE : ASTC format only contains one mipmap level
image . mipmaps = 1 ;
image . mipmaps = 1 ;
TraceLog ( DEBUG , " ASTC image width: %i " , image . width ) ;
TraceLog ( DEBUG , " ASTC image width: %i " , image . width ) ;
TraceLog ( DEBUG , " ASTC image height: %i " , image . height ) ;
TraceLog ( DEBUG , " ASTC image height: %i " , image . height ) ;
TraceLog ( DEBUG , " ASTC image blocks: %ix%i " , h eader. blockX , h eader. blockY ) ;
TraceLog ( DEBUG , " ASTC image blocks: %ix%i " , astcH eader. blockX , astcH eader. blockY ) ;
/ / NOTE : Each block is always stored in 128 bit so we can calculate the bpp
/ / NOTE : Each block is always stored in 128 bit so we can calculate the bpp
int bpp = 128 / ( h eader. blockX * h eader. blockY ) ;
int bpp = 128 / ( astcH eader. blockX * astcH eader. blockY ) ;
/ / NOTE : Currently we only support 2 blocks configurations : 4 x4 and 8 x8
/ / NOTE : Currently we only support 2 blocks configurations : 4 x4 and 8 x8
if ( ( bpp = = 8 ) | | ( bpp = = 2 ) )
if ( ( bpp = = 8 ) | | ( bpp = = 2 ) )