1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * RLE sprite generation routines.
12 *
13 * By Shawn Hargreaves.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include <string.h>
20
21 #include "allegro.h"
22 #include "allegro/internal/aintern.h"
23
24
25
26 /* get_rle_sprite:
27 * Creates a run length encoded sprite based on the specified bitmap.
28 * The returned sprite is likely to be a lot smaller than the original
29 * bitmap, and can be drawn to the screen with draw_rle_sprite().
30 *
31 * The compression is done individually for each line of the image.
32 * Format is a series of command bytes, 1-127 marks a run of that many
33 * solid pixels, negative numbers mark a gap of -n pixels, and 0 marks
34 * the end of a line (since zero can't occur anywhere else in the data,
35 * this can be used to find the start of a specified line when clipping).
36 * For truecolor RLE sprites, the data and command bytes are both in the
37 * same format (16 or 32 bits, 24 bpp data is padded to 32 bit aligment),
38 * and the mask color (bright pink) is used as the EOL marker.
39 */
get_rle_sprite(BITMAP * bitmap)40 RLE_SPRITE *get_rle_sprite(BITMAP *bitmap)
41 {
42 int depth;
43 RLE_SPRITE *s;
44 int x, y;
45 int run;
46 int pix;
47 int c;
48 ASSERT(bitmap);
49
50 depth = bitmap_color_depth(bitmap);
51
52 #define WRITE_TO_SPRITE8(x) { \
53 _grow_scratch_mem(c+1); \
54 p = (signed char *)_scratch_mem; \
55 p[c] = x; \
56 c++; \
57 }
58
59 #define WRITE_TO_SPRITE16(x) { \
60 _grow_scratch_mem((c+1)*sizeof(int16_t)); \
61 p = (int16_t *)_scratch_mem; \
62 p[c] = x; \
63 c++; \
64 }
65
66 #define WRITE_TO_SPRITE32(x) { \
67 _grow_scratch_mem((c+1)*sizeof(int32_t)); \
68 p = (int32_t *)_scratch_mem; \
69 p[c] = x; \
70 c++; \
71 }
72
73 /* helper for building an RLE run */
74 #define DO_RLE(bits) \
75 { \
76 for (y=0; y<bitmap->h; y++) { \
77 run = -1; \
78 for (x=0; x<bitmap->w; x++) { \
79 pix = getpixel(bitmap, x, y) & 0xFFFFFF; \
80 if (pix != bitmap->vtable->mask_color) { \
81 if ((run >= 0) && (p[run] > 0) && (p[run] < 127)) \
82 p[run]++; \
83 else { \
84 run = c; \
85 WRITE_TO_SPRITE##bits(1); \
86 } \
87 WRITE_TO_SPRITE##bits(getpixel(bitmap, x, y)); \
88 } \
89 else { \
90 if ((run >= 0) && (p[run] < 0) && (p[run] > -128)) \
91 p[run]--; \
92 else { \
93 run = c; \
94 WRITE_TO_SPRITE##bits(-1); \
95 } \
96 } \
97 } \
98 WRITE_TO_SPRITE##bits(bitmap->vtable->mask_color); \
99 } \
100 }
101
102 c = 0;
103
104 switch (depth) {
105
106 #ifdef ALLEGRO_COLOR8
107
108 case 8:
109 {
110 signed char *p = (signed char *)_scratch_mem;
111 DO_RLE(8);
112 }
113 break;
114
115 #endif
116
117 #ifdef ALLEGRO_COLOR16
118
119 case 15:
120 case 16:
121 {
122 signed short *p = (signed short *)_scratch_mem;
123 DO_RLE(16);
124 c *= sizeof(short);
125 }
126 break;
127
128 #endif
129
130 #if (defined ALLEGRO_COLOR24) || (defined ALLEGRO_COLOR32)
131
132 case 24:
133 case 32:
134 {
135 int32_t *p = (int32_t *)_scratch_mem;
136 DO_RLE(32);
137 c *= sizeof(int32_t);
138 }
139 break;
140
141 #endif
142 }
143
144 s = _AL_MALLOC(sizeof(RLE_SPRITE) + c);
145
146 if (s) {
147 s->w = bitmap->w;
148 s->h = bitmap->h;
149 s->color_depth = depth;
150 s->size = c;
151 memcpy(s->dat, _scratch_mem, c);
152 }
153
154 return s;
155 }
156
157
158
159 /* destroy_rle_sprite:
160 * Destroys an RLE sprite structure returned by get_rle_sprite().
161 */
destroy_rle_sprite(RLE_SPRITE * sprite)162 void destroy_rle_sprite(RLE_SPRITE *sprite)
163 {
164 if (sprite)
165 _AL_FREE(sprite);
166 }
167
168
169