X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Tools%2Fimg2sif.c;h=d04c9aa127a3d2ad8df7491b97bad5a87fc937ca;hb=86b0974b33759726b99f8940900a88e395247460;hp=26ab4eb6e2a47c4f5a2ddeec3c6644d749b5f8d5;hpb=7ba570fe3cc5418f42decf5b72ac2295cce9e60f;p=tpg%2Facess2.git diff --git a/Tools/img2sif.c b/Tools/img2sif.c index 26ab4eb6..d04c9aa1 100644 --- a/Tools/img2sif.c +++ b/Tools/img2sif.c @@ -4,84 +4,163 @@ #include #include +enum eCompressionModes { + COMP_NONE, + COMP_RLE1x32, + COMP_ZLIB, + COMP_RLE4x8, + COMP_AUTO = 8 +}; + // === PROTOTYPES === int main(int argc, char *argv[]); -size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength); +size_t CompressRLE1x32(void *Dest, const void *Src, size_t Size); +size_t CompressRLE4x8(void *Dest, const void *Src, size_t Size); +size_t RLE1_7(void *Dest, const 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; + enum eCompressionModes comp = COMP_AUTO; + int w, h; + int pixel_count; uint32_t *buffer, *buffer2; - img = IMG_Load(argv[1]); - if( !img ) return -1; - - buffer = malloc( img->w * img->h * 4 ); + const char *input_file = NULL, *output_file = NULL; + + for( int i = 1; i < argc; i ++ ) + { + if( argv[i][0] != '-' ) { + if( !input_file ) + input_file = argv[i]; + else if( !output_file ) + output_file = argv[i]; + else { + // Error + } + } + else if( argv[i][1] != '-' ) { + // Single char args + } + else { + // Long args + if( strcmp(argv[i], "--uncompressed") == 0 ) { + // Force compression mode to '0' + comp = COMP_NONE; + } + else if( strcmp(argv[i], "--rle4x8") == 0 ) { + comp = COMP_RLE4x8; + } + else if( strcmp(argv[i], "--rle1x32") == 0 ) { + comp = COMP_RLE1x32; + } + else { + // Error + } + } + } + if( !input_file || !output_file ) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } - i = 0; - for( y = 0; y < img->h; y++ ) + // Read image { - for( x = 0; x < img->w; x ++ ) + SDL_Surface *img = IMG_Load(input_file); + if( !img ) return -1; + + w = img->w; + h = img->h; + pixel_count = w * h; + buffer = malloc( pixel_count * 4 ); + + for( int y = 0, i = 0; y < img->h; y++ ) { - val = GetARGB(img, x, y); - buffer[i++] = val; + for( int x = 0; x < img->w; x ++ ) + { + buffer[i++] = GetARGB(img, x, y); + } } + SDL_FreeSurface(img); } - 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); + if( comp == COMP_AUTO ) + { + // Try encoding using a single RLE stream + size_t rle32length = CompressRLE1x32(NULL, buffer, pixel_count); + // Try encoding using separate RLE streams for each channel + size_t rle4x8length = CompressRLE4x8(NULL, buffer, pixel_count); + + // printf("raw length = %i\n", pixel_count * 4); + // printf("rle32length = %u\n", (unsigned int)rle32length); + // printf("rle4x8length = %u\n", (unsigned int)rle4x8length); + + if( rle32length <= rle4x8length ) { + comp = COMP_RLE1x32; // 32-bit RLE + } + else { + comp = COMP_RLE4x8; // 4x8 bit RLE + } } - 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; + + switch(comp) + { + case COMP_NONE: + bufLen = pixel_count*4; + buffer2 = buffer; + buffer = NULL; + break; + case COMP_RLE1x32: + bufLen = CompressRLE1x32(NULL, buffer, pixel_count); + buffer2 = malloc(bufLen); + bufLen = CompressRLE1x32(buffer2, buffer, pixel_count); + break; + case COMP_RLE4x8: + bufLen = CompressRLE4x8(NULL, buffer, pixel_count); + buffer2 = malloc(bufLen); + bufLen = CompressRLE4x8(buffer2, buffer, pixel_count); + break; + default: + fprintf(stderr, "Unknown compresion %i\n", comp); + return 2; } + + free(buffer); // Open and write - fp = fopen(argv[2], "w"); + fp = fopen(output_file, "w"); if( !fp ) return -1; + uint16_t word; 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); + word = w; fwrite(&word, 2, 1, fp); + word = h; fwrite(&word, 2, 1, fp); fwrite(buffer2, bufLen, 1, fp); - + free(buffer2); fclose(fp); return 0; } +size_t CompressRLE1x32(void *Dest, const void *Src, size_t Size) +{ + return RLE1_7(Dest, Src, Size, 4, 4, 2); +} +size_t CompressRLE4x8(void *Dest, const void *Src, size_t Size) +{ + size_t ret = 0; + ret += RLE1_7(Dest ? Dest + ret : NULL, Src+0, Size, 1, 4, 3); + ret += RLE1_7(Dest ? Dest + ret : NULL, Src+1, Size, 1, 4, 3); + ret += RLE1_7(Dest ? Dest + ret : NULL, Src+2, Size, 1, 4, 3); + ret += RLE1_7(Dest ? Dest + ret : NULL, Src+3, Size, 1, 4, 3); + return ret; +} + #define USE_VERBATIM 1 /** @@ -102,12 +181,11 @@ int main(int argc, char *argv[]) * 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) +size_t RLE1_7(void *Dest, const void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength) { - uint8_t *src = Src; + const 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", @@ -120,50 +198,54 @@ size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, if( MinRunLength < 1 ) return -1; // Scan through the data stream - for( i = 0; i < Size; i ++ ) + for( int i = 0; i < Size; i ++ ) { //printf("i = %i, ", i); + int runlen; // Check forward for and get the "run length" - for( j = i + 1; j < i + 127 && j < Size; j ++ ) + for( runlen = 1; runlen < 127 && i+runlen < Size; runlen ++ ) { // 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( memcmp(&src[i*BlockStep], &src[(i+runlen)*BlockStep], BlockSize) != 0 ) + break; } #if USE_VERBATIM // Check for a verbatim range (runlength of `MinRunLength` or less) - if( j - i <= MinRunLength ) { + if( runlen <= MinRunLength ) + { int nSame = 0; // Get the length of the verbatim run - for( j = i + 1; j < i + 127 && j < Size; j ++ ) + for( runlen = 1; runlen < 127 && i+runlen < Size; runlen ++ ) { // Check for equality - for( k = 0; k < BlockSize; k ++ ) { - if( src[j*BlockStep+k] != src[i*BlockStep+k] ) break; + if( memcmp(&src[i*BlockStep], &src[(i+runlen)*BlockStep], BlockSize) != 0 ) + { + nSame = 0; } - if( k == BlockSize ) { + else + { nSame ++; - if( nSame > MinRunLength ) + if( nSame > MinRunLength ) { + runlen -= nSame-1; break; - } - else { - nSame = 0; + } } } // Save data - if( dest ) { - dest[ret++] = (j - i) | 0x80; // Length (with high bit set) + if( dest ) + { + dest[ret++] = runlen | 0x80; // Length (with high bit set) // Data - for( k = 0; k < (j - i)*BlockSize; k ++ ) - dest[ret++] = src[i*BlockStep+k]; + for( int k = 0; k < runlen; k ++ ) + { + memcpy( &dest[ret], &src[(i+k)*BlockStep], BlockSize ); + ret += BlockSize; + } } else { - ret += 1 + BlockSize*(j - i); + ret += 1 + runlen*BlockSize; } nVerb ++; @@ -171,12 +253,10 @@ size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, // 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]; - } + dest[ret++] = runlen; // Length (with high bit unset) + memcpy(&dest[ret], &src[i*BlockStep], BlockSize); + ret += BlockSize; } else { ret += 1 + BlockSize; @@ -187,7 +267,7 @@ size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, } #endif - i = j; + i += runlen-1; } //printf("nVerb = %i, nRLE = %i\n", nVerb, nRLE);