Tools/nativelib - Working on threading
[tpg/acess2.git] / Tools / img2sif.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
4 #include <SDL/SDL.h>
5 #include <SDL/SDL_image.h>
6
7 // === PROTOTYPES ===
8  int    main(int argc, char *argv[]);
9 size_t  RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength);
10 uint32_t        GetARGB(SDL_Surface *srf, int x, int y);
11
12 // === CODE ===
13 int main(int argc, char *argv[])
14 {
15         FILE    *fp;
16         SDL_Surface     *img;
17         uint16_t        word;
18         uint32_t        val;
19          int    y, x, i;
20          int    rle32length, rle4x8length;
21          int    bufLen;
22         uint32_t        *buffer, *buffer2;
23         
24         img = IMG_Load(argv[1]);
25         if( !img )      return -1;
26         
27         buffer = malloc( img->w * img->h * 4 );
28         
29         i = 0;
30         for( y = 0; y < img->h; y++ )
31         {
32                 for( x = 0; x < img->w; x ++ )
33                 {
34                         val = GetARGB(img, x, y);
35                         buffer[i++] = val;
36                 }
37         }
38         
39         SDL_FreeSurface(img);
40         
41         // Try encoding using a single RLE stream
42         rle32length = RLE1_7(NULL, buffer, img->w * img->h, 4, 4, 3);
43         
44         // Try encoding using separate RLE streams for each channel
45         rle4x8length  = RLE1_7(NULL, buffer, img->w * img->h, 1, 4, 2);
46         rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+1, img->w * img->h, 1, 4, 2);
47         rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+2, img->w * img->h, 1, 4, 2);
48         rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+3, img->w * img->h, 1, 4, 2);
49         
50         printf("raw length = %i\n", img->w * img->h * 4);
51         printf("rle32length = %i\n", rle32length);
52         printf("rle4x8length = %i\n", rle4x8length);
53         
54         if( rle32length < rle4x8length ) {
55                 comp = 1;       // 32-bit RLE
56                 buffer2 = malloc( rle32length );
57                 bufLen = RLE1_7(buffer2, buffer, img->w * img->h, 4, 4, 2);
58         }
59         else {
60                 comp = 3;       // 4x8 bit RLE
61                 buffer2 = malloc( rle4x8length );
62                 rle4x8length  = RLE1_7(buffer2, buffer, img->w * img->h, 1, 4, 3);
63                 rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+1, img->w * img->h, 1, 4, 3);
64                 rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+2, img->w * img->h, 1, 4, 3);
65                 rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+3, img->w * img->h, 1, 4, 3);
66                 bufLen = rle4x8length;
67         }
68         
69         // Open and write
70         fp = fopen(argv[2], "w");
71         if( !fp )       return -1;
72         
73         word = 0x51F0;  fwrite(&word, 2, 1, fp);
74         word = comp&7;  fwrite(&word, 2, 1, fp);
75         word = img->w;  fwrite(&word, 2, 1, fp);
76         word = img->h;  fwrite(&word, 2, 1, fp);
77         
78         fwrite(buffer2, bufLen, 1, fp);
79         
80         fclose(fp);
81         
82         return 0;
83 }
84
85 #define USE_VERBATIM    1
86
87 /**
88  * \brief Run Length Encode a data stream
89  * \param Dest  Destination buffer (can be NULL)
90  * \param Src   Source data
91  * \param Size  Size of source data
92  * \param BlockSize     Size of a data element (in bytes)       
93  * \param BlockStep     Separation of the beginning of each data element (must be > 0 and should be >= BlockSize)
94  * \param MinRunLength  Minimum run length for RLE to be used (must be be >= 1)
95  * 
96  * This function produces a RLE stream encoded with a 7-bit size and a
97  * verbatim flag (allowing strings of non-rle data to be included in the
98  * data for efficiency) of the data blocks from \a Src. Each block is
99  * \a BlockSize bytes in size.
100  * 
101  * \a BlockStep allows this function to encode data that is interlaced with
102  * other data that you may not want to RLE together (for example, different
103  * colour channels in an image).
104  */
105 size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength)
106 {
107         uint8_t *src = Src;
108         uint8_t *dest = Dest;
109          int    ret = 0;
110          int    i, j, k;
111          int    nVerb = 0, nRLE = 0;    // Debugging
112         
113         //printf("RLE1_7: (Dest=%p, Src=%p, Size=%lu, BlockSize=%i, BlockStep=%i, MinRunLength=%i)\n",
114         //      Dest, Src, Size, BlockSize, BlockStep, MinRunLength);
115         
116         // Prevent errors
117         if( Size < BlockSize )  return -1;
118         if( !Src )      return -1;
119         if( BlockSize <= 0 || BlockStep <= 0 )  return -1;
120         if( MinRunLength < 1 )  return -1;
121         
122         // Scan through the data stream
123         for( i = 0; i < Size; i ++ )
124         {
125                 //printf("i = %i, ", i);
126                 // Check forward for and get the "run length"
127                 for( j = i + 1; j < i + 127 && j < Size; j ++ )
128                 {
129                         // Check for equality
130                         for( k = 0; k < BlockSize; k ++ ) {
131                                 if( src[j*BlockStep+k] != src[i*BlockStep+k] )  break;
132                         }
133                         // If not, break
134                         if( k < BlockSize )     break;
135                 }
136                 
137                 #if USE_VERBATIM
138                 // Check for a verbatim range (runlength of `MinRunLength` or less)
139                 if( j - i <= MinRunLength ) {
140                          int    nSame = 0;
141                         // Get the length of the verbatim run
142                         for( j = i + 1; j < i + 127 && j < Size; j ++ )
143                         {
144                                 // Check for equality
145                                 for( k = 0; k < BlockSize; k ++ ) {
146                                         if( src[j*BlockStep+k] != src[i*BlockStep+k] )  break;
147                                 }
148                                 if( k == BlockSize ) {
149                                         nSame ++;
150                                         if( nSame > MinRunLength )
151                                                 break;
152                                 }
153                                 else {
154                                         nSame = 0;
155                                 }
156                         }
157                         
158                         // Save data
159                         if( dest ) {
160                                 dest[ret++] = (j - i) | 0x80;   // Length (with high bit set)
161                                 // Data
162                                 for( k = 0; k < (j - i)*BlockSize; k ++ )
163                                         dest[ret++] = src[i*BlockStep+k];
164                         }
165                         else {
166                                 ret += 1 + BlockSize*(j - i);
167                         }
168                         
169                         nVerb ++;
170                 }
171                 // RLE Range
172                 else {
173                 #endif  // USE_VERBATIM
174                         // length = j - i (maxes out at 127)
175                         if( dest ) {
176                                 dest[ret++] = j - i;    // Length (with high bit unset)
177                                 for( k = 0; k < BlockSize; k ++ ) {
178                                         dest[ret++] = src[i*BlockStep+k];
179                                 }
180                         }
181                         else {
182                                 ret += 1 + BlockSize;
183                         }
184                         
185                         nRLE ++;
186                 #if USE_VERBATIM
187                 }
188                 #endif
189                 
190                 i = j;
191         }
192         
193         //printf("nVerb = %i, nRLE = %i\n", nVerb, nRLE);
194         return ret;
195 }
196
197 uint32_t GetARGB(SDL_Surface *srf, int x, int y)
198 {
199         uint8_t r, g, b, a;
200         SDL_GetRGBA(
201                 *(uint32_t*)( srf->pixels + srf->format->BytesPerPixel*x + y * srf->pitch ),
202                 srf->format, &r, &g, &b, &a
203                 );
204         return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b);
205 }

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