Kernel/debug - Clean up Debug() method, bind to #define config
[tpg/acess2.git] / Tools / img2sif.c
index 26ab4eb..d04c9aa 100644 (file)
 #include <SDL/SDL.h>
 #include <SDL/SDL_image.h>
 
+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 <infile> <outfile>\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);

UCC git Repository :: git.ucc.asn.au