5 #include <SDL/SDL_image.h>
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);
13 int main(int argc, char *argv[])
16 size_t rle32length, rle4x8length;
21 uint32_t *buffer, *buffer2;
24 fprintf(stderr, "Usage: %s <input> <output>\n", argv[0]);
30 SDL_Surface *img = IMG_Load(argv[1]);
36 buffer = malloc( pixel_count * 4 );
38 for( int y = 0, i = 0; y < img->h; y++ )
40 for( int x = 0; x < img->w; x ++ )
42 buffer[i++] = GetARGB(img, x, y);
48 // Try encoding using a single RLE stream
49 rle32length = RLE1_7(NULL, buffer, pixel_count, 4, 4, 3);
51 // Try encoding using separate RLE streams for each channel
52 rle4x8length = RLE1_7(NULL, buffer, pixel_count, 1, 4, 2);
53 rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+1, pixel_count, 1, 4, 2);
54 rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+2, pixel_count, 1, 4, 2);
55 rle4x8length += RLE1_7(NULL, ((uint8_t*)buffer)+3, pixel_count, 1, 4, 2);
57 // printf("raw length = %i\n", pixel_count * 4);
58 // printf("rle32length = %u\n", (unsigned int)rle32length);
59 // printf("rle4x8length = %u\n", (unsigned int)rle4x8length);
61 if( rle32length < rle4x8length ) {
62 comp = 1; // 32-bit RLE
63 buffer2 = malloc( rle32length );
64 bufLen = RLE1_7(buffer2, buffer, pixel_count, 4, 4, 2);
67 comp = 3; // 4x8 bit RLE
68 buffer2 = malloc( rle4x8length );
69 rle4x8length = RLE1_7(buffer2, buffer, pixel_count, 1, 4, 3);
70 rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+1, pixel_count, 1, 4, 3);
71 rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+2, pixel_count, 1, 4, 3);
72 rle4x8length += RLE1_7(buffer2+rle4x8length, ((uint8_t*)buffer)+3, pixel_count, 1, 4, 3);
73 bufLen = rle4x8length;
78 fp = fopen(argv[2], "w");
82 word = 0x51F0; fwrite(&word, 2, 1, fp);
83 word = comp&7; fwrite(&word, 2, 1, fp);
84 word = w; fwrite(&word, 2, 1, fp);
85 word = h; fwrite(&word, 2, 1, fp);
87 fwrite(buffer2, bufLen, 1, fp);
94 #define USE_VERBATIM 1
97 * \brief Run Length Encode a data stream
98 * \param Dest Destination buffer (can be NULL)
99 * \param Src Source data
100 * \param Size Size of source data
101 * \param BlockSize Size of a data element (in bytes)
102 * \param BlockStep Separation of the beginning of each data element (must be > 0 and should be >= BlockSize)
103 * \param MinRunLength Minimum run length for RLE to be used (must be be >= 1)
105 * This function produces a RLE stream encoded with a 7-bit size and a
106 * verbatim flag (allowing strings of non-rle data to be included in the
107 * data for efficiency) of the data blocks from \a Src. Each block is
108 * \a BlockSize bytes in size.
110 * \a BlockStep allows this function to encode data that is interlaced with
111 * other data that you may not want to RLE together (for example, different
112 * colour channels in an image).
114 size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength)
117 uint8_t *dest = Dest;
119 int nVerb = 0, nRLE = 0; // Debugging
121 //printf("RLE1_7: (Dest=%p, Src=%p, Size=%lu, BlockSize=%i, BlockStep=%i, MinRunLength=%i)\n",
122 // Dest, Src, Size, BlockSize, BlockStep, MinRunLength);
125 if( Size < BlockSize ) return -1;
126 if( !Src ) return -1;
127 if( BlockSize <= 0 || BlockStep <= 0 ) return -1;
128 if( MinRunLength < 1 ) return -1;
130 // Scan through the data stream
131 for( int i = 0; i < Size; i ++ )
133 //printf("i = %i, ", i);
135 // Check forward for and get the "run length"
136 for( runlen = 1; runlen < 127 && i+runlen < Size; runlen ++ )
138 // Check for equality
139 if( memcmp(&src[i*BlockStep], &src[(i+runlen)*BlockStep], BlockSize) != 0 )
144 // Check for a verbatim range (runlength of `MinRunLength` or less)
145 if( runlen <= MinRunLength )
148 // Get the length of the verbatim run
149 for( runlen = 1; runlen < 127 && i+runlen < Size; runlen ++ )
151 // Check for equality
152 if( memcmp(&src[i*BlockStep], &src[(i+runlen)*BlockStep], BlockSize) != 0 )
159 if( nSame > MinRunLength ) {
169 dest[ret++] = runlen | 0x80; // Length (with high bit set)
171 for( int k = 0; k < runlen; k ++ )
173 memcpy( &dest[ret], &src[(i+k)*BlockStep], BlockSize );
178 ret += 1 + runlen*BlockSize;
185 #endif // USE_VERBATIM
187 dest[ret++] = runlen; // Length (with high bit unset)
188 memcpy(&dest[ret], &src[i*BlockStep], BlockSize);
192 ret += 1 + BlockSize;
203 //printf("nVerb = %i, nRLE = %i\n", nVerb, nRLE);
207 uint32_t GetARGB(SDL_Surface *srf, int x, int y)
211 *(uint32_t*)( srf->pixels + srf->format->BytesPerPixel*x + y * srf->pitch ),
212 srf->format, &r, &g, &b, &a
214 return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b);