From: John Hodge (sonata) Date: Fri, 25 Jan 2013 14:53:26 +0000 (+0800) Subject: Tools - Added SDL_Image->.sif converter X-Git-Tag: rel0.15~597^2~9^2~4 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=d6fa61f5cf085eb48a78c50f7c10735b39d57e3e;p=tpg%2Facess2.git Tools - Added SDL_Image->.sif converter --- diff --git a/Tools/img2sif.c b/Tools/img2sif.c new file mode 100644 index 00000000..26ab4eb6 --- /dev/null +++ b/Tools/img2sif.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include + +// === PROTOTYPES === + int main(int argc, char *argv[]); +size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength); +uint32_t GetARGB(SDL_Surface *srf, int x, int y); + +// === CODE === +int main(int argc, char *argv[]) +{ + FILE *fp; + SDL_Surface *img; + uint16_t word; + uint32_t val; + int y, x, i; + int rle32length, rle4x8length; + int bufLen; + uint32_t *buffer, *buffer2; + + img = IMG_Load(argv[1]); + if( !img ) return -1; + + buffer = malloc( img->w * img->h * 4 ); + + i = 0; + for( y = 0; y < img->h; y++ ) + { + for( x = 0; x < img->w; x ++ ) + { + val = GetARGB(img, x, y); + buffer[i++] = val; + } + } + + SDL_FreeSurface(img); + + // Try encoding using a single RLE stream + rle32length = RLE1_7(NULL, buffer, img->w * img->h, 4, 4, 3); + + // Try encoding using separate RLE streams for each channel + rle4x8length = RLE1_7(NULL, buffer, img->w * img->h, 1, 4, 2); + rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+1, img->w * img->h, 1, 4, 2); + rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+2, img->w * img->h, 1, 4, 2); + rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+3, img->w * img->h, 1, 4, 2); + + printf("raw length = %i\n", img->w * img->h * 4); + printf("rle32length = %i\n", rle32length); + printf("rle4x8length = %i\n", rle4x8length); + + if( rle32length < rle4x8length ) { + comp = 1; // 32-bit RLE + buffer2 = malloc( rle32length ); + bufLen = RLE1_7(buffer2, buffer, img->w * img->h, 4, 4, 2); + } + else { + comp = 3; // 4x8 bit RLE + buffer2 = malloc( rle4x8length ); + rle4x8length = RLE1_7(buffer2, buffer, img->w * img->h, 1, 4, 3); + rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+1, img->w * img->h, 1, 4, 3); + rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+2, img->w * img->h, 1, 4, 3); + rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+3, img->w * img->h, 1, 4, 3); + bufLen = rle4x8length; + } + + // Open and write + fp = fopen(argv[2], "w"); + if( !fp ) return -1; + + word = 0x51F0; fwrite(&word, 2, 1, fp); + word = comp&7; fwrite(&word, 2, 1, fp); + word = img->w; fwrite(&word, 2, 1, fp); + word = img->h; fwrite(&word, 2, 1, fp); + + fwrite(buffer2, bufLen, 1, fp); + + fclose(fp); + + return 0; +} + +#define USE_VERBATIM 1 + +/** + * \brief Run Length Encode a data stream + * \param Dest Destination buffer (can be NULL) + * \param Src Source data + * \param Size Size of source data + * \param BlockSize Size of a data element (in bytes) + * \param BlockStep Separation of the beginning of each data element (must be > 0 and should be >= BlockSize) + * \param MinRunLength Minimum run length for RLE to be used (must be be >= 1) + * + * This function produces a RLE stream encoded with a 7-bit size and a + * verbatim flag (allowing strings of non-rle data to be included in the + * data for efficiency) of the data blocks from \a Src. Each block is + * \a BlockSize bytes in size. + * + * \a BlockStep allows this function to encode data that is interlaced with + * other data that you may not want to RLE together (for example, different + * colour channels in an image). + */ +size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength) +{ + uint8_t *src = Src; + uint8_t *dest = Dest; + int ret = 0; + int i, j, k; + int nVerb = 0, nRLE = 0; // Debugging + + //printf("RLE1_7: (Dest=%p, Src=%p, Size=%lu, BlockSize=%i, BlockStep=%i, MinRunLength=%i)\n", + // Dest, Src, Size, BlockSize, BlockStep, MinRunLength); + + // Prevent errors + if( Size < BlockSize ) return -1; + if( !Src ) return -1; + if( BlockSize <= 0 || BlockStep <= 0 ) return -1; + if( MinRunLength < 1 ) return -1; + + // Scan through the data stream + for( i = 0; i < Size; i ++ ) + { + //printf("i = %i, ", i); + // Check forward for and get the "run length" + for( j = i + 1; j < i + 127 && j < Size; j ++ ) + { + // Check for equality + for( k = 0; k < BlockSize; k ++ ) { + if( src[j*BlockStep+k] != src[i*BlockStep+k] ) break; + } + // If not, break + if( k < BlockSize ) break; + } + + #if USE_VERBATIM + // Check for a verbatim range (runlength of `MinRunLength` or less) + if( j - i <= MinRunLength ) { + int nSame = 0; + // Get the length of the verbatim run + for( j = i + 1; j < i + 127 && j < Size; j ++ ) + { + // Check for equality + for( k = 0; k < BlockSize; k ++ ) { + if( src[j*BlockStep+k] != src[i*BlockStep+k] ) break; + } + if( k == BlockSize ) { + nSame ++; + if( nSame > MinRunLength ) + break; + } + else { + nSame = 0; + } + } + + // Save data + if( dest ) { + dest[ret++] = (j - i) | 0x80; // Length (with high bit set) + // Data + for( k = 0; k < (j - i)*BlockSize; k ++ ) + dest[ret++] = src[i*BlockStep+k]; + } + else { + ret += 1 + BlockSize*(j - i); + } + + nVerb ++; + } + // RLE Range + else { + #endif // USE_VERBATIM + // length = j - i (maxes out at 127) + if( dest ) { + dest[ret++] = j - i; // Length (with high bit unset) + for( k = 0; k < BlockSize; k ++ ) { + dest[ret++] = src[i*BlockStep+k]; + } + } + else { + ret += 1 + BlockSize; + } + + nRLE ++; + #if USE_VERBATIM + } + #endif + + i = j; + } + + //printf("nVerb = %i, nRLE = %i\n", nVerb, nRLE); + return ret; +} + +uint32_t GetARGB(SDL_Surface *srf, int x, int y) +{ + uint8_t r, g, b, a; + SDL_GetRGBA( + *(uint32_t*)( srf->pixels + srf->format->BytesPerPixel*x + y * srf->pitch ), + srf->format, &r, &g, &b, &a + ); + return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b); +}