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[])
20 int rle32length, rle4x8length;
22 uint32_t *buffer, *buffer2;
24 img = IMG_Load(argv[1]);
27 buffer = malloc( img->w * img->h * 4 );
30 for( y = 0; y < img->h; y++ )
32 for( x = 0; x < img->w; x ++ )
34 val = GetARGB(img, x, y);
41 // Try encoding using a single RLE stream
42 rle32length = RLE1_7(NULL, buffer, img->w * img->h, 4, 4, 3);
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);
50 printf("raw length = %i\n", img->w * img->h * 4);
51 printf("rle32length = %i\n", rle32length);
52 printf("rle4x8length = %i\n", rle4x8length);
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);
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;
70 fp = fopen(argv[2], "w");
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);
78 fwrite(buffer2, bufLen, 1, fp);
85 #define USE_VERBATIM 1
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)
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.
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).
105 size_t RLE1_7(void *Dest, void *Src, size_t Size, int BlockSize, int BlockStep, int MinRunLength)
108 uint8_t *dest = Dest;
111 int nVerb = 0, nRLE = 0; // Debugging
113 //printf("RLE1_7: (Dest=%p, Src=%p, Size=%lu, BlockSize=%i, BlockStep=%i, MinRunLength=%i)\n",
114 // Dest, Src, Size, BlockSize, BlockStep, MinRunLength);
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;
122 // Scan through the data stream
123 for( i = 0; i < Size; i ++ )
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 ++ )
129 // Check for equality
130 for( k = 0; k < BlockSize; k ++ ) {
131 if( src[j*BlockStep+k] != src[i*BlockStep+k] ) break;
134 if( k < BlockSize ) break;
138 // Check for a verbatim range (runlength of `MinRunLength` or less)
139 if( j - i <= MinRunLength ) {
141 // Get the length of the verbatim run
142 for( j = i + 1; j < i + 127 && j < Size; j ++ )
144 // Check for equality
145 for( k = 0; k < BlockSize; k ++ ) {
146 if( src[j*BlockStep+k] != src[i*BlockStep+k] ) break;
148 if( k == BlockSize ) {
150 if( nSame > MinRunLength )
160 dest[ret++] = (j - i) | 0x80; // Length (with high bit set)
162 for( k = 0; k < (j - i)*BlockSize; k ++ )
163 dest[ret++] = src[i*BlockStep+k];
166 ret += 1 + BlockSize*(j - i);
173 #endif // USE_VERBATIM
174 // length = j - i (maxes out at 127)
176 dest[ret++] = j - i; // Length (with high bit unset)
177 for( k = 0; k < BlockSize; k ++ ) {
178 dest[ret++] = src[i*BlockStep+k];
182 ret += 1 + BlockSize;
193 //printf("nVerb = %i, nRLE = %i\n", nVerb, nRLE);
197 uint32_t GetARGB(SDL_Surface *srf, int x, int y)
201 *(uint32_t*)( srf->pixels + srf->format->BytesPerPixel*x + y * srf->pitch ),
202 srf->format, &r, &g, &b, &a
204 return ((uint32_t)a << 24) | ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b);