Show rle.c syntax highlighted
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* RLE sprite generation routines.
*
* By Shawn Hargreaves.
*
* See readme.txt for copyright information.
*/
#include <string.h>
#include "allegro.h"
#include "allegro/internal/aintern.h"
/* al_create_rle_sprite:
* Creates a run length encoded sprite based on the specified bitmap.
* The returned sprite is likely to be a lot smaller than the original
* bitmap, and can be drawn to the al_screen with al_draw_rle_sprite().
*
* The compression is done individually for each al_draw_line of the image.
* Format is a series of command bytes, 1-127 marks a run of that many
* solid pixels, negative numbers mark a gap of -n pixels, and 0 marks
* the end of a al_draw_line (since zero can't occur anywhere else in the data,
* this can be used to find the start of a specified al_draw_line when clipping).
* For truecolor RLE sprites, the data and command bytes are both in the
* same format (16 or 32 bits, 24 bpp data is padded to 32 bit aligment),
* and the mask color (bright pink) is used as the EOL marker.
*/
AL_RLE_SPRITE *al_create_rle_sprite(AL_BITMAP *bitmap)
{
int depth = al_bitmap_color_depth(bitmap);
AL_RLE_SPRITE *s;
int x, y;
int run;
int pix;
int c;
#define WRITE_TO_SPRITE8(x) { \
_grow_scratch_mem(c+1); \
p = (signed char *)_scratch_mem; \
p[c] = x; \
c++; \
}
#define WRITE_TO_SPRITE16(x) { \
_grow_scratch_mem((c+1)*sizeof(short)); \
p = (signed short *)_scratch_mem; \
p[c] = x; \
c++; \
}
#define WRITE_TO_SPRITE32(x) { \
_grow_scratch_mem((c+1)*sizeof(long)); \
p = (signed long *)_scratch_mem; \
p[c] = x; \
c++; \
}
/* helper for building an RLE run */
#define DO_RLE(bits) \
{ \
for (y=0; y<bitmap->h; y++) { \
run = -1; \
for (x=0; x<bitmap->w; x++) { \
pix = al_get_pixel(bitmap, x, y) & 0xFFFFFF; \
if (pix != bitmap->vtable->mask_color) { \
if ((run >= 0) && (p[run] > 0) && (p[run] < 127)) \
p[run]++; \
else { \
run = c; \
WRITE_TO_SPRITE##bits(1); \
} \
WRITE_TO_SPRITE##bits(al_get_pixel(bitmap, x, y)); \
} \
else { \
if ((run >= 0) && (p[run] < 0) && (p[run] > -128)) \
p[run]--; \
else { \
run = c; \
WRITE_TO_SPRITE##bits(-1); \
} \
} \
} \
WRITE_TO_SPRITE##bits(bitmap->vtable->mask_color); \
} \
}
c = 0;
switch (depth) {
#ifdef ALLEGRO_COLOR8
case 8:
{
signed char *p = (signed char *)_scratch_mem;
DO_RLE(8);
}
break;
#endif
#ifdef ALLEGRO_COLOR16
case 15:
case 16:
{
signed short *p = (signed short *)_scratch_mem;
DO_RLE(16);
c *= sizeof(short);
}
break;
#endif
#if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32)
case 24:
case 32:
{
signed long *p = (signed long *)_scratch_mem;
DO_RLE(32);
c *= sizeof(long);
}
break;
#endif
}
s = malloc(sizeof(AL_RLE_SPRITE) + c);
if (s) {
s->w = bitmap->w;
s->h = bitmap->h;
s->color_depth = depth;
s->size = c;
memcpy(s->dat, _scratch_mem, c);
}
return s;
}
/* al_destroy_rle_sprite:
* Destroys an RLE sprite structure returned by al_create_rle_sprite().
*/
void al_destroy_rle_sprite(AL_RLE_SPRITE *sprite)
{
if (sprite)
free(sprite);
}
See more files for this project here