1 /* ______ ___ ___
2 * /\ _ \ /\_ \ /\_ \
3 * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
4 * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
5 * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
6 * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7 * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8 * /\____/
9 * \_/__/
10 *
11 * Grabber plugin for editing alpha channels.
12 *
13 * By Shawn Hargreaves.
14 *
15 * See readme.txt for copyright information.
16 */
17
18
19 #include <stdio.h>
20 #include <string.h>
21
22 #include "allegro.h"
23 #include "allegro/internal/aintern.h"
24 #include "../datedit.h"
25
26
27
28 /* creates a monochrome image containing the alpha channel of this bitmap */
get_alpha_bitmap(BITMAP * bmp)29 static BITMAP *get_alpha_bitmap(BITMAP *bmp)
30 {
31 BITMAP *alpha;
32 int x, y, c, a;
33 int got = FALSE;
34
35 if (bitmap_color_depth(bmp) != 32)
36 return NULL;
37
38 alpha = create_bitmap_ex(24, bmp->w, bmp->h);
39
40 for (y=0; y<bmp->h; y++) {
41 for (x=0; x<bmp->w; x++) {
42 c = getpixel(bmp, x, y);
43 a = geta32(c);
44 putpixel(alpha, x, y, makecol24(a, a, a));
45 if (a)
46 got = TRUE;
47 }
48 }
49
50 if (!got) {
51 destroy_bitmap(alpha);
52 return NULL;
53 }
54
55 return alpha;
56 }
57
58
59
60 /* checks whether the selection is capable of having an alpha channel */
alpha_query(int popup)61 static int alpha_query(int popup)
62 {
63 if (popup) {
64 DATAFILE *dat = grabber_single_selection();
65 return ((dat) && ((dat->type == DAT_BITMAP) || (dat->type == DAT_RLE_SPRITE)));
66 }
67
68 return TRUE;
69 }
70
71
72
73 /* views the current alpha channel */
view_alpha(void)74 static int view_alpha(void)
75 {
76 DATAFILE *dat = grabber_single_selection();
77 DATAFILE tmpdat;
78 RLE_SPRITE *rle;
79 BITMAP *bmp;
80 int ret = 0;
81 int i;
82
83 if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
84 alert("You must select a single bitmap or RLE sprite",
85 "object before you can view the alpha channel",
86 NULL, "Sorry", NULL, 13, 0);
87 return 0;
88 }
89
90 if (dat->type == DAT_RLE_SPRITE) {
91 rle = dat->dat;
92 bmp = create_bitmap_ex(rle->color_depth, rle->w, rle->h);
93 clear_to_color(bmp, bmp->vtable->mask_color);
94 draw_rle_sprite(bmp, rle, 0, 0);
95 }
96 else
97 bmp = dat->dat;
98
99 tmpdat.dat = get_alpha_bitmap(bmp);
100
101 if (tmpdat.dat) {
102 tmpdat.type = DAT_BITMAP;
103 tmpdat.size = 0;
104 tmpdat.prop = NULL;
105
106 for (i=0; datedit_object_info[i]->type != DAT_END; i++) {
107 if ((datedit_object_info[i]->type == DAT_BITMAP) && (datedit_object_info[i]->dclick)) {
108 ret = datedit_object_info[i]->dclick(&tmpdat);
109 break;
110 }
111 }
112
113 destroy_bitmap(tmpdat.dat);
114 }
115 else
116 alert("There is no alpha channel in this image", NULL, NULL, "Sorry", NULL, 13, 0);
117
118 if (dat->type == DAT_RLE_SPRITE)
119 destroy_bitmap(bmp);
120
121 return ret;
122 }
123
124
125
126 /* exports the current alpha channel */
export_alpha(void)127 static int export_alpha(void)
128 {
129 DATAFILE *dat = grabber_single_selection();
130 DATAFILE tmpdat;
131 RLE_SPRITE *rle;
132 BITMAP *bmp;
133 char buf[256], name[FILENAME_LENGTH] = EMPTY_STRING;
134 AL_CONST char *ext;
135 int ret = 0;
136
137 if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
138 alert("You must select a single bitmap or RLE sprite",
139 "object before you can export the alpha channel",
140 NULL, "Sorry", NULL, 13, 0);
141 return 0;
142 }
143
144 if (dat->type == DAT_RLE_SPRITE) {
145 rle = dat->dat;
146 bmp = create_bitmap_ex(rle->color_depth, rle->w, rle->h);
147 clear_to_color(bmp, bmp->vtable->mask_color);
148 draw_rle_sprite(bmp, rle, 0, 0);
149 }
150 else
151 bmp = dat->dat;
152
153 tmpdat.dat = get_alpha_bitmap(bmp);
154
155 if (tmpdat.dat) {
156 tmpdat.type = DAT_BITMAP;
157 tmpdat.size = 0;
158 tmpdat.prop = NULL;
159
160 ext = datedit_export_ext(DAT_BITMAP);
161 sprintf(buf, "Export alpha (%s)", ext);
162
163 strcpy(name, grabber_import_file);
164 *get_filename(name) = 0;
165
166 if (file_select_ex(buf, name, ext, sizeof(name), 0, 0)) {
167 fix_filename_case(name);
168 strcpy(grabber_import_file, name);
169 grabber_busy_mouse(TRUE);
170 datedit_export(&tmpdat, name);
171 grabber_busy_mouse(FALSE);
172 }
173
174 destroy_bitmap(tmpdat.dat);
175 ret = D_REDRAW;
176 }
177 else
178 alert("There is no alpha channel in this image", NULL, NULL, "Sorry", NULL, 13, 0);
179
180 if (dat->type == DAT_RLE_SPRITE)
181 destroy_bitmap(bmp);
182
183 return ret;
184 }
185
186
187
188 /* deletes the current alpha channel */
delete_alpha(void)189 static int delete_alpha(void)
190 {
191 DATAFILE *dat = grabber_single_selection();
192 RLE_SPRITE *rle;
193 BITMAP *bmp;
194 int got = FALSE;
195 int ret = 0;
196 int x, y, c, r, g, b, a;
197
198 if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
199 alert("You must select a single bitmap or RLE sprite",
200 "object before you can delete the alpha channel",
201 NULL, "Sorry", NULL, 13, 0);
202 return 0;
203 }
204
205 if (dat->type == DAT_RLE_SPRITE) {
206 rle = dat->dat;
207 bmp = create_bitmap_ex(rle->color_depth, rle->w, rle->h);
208 clear_to_color(bmp, bmp->vtable->mask_color);
209 draw_rle_sprite(bmp, rle, 0, 0);
210 }
211 else
212 bmp = dat->dat;
213
214 if (bitmap_color_depth(bmp) == 32) {
215 for (y=0; y<bmp->h; y++) {
216 for (x=0; x<bmp->w; x++) {
217 c = getpixel(bmp, x, y);
218 r = getr32(c);
219 g = getg32(c);
220 b = getb32(c);
221 a = geta32(c);
222 putpixel(bmp, x, y, makecol32(r, g, b));
223 if (a)
224 got = TRUE;
225 }
226 }
227 }
228
229 if (got) {
230 if (dat->type == DAT_RLE_SPRITE) {
231 destroy_rle_sprite(dat->dat);
232 dat->dat = get_rle_sprite(bmp);
233 }
234
235 alert("Success: alpha channel moved to /dev/null", NULL, NULL, "Cool", NULL, 13, 0);
236 ret = D_REDRAW;
237 }
238 else
239 alert("There is no alpha channel in this image", NULL, NULL, "Sorry", NULL, 13, 0);
240
241 if (dat->type == DAT_RLE_SPRITE)
242 destroy_bitmap(bmp);
243
244 return ret;
245 }
246
247
248
249 /* worker function for importing alpha channels */
do_alpha_import(BITMAP * bmp,int * changed,RGB * pal)250 static BITMAP *do_alpha_import(BITMAP *bmp, int *changed, RGB *pal)
251 {
252 BITMAP *newbmp;
253 DATAFILE *alpha;
254 char buf[256], name[FILENAME_LENGTH];
255 DATEDIT_GRAB_PARAMETERS params;
256 AL_CONST char *ext;
257 int x, y, c, r, g, b, a;
258
259 *changed = FALSE;
260
261 ext = datedit_grab_ext(DAT_BITMAP);
262 sprintf(buf, "Import alpha (%s)", ext);
263
264 strcpy(name, grabber_import_file);
265 *get_filename(name) = 0;
266
267 if (file_select_ex(buf, name, ext, sizeof(name), 0, 0)) {
268 fix_filename_case(name);
269 strcpy(grabber_import_file, name);
270 grabber_busy_mouse(TRUE);
271
272 params.datafile = NULL; /* only with absolute filenames */
273 params.filename = name;
274 params.name = name;
275 params.type = DAT_BITMAP;
276 params.x = -1;
277 params.y = -1;
278 params.w = -1;
279 params.h = -1;
280 params.colordepth = -1;
281 params.relative = FALSE; /* required (see above) */
282
283 alpha = datedit_grab(NULL, ¶ms);
284
285 if ((alpha) && (alpha->dat)) {
286 if (pal)
287 select_palette(pal);
288
289 newbmp = create_bitmap_ex(32, bmp->w, bmp->h);
290 blit(bmp, newbmp, 0, 0, 0, 0, bmp->w, bmp->h);
291 destroy_bitmap(bmp);
292 bmp = newbmp;
293
294 if (pal)
295 unselect_palette();
296
297 select_palette(datedit_last_read_pal);
298
299 for (y=0; y<bmp->h; y++) {
300 for (x=0; x<bmp->w; x++) {
301 if (getpixel(bmp, x, y) != bitmap_mask_color(bmp)) {
302 c = getpixel(alpha->dat, x, y);
303 r = getr_depth(bitmap_color_depth(alpha->dat), c);
304 g = getg_depth(bitmap_color_depth(alpha->dat), c);
305 b = getb_depth(bitmap_color_depth(alpha->dat), c);
306 a = (r+g+b)/3;
307
308 bmp->line[y][x*4+_rgb_a_shift_32/8] = a;
309 }
310 }
311 }
312
313 unselect_palette();
314 _unload_datafile_object(alpha);
315
316 *changed = TRUE;
317 }
318
319 grabber_busy_mouse(FALSE);
320 }
321
322 return bmp;
323 }
324
325
326
327 /* imports an alpha channel over the top of the current selection */
import_alpha(void)328 static int import_alpha(void)
329 {
330 DATAFILE *dat = grabber_single_selection();
331 RLE_SPRITE *rle;
332 BITMAP *bmp;
333 int changed;
334
335 if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
336 alert("You must select a single bitmap or RLE sprite",
337 "object before you can import an alpha channel",
338 NULL, "Sorry", NULL, 13, 0);
339 return 0;
340 }
341
342 if (dat->type == DAT_RLE_SPRITE) {
343 rle = dat->dat;
344 bmp = create_bitmap_ex(rle->color_depth, rle->w, rle->h);
345 clear_to_color(bmp, bmp->vtable->mask_color);
346 draw_rle_sprite(bmp, rle, 0, 0);
347 bmp = do_alpha_import(bmp, &changed, NULL);
348 destroy_rle_sprite(rle);
349 dat->dat = get_rle_sprite(bmp);
350 destroy_bitmap(bmp);
351 }
352 else
353 dat->dat = do_alpha_import(dat->dat, &changed, NULL);
354
355 if (changed)
356 view_alpha();
357
358 return D_REDRAW;
359 }
360
361
362
363 /* reads an alpha channel over the top of the grab source bitmap */
read_alpha(void)364 static int read_alpha(void)
365 {
366 int changed;
367
368 if (!grabber_graphic) {
369 alert("You must read in a bitmap file before", "you can add an alpha channel to it", NULL, "OK", NULL, 13, 0);
370 return 0;
371 }
372
373 grabber_graphic = do_alpha_import(grabber_graphic, &changed, grabber_palette);
374
375 if (changed)
376 alert("Alpha channel imported successfully: this will be", "used when you next grab a bitmap or RLE sprite", NULL, "OK", NULL, 13, 0);
377
378 return D_REDRAW;
379 }
380
381
382
383 /* menu commands for doing stuff to the alpha channel */
384 static MENU alpha_sub_menu[] =
385 {
386 { "&View Alpha", view_alpha, NULL, 0, NULL },
387 { "&Import Alpha", import_alpha, NULL, 0, NULL },
388 { "&Export Alpha", export_alpha, NULL, 0, NULL },
389 { "&Delete Alpha", delete_alpha, NULL, 0, NULL },
390 { NULL, NULL, NULL, 0, NULL }
391 };
392
393
394
395 /* per-object alpha channel menu */
396 static MENU alpha_menu =
397 {
398 "Alpha Channel",
399 NULL,
400 alpha_sub_menu,
401 0,
402 NULL
403 };
404
405
406
407 /* alpha channel command for the file menu */
408 static MENU read_alpha_menu =
409 {
410 "Read Alpha Channel",
411 read_alpha,
412 NULL,
413 0,
414 NULL
415 };
416
417
418
419 /* plugin interface header */
420 DATEDIT_MENU_INFO datalpha_menu1 =
421 {
422 &alpha_menu,
423 alpha_query,
424 DATEDIT_MENU_POPUP | DATEDIT_MENU_OBJECT,
425 0,
426 NULL
427 };
428
429
430
431 DATEDIT_MENU_INFO datalpha_menu2 =
432 {
433 &read_alpha_menu,
434 NULL,
435 DATEDIT_MENU_FILE,
436 0,
437 NULL
438 };
439
440