2012-04-04 00:24:25 -05:00
# include <stdlib.h>
# include <string.h>
# include <stdint.h>
# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <stdarg.h>
# include <png.h>
# include "iff.h"
int sprite_frame_set_texel ( IFFSpriteFrame * frame , uint32_t column , uint32_t row , IFFSpriteColor color ) ;
2012-04-05 00:50:46 -05:00
int sprite_frame_set_texel_alpha ( IFFSpriteFrame * frame , uint32_t column , uint32_t row , IFFSpriteColor color , uint8_t alpha ) ;
2012-04-04 00:24:25 -05:00
int sprite_frame_export_as_targa ( IFFSpriteFrame * frame , const char * filename ) ;
int sprite_frame_export_as_png ( IFFSpriteFrame * frame , const char * filename ) ;
2012-04-05 00:50:46 -05:00
int iff_parse_sprite ( IFFChunk * ChunkInfo , const uint8_t * pBuffer , IFFFile * SourceFile )
2012-04-04 00:24:25 -05:00
{
uint32_t frameCount = 0 ;
uint32_t paletteID = 0 ;
uint32_t * offsets ;
IFFChunk * PaletteMap ;
IFFPMap * PMap ;
IFFSprite * Sprite ;
IFFSpriteFrame * Frame ;
uint32_t i = 0 ;
uint32_t l = 0 ;
2012-04-05 00:50:46 -05:00
uint32_t j = 0 ;
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
uint32_t iRow = 0 ;
uint32_t cPixelsSet = 0 ;
uint8_t bQuit = 0 ;
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
uint32_t cBytesReadInitial = 0 ;
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
uint32_t cBytesRead = 0 ;
uint16_t mRowHeader = 0 ;
uint16_t mColumnHeader = 0 ;
uint16_t eRowControlCode = 0 ;
uint16_t eColumnControlCode = 0 ;
uint16_t cBytesInThisRow = 0 ;
uint16_t cPixelCount = 0 ; /* Per-control-code pixel count*/
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
uint8_t Z ;
2012-04-04 00:24:25 -05:00
# ifdef IFF2HTML
char * outputPath ;
char * dummyName ;
char * folderName ;
# endif
2012-04-05 00:50:46 -05:00
uint32_t version = read_uint32le ( pBuffer ) ;
pBuffer + = 4 ;
2012-04-04 00:24:25 -05:00
if ( version = = 1001 )
{
2012-04-05 00:50:46 -05:00
paletteID = read_uint32le ( pBuffer ) ;
pBuffer + = 4 ;
frameCount = read_uint32le ( pBuffer ) ;
pBuffer + = 4 ;
2012-04-04 00:24:25 -05:00
}
else
{
2012-04-05 00:50:46 -05:00
frameCount = read_uint32le ( pBuffer ) ;
pBuffer + = 4 ;
paletteID = read_uint32le ( pBuffer ) ;
pBuffer + = 4 ;
2012-04-04 00:24:25 -05:00
}
2012-04-05 00:50:46 -05:00
2012-04-04 00:24:25 -05:00
/* Try to load the appropriate palette */
PaletteMap = iff_find_first_chunk ( SourceFile , " PALT " , paletteID ) ;
/* If that didn't work, try loading any palette from the IFF file */
/* Some sprites in IFFs containing only one PALT don't bother to specify a correct PALT ID */
if ( PaletteMap = = NULL )
{
2012-04-05 00:50:46 -05:00
printf ( " ERR " ) ;
fflush ( stdout ) ;
2012-04-04 00:24:25 -05:00
PaletteMap = iff_find_first_chunk ( SourceFile , " PALT " , 0 ) ;
/* If there is no existing palette data, there can be no coherent image. */
if ( PaletteMap = = NULL )
2012-04-05 00:50:46 -05:00
{
2012-04-04 00:24:25 -05:00
return 0 ;
2012-04-05 00:50:46 -05:00
}
}
if ( PaletteMap - > FormattedData = = NULL )
{
printf ( " HERE " ) ;
fflush ( stdout ) ;
iff_parse_pmap ( PaletteMap , PaletteMap - > Data ) ;
2012-04-04 00:24:25 -05:00
}
PMap = ( IFFPMap * ) PaletteMap - > FormattedData ;
offsets = ( uint32_t * ) malloc ( sizeof ( uint32_t ) * frameCount ) ;
memset ( offsets , 0 , sizeof ( uint32_t ) * frameCount ) ;
if ( version = = 1000 )
{
for ( i = 0 ; i < frameCount ; i + + )
{
2012-04-05 00:50:46 -05:00
offsets [ i ] = read_uint32le ( pBuffer ) ;
pBuffer + = 4 ;
2012-04-04 00:24:25 -05:00
}
}
Sprite = ( IFFSprite * ) malloc ( sizeof ( IFFSprite ) ) ;
Sprite - > FrameCount = frameCount ;
Sprite - > Frames = ( IFFSpriteFrame * * ) malloc ( sizeof ( IFFSpriteFrame * ) * frameCount ) ;
# ifdef IFF2HTML
Sprite - > Version = version ;
# endif
for ( l = 0 ; l < frameCount ; l + + )
{
Frame = ( IFFSpriteFrame * ) malloc ( sizeof ( IFFSpriteFrame ) ) ;
/* Version 1000 specifies offsets for each frame of image data */
if ( version = = 1000 )
2012-04-05 00:50:46 -05:00
pBuffer = ChunkInfo - > Data + offsets [ l ] ;
2012-04-04 00:24:25 -05:00
/* There are two "+=" statements here for clarity. That is optimized away by a decent compiler */
if ( version = = 1001 )
{
2012-04-05 00:50:46 -05:00
pBuffer + = 4 ; /* Version */
pBuffer + = 4 ; /* Size */
2012-04-04 00:24:25 -05:00
}
if ( version ! = 1000 & & version ! = 1001 ) /* for SPR# resources */
{
2012-04-05 00:50:46 -05:00
Frame - > YLocation = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
Frame - > YLocation = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
Frame - > Height = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
Frame - > Width = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
2012-04-04 00:24:25 -05:00
}
else
{
2012-04-05 00:50:46 -05:00
Frame - > Width = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
Frame - > Height = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
2012-04-04 00:24:25 -05:00
}
2012-04-05 00:50:46 -05:00
Frame - > Flag = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
2012-04-04 00:24:25 -05:00
if ( version = = 1000 | | version = = 1001 )
{
2012-04-05 00:50:46 -05:00
pBuffer + = 2 ;
Frame - > PaletteID = read_uint16le ( pBuffer ) ; /* This is unused or the same as the master PALT ID */
pBuffer + = 2 ;
Frame - > TransparentPixel = PMap - > Colors [ read_uint16le ( pBuffer ) ] ;
pBuffer + = 2 ;
Frame - > YLocation = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
Frame - > XLocation = read_uint16le ( pBuffer ) ;
pBuffer + = 2 ;
}
if ( Frame - > PaletteID ! = 0xA3A3 )
{
/* Try to load the appropriate palette */
PaletteMap = iff_find_first_chunk ( SourceFile , " PALT " , Frame - > PaletteID ) ;
/* If that didn't work, try loading any palette from the IFF file */
/* Some sprites in IFFs containing only one PALT don't bother to specify a correct PALT ID */
if ( PaletteMap = = NULL )
{
PaletteMap = iff_find_first_chunk ( SourceFile , " PALT " , 0 ) ;
/* If there is no existing palette data, there can be no coherent image. */
if ( PaletteMap = = NULL )
return 0 ;
}
PMap = ( IFFPMap * ) PaletteMap - > FormattedData ;
2012-04-04 00:24:25 -05:00
}
/* Now that we know the frame size, allocate the buffer to hold its texels */
Frame - > Texels = ( IFFSpriteColor * ) malloc ( sizeof ( IFFSpriteColor ) * Frame - > Width * Frame - > Height ) ;
2012-04-05 00:50:46 -05:00
iRow = 0 ;
cPixelsSet = 0 ;
bQuit = 0 ;
cBytesReadInitial = 0 ;
cBytesRead = 0 ;
mRowHeader = 0 ;
mColumnHeader = 0 ;
eRowControlCode = 0 ;
eColumnControlCode = 0 ;
cBytesInThisRow = 0 ;
cPixelCount = 0 ;
2012-04-04 00:24:25 -05:00
if ( version = = 1000 | | version = = 1001 )
{
2012-04-05 00:50:46 -05:00
while ( ! bQuit )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
mRowHeader = read_uint16le ( pBuffer ) ;
eRowControlCode = mRowHeader > > 13 ;
cBytesInThisRow = mRowHeader & 0x1FFF ;
pBuffer + = 2 ;
cBytesRead = 2 ; /* We just read the row header, which is included in cBytesInThisRow */
cPixelsSet = 0 ;
switch ( eRowControlCode )
2012-04-04 00:24:25 -05:00
{
case 0 :
2012-04-05 00:50:46 -05:00
while ( cBytesRead < cBytesInThisRow )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
mColumnHeader = read_uint16le ( pBuffer ) ;
eColumnControlCode = mColumnHeader > > 13 ;
cPixelCount = mColumnHeader & 0x1FFF ;
pBuffer + = 2 ;
cBytesRead + = 2 ;
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
switch ( eColumnControlCode )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
case 1 : /* Add cPixelCount ZRGB pixels */
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cPixelCount ; i + + )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
Z = * pBuffer + + ; /* TODO: Use the z-buffer */
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , PMap - > Colors [ * pBuffer + + ] ) ;
cBytesRead + = 2 ;
2012-04-04 00:24:25 -05:00
}
break ;
2012-04-05 00:50:46 -05:00
case 2 : /* Add cPixelCount ZRGBA pixels */
2012-04-04 00:24:25 -05:00
i = 0 ;
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cPixelCount ; i + + )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
Z = * pBuffer + + ; /* TODO: Use the z-buffer */
sprite_frame_set_texel_alpha ( Frame , cPixelsSet + + , iRow , PMap - > Colors [ * pBuffer + + ] , ( uint8_t ) * pBuffer + + ) ; /* Read and set the alpha channel's value */
cBytesRead + = 3 ;
2012-04-04 00:24:25 -05:00
}
2012-04-05 00:50:46 -05:00
/* Read EA's padding byte if the current position is not a multiple of 2 */
if ( ( pBuffer - ChunkInfo - > Data ) % 2 = = 1 )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
pBuffer + + ;
cBytesRead + + ;
2012-04-04 00:24:25 -05:00
}
break ;
2012-04-05 00:50:46 -05:00
case 3 : /* Add cPixelCount transparent pixels */
for ( i = 0 ; i < cPixelCount ; i + + )
{
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , Frame - > TransparentPixel ) ;
}
2012-04-04 00:24:25 -05:00
break ;
2012-04-05 00:50:46 -05:00
case 6 : /* Add cPixelCount RGB pixels */
2012-04-04 00:24:25 -05:00
i = 0 ;
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cPixelCount ; i + + )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , PMap - > Colors [ * pBuffer + + ] ) ;
cBytesRead + + ;
2012-04-04 00:24:25 -05:00
}
2012-04-05 00:50:46 -05:00
/* Read EA's padding byte if the current position is not a multiple of 2 */
if ( ( pBuffer - ChunkInfo - > Data ) % 2 = = 1 )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
pBuffer + + ;
cBytesRead + + ;
2012-04-04 00:24:25 -05:00
}
break ;
default :
2012-04-05 00:50:46 -05:00
/* Error reading column code */
return 0 ;
2012-04-04 00:24:25 -05:00
}
}
2012-04-05 00:50:46 -05:00
/* Set any extra (unread) texels in the current row to transparent */
while ( cPixelsSet < Frame - > Width ) { sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , Frame - > TransparentPixel ) ; }
iRow + + ;
2012-04-04 00:24:25 -05:00
break ;
case 4 :
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cBytesInThisRow ; i + + ) /* cBytesInThisRow is used as the count of rows to fill with the transparent color in this case */
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
for ( cPixelsSet = 0 ; cPixelsSet < Frame - > Width ; cPixelsSet + + )
{
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , Frame - > TransparentPixel ) ;
}
iRow + + ;
2012-04-04 00:24:25 -05:00
}
break ;
2012-04-05 00:50:46 -05:00
case 5 : /* This means to stop reading */
bQuit = 1 ;
2012-04-04 00:24:25 -05:00
break ;
default :
2012-04-05 00:50:46 -05:00
/* Error reading row code */
2012-04-04 00:24:25 -05:00
return 0 ;
}
2012-04-05 00:50:46 -05:00
if ( ( uint32_t ) ( pBuffer - ChunkInfo - > Data ) = = ChunkInfo - > Size )
2012-04-04 00:24:25 -05:00
break ;
}
}
else
{
2012-04-05 00:50:46 -05:00
while ( bQuit = = 0 )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
eRowControlCode = * pBuffer + + ;
cBytesInThisRow = * pBuffer + + ;
cBytesRead = 2 ;
cPixelsSet = 0 ;
switch ( eRowControlCode )
2012-04-04 00:24:25 -05:00
{
case 4 :
2012-04-05 00:50:46 -05:00
for ( cBytesInThisRow = 0 ; cBytesInThisRow < cBytesInThisRow ; )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
eColumnControlCode = * pBuffer + + ;
cPixelCount = * pBuffer + + ;
cBytesRead + = 2 ;
2012-04-04 00:24:25 -05:00
2012-04-05 00:50:46 -05:00
switch ( eColumnControlCode )
2012-04-04 00:24:25 -05:00
{
case 3 :
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cPixelCount ; i + + )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , PMap - > Colors [ * pBuffer + + ] ) ;
cBytesRead + + ;
2012-04-04 00:24:25 -05:00
}
2012-04-05 00:50:46 -05:00
if ( ( pBuffer - ChunkInfo - > Data ) % 2 = = 1 )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
pBuffer + + ;
cBytesRead + + ;
2012-04-04 00:24:25 -05:00
}
break ;
case 2 :
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cPixelCount ; i + + )
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , PMap - > Colors [ * pBuffer + + ] ) ;
pBuffer + + ; /* Unused value */
cBytesRead + = 2 ;
2012-04-04 00:24:25 -05:00
}
break ;
case 1 :
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cPixelCount ; i + + )
{
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , Frame - > TransparentPixel ) ;
}
2012-04-04 00:24:25 -05:00
break ;
default :
2012-04-05 00:50:46 -05:00
/* Error reading column code */
2012-04-04 00:24:25 -05:00
return 0 ;
}
}
2012-04-05 00:50:46 -05:00
/* Set any extra (unread) texels in the current row to transparent */
while ( cPixelsSet < Frame - > Width ) { sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , Frame - > TransparentPixel ) ; }
iRow + + ;
2012-04-04 00:24:25 -05:00
break ;
case 9 :
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < cBytesInThisRow ; i + + ) /* cBytesInThisRow is used as the count of rows to fill with the transparent color in this case */
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
for ( cPixelsSet = 0 ; cPixelsSet < Frame - > Width ; cPixelsSet + + )
{
sprite_frame_set_texel ( Frame , cPixelsSet + + , iRow , Frame - > TransparentPixel ) ;
}
iRow + + ;
2012-04-04 00:24:25 -05:00
}
break ;
case 5 :
2012-04-05 00:50:46 -05:00
bQuit = 1 ;
printf ( " END " ) ;
fflush ( stdout ) ;
2012-04-04 00:24:25 -05:00
break ;
default :
2012-04-05 00:50:46 -05:00
/* Error reading row code */
2012-04-04 00:24:25 -05:00
return 0 ;
}
2012-04-05 00:50:46 -05:00
/*if ((uint32_t)(pBuffer - ChunkInfo->Data) == ChunkInfo->Size)
break ; */
2012-04-04 00:24:25 -05:00
}
}
2012-04-05 00:50:46 -05:00
for ( i = 0 ; i < Frame - > Height ; i + + ) /* cBytesInThisRow is used as the count of rows to fill with the transparent color in this case */
{
for ( j = 0 ; j < Frame - > Width ; j + + )
{
if ( sprite_are_colors_equal_rgb ( Frame - > Texels [ i * Frame - > Width + j ] , Frame - > TransparentPixel ) )
Frame - > Texels [ i * Frame - > Width + j ] . A = 0 ;
}
}
2012-04-04 00:24:25 -05:00
# ifdef IFF2HTML
outputPath = ( char * ) malloc ( sizeof ( char ) * 255 ) ;
folderName = ( char * ) malloc ( sizeof ( char ) * 255 ) ;
dummyName = ( char * ) malloc ( sizeof ( char ) * 255 ) ;
strcpy ( folderName , SourceFile - > FileName ) ;
* strchr ( folderName , ( int ) ' . ' ) = ' \0 ' ;
sprintf ( outputPath , " ./%s/%s (%d) Frame %d.png " , folderName , ChunkInfo - > Label , ChunkInfo - > ChunkID , l ) ;
/*printf(outputPath);
fflush ( stdout ) ; */
sprite_frame_export_as_png ( Frame , outputPath ) ; /* The images export faster and look better as targa. This tells me I'm doing something wrong in the PNG exporter code */
Sprite - > Frames [ l ] = Frame ;
Sprite - > Frames [ l ] - > filePath = outputPath ;
# endif
}
/* By adding this to the ChunkInfo at the success point, we ensure that no corrupt or partial sprite appears ingame */
ChunkInfo - > FormattedData = Sprite ;
return 1 ;
}
/* This function never returns zero because it is capable of producing logical output independent of the input's validity. */
2012-04-05 00:50:46 -05:00
int sprite_are_colors_equal_rgb ( IFFSpriteColor clr1 , IFFSpriteColor clr2 )
{
return clr1 . R = = clr2 . R & & clr1 . G = = clr2 . G & & clr1 . B = = clr2 . B ;
}
/* This function never returns zero because it is capable of producing logical output independent of the input's validity. */
int iff_parse_pmap ( IFFChunk * ChunkInfo , uint8_t * pBuffer )
2012-04-04 00:24:25 -05:00
{
uint32_t i ;
2012-04-05 00:50:46 -05:00
uint32_t indicator ;
2012-04-04 00:24:25 -05:00
IFFPMap * PMap = malloc ( sizeof ( IFFPMap ) ) ;
2012-04-05 00:50:46 -05:00
pBuffer = ChunkInfo - > Data ;
2012-04-04 00:24:25 -05:00
PMap - > Colors = ( IFFSpriteColor * ) malloc ( sizeof ( IFFSpriteColor ) * 256 ) ;
2012-04-05 00:50:46 -05:00
indicator = read_uint32le ( pBuffer ) ;
if ( indicator ! = 1 )
pBuffer + = ( indicator > > 24 ) - 8 ;
else
pBuffer + = 12 ;
2012-04-04 00:24:25 -05:00
/* In every single one of EA's PALT resources, there have been 256 colors. */
for ( i = 0 ; i < 256 ; i + + )
{
2012-04-05 00:50:46 -05:00
if ( ( uint32_t ) ( pBuffer - ChunkInfo - > Data ) < ChunkInfo - > Size + 3 ) /* Are there 3 more bytes left to read? */
2012-04-04 00:24:25 -05:00
{
2012-04-05 00:50:46 -05:00
PMap - > Colors [ i ] . R = * ( pBuffer + + ) ;
PMap - > Colors [ i ] . G = * ( pBuffer + + ) ;
PMap - > Colors [ i ] . B = * ( pBuffer + + ) ;
2012-04-04 00:24:25 -05:00
PMap - > Colors [ i ] . A = 255 ;
}
else
{
PMap - > Colors [ i ] . R = 128 ;
PMap - > Colors [ i ] . G = 128 ;
PMap - > Colors [ i ] . B = 128 ;
PMap - > Colors [ i ] . A = 255 ;
}
}
ChunkInfo - > FormattedData = PMap ;
return 1 ;
}
int sprite_frame_set_texel ( IFFSpriteFrame * frame , uint32_t column , uint32_t row , IFFSpriteColor color )
{
/*printf("Index: %d out of %d", frame->Width * row + column, frame->Width*frame->Height);*/
memcpy ( & frame - > Texels [ frame - > Width * row + column ] , & color , sizeof ( IFFSpriteColor ) ) ;
return 1 ;
}
2012-04-05 00:50:46 -05:00
int sprite_frame_set_texel_alpha ( IFFSpriteFrame * frame , uint32_t column , uint32_t row , IFFSpriteColor color , uint8_t alpha )
{
/*printf("Index: %d out of %d", frame->Width * row + column, frame->Width*frame->Height);*/
memcpy ( & frame - > Texels [ frame - > Width * row + column ] , & color , sizeof ( IFFSpriteColor ) ) ;
frame - > Texels [ frame - > Width * row + column ] . A = alpha ;
return 1 ;
}
2012-04-04 00:24:25 -05:00
int sprite_frame_export_as_targa ( IFFSpriteFrame * frame , const char * filename )
{
int i ;
FILE * targaFile = fopen ( filename , " w " ) ;
putc ( 0 , targaFile ) ;
putc ( 0 , targaFile ) ;
putc ( 2 , targaFile ) ;
putc ( 0 , targaFile ) ; putc ( 0 , targaFile ) ;
putc ( 0 , targaFile ) ; putc ( 0 , targaFile ) ;
putc ( 0 , targaFile ) ;
fwrite ( & frame - > XLocation , 2 , 1 , targaFile ) ;
fwrite ( & frame - > YLocation , 2 , 1 , targaFile ) ;
fwrite ( & frame - > Width , 2 , 1 , targaFile ) ;
fwrite ( & frame - > Height , 2 , 1 , targaFile ) ;
putc ( 32 , targaFile ) ;
putc ( 0 , targaFile ) ;
for ( i = 0 ; i < frame - > Width * frame - > Height ; i + + )
{
putc ( frame - > Texels [ i ] . B , targaFile ) ;
putc ( frame - > Texels [ i ] . G , targaFile ) ;
putc ( frame - > Texels [ i ] . R , targaFile ) ;
putc ( frame - > Texels [ i ] . A , targaFile ) ;
}
fclose ( targaFile ) ;
return 1 ;
}
int sprite_frame_export_as_png ( IFFSpriteFrame * frame , const char * filename )
{
png_structp png_ptr ;
png_infop info_ptr ;
png_bytepp row_pointers ;
int h ;
int w ;
FILE * pngFile = fopen ( filename , " wb " ) ;
png_ptr = png_create_write_struct ( PNG_LIBPNG_VER_STRING , NULL , NULL , NULL ) ;
info_ptr = png_create_info_struct ( png_ptr ) ;
setjmp ( png_jmpbuf ( png_ptr ) ) ;
png_init_io ( png_ptr , pngFile ) ;
setjmp ( png_jmpbuf ( png_ptr ) ) ;
png_set_IHDR ( png_ptr , info_ptr , frame - > Width , frame - > Height ,
8 , 6 , PNG_INTERLACE_NONE ,
PNG_COMPRESSION_TYPE_BASE , PNG_FILTER_TYPE_BASE ) ;
png_write_info ( png_ptr , info_ptr ) ;
setjmp ( png_jmpbuf ( png_ptr ) ) ;
row_pointers = ( png_bytepp ) malloc ( frame - > Height * sizeof ( png_bytep ) ) ;
for ( h = 0 ; h < frame - > Height ; h + + ) {
2012-04-05 00:50:46 -05:00
row_pointers [ h ] = ( png_bytep ) malloc ( frame - > Width * 4 ) ;
2012-04-04 00:24:25 -05:00
for ( w = 0 ; w < frame - > Width ; w + + ) {
2012-04-05 00:50:46 -05:00
row_pointers [ h ] [ w * 4 ] = frame - > Texels [ frame - > Width * h + w ] . R ;
row_pointers [ h ] [ w * 4 + 1 ] = frame - > Texels [ frame - > Width * h + w ] . G ;
row_pointers [ h ] [ w * 4 + 2 ] = frame - > Texels [ frame - > Width * h + w ] . B ;
row_pointers [ h ] [ w * 4 + 3 ] = frame - > Texels [ frame - > Width * h + w ] . A ;
2012-04-04 00:24:25 -05:00
}
}
png_write_image ( png_ptr , row_pointers ) ;
setjmp ( png_jmpbuf ( png_ptr ) ) ;
png_write_end ( png_ptr , NULL ) ;
for ( h = 0 ; h < frame - > Height ; h + + ) {
free ( ( row_pointers ) [ h ] ) ;
}
free ( row_pointers ) ;
fclose ( pngFile ) ;
return 1 ;
}