Show datalpha.c syntax highlighted
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* Grabber plugin for editing alpha channels.
*
* By Shawn Hargreaves.
*
* See readme.txt for copyright information.
*/
#include <stdio.h>
#include <string.h>
#include "allegro.h"
#include "allegro/internal/aintern.h"
#include "../datedit.h"
/* 80 characters * maximum character width (6 bytes for UTF8) */
#define FILENAME_LENGTH (80*6)
/* creates a monochrome image containing the alpha channel of this bitmap */
static AL_BITMAP *get_alpha_bitmap(AL_BITMAP *bmp)
{
AL_BITMAP *alpha;
int x, y, c, a;
int got = FALSE;
if (al_bitmap_color_depth(bmp) != 32)
return NULL;
alpha = al_create_bitmap_ex(24, bmp->w, bmp->h);
for (y=0; y<bmp->h; y++) {
for (x=0; x<bmp->w; x++) {
c = al_get_pixel(bmp, x, y);
a = al_get_a32(c);
al_put_pixel(alpha, x, y, al_make_color_24(a, a, a));
if (a)
got = TRUE;
}
}
if (!got) {
al_destroy_bitmap(alpha);
return NULL;
}
return alpha;
}
/* checks whether the selection is capable of having an alpha channel */
static int alpha_query(int popup)
{
if (popup) {
AL_DATAFILE *dat = grabber_single_selection();
return ((dat) && ((dat->type == DAT_BITMAP) || (dat->type == DAT_RLE_SPRITE)));
}
return TRUE;
}
/* views the current alpha channel */
static int view_alpha(void)
{
AL_DATAFILE *dat = grabber_single_selection();
AL_DATAFILE tmpdat;
AL_RLE_SPRITE *rle;
AL_BITMAP *bmp;
int ret = 0;
int i;
if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
al_show_alert("You must select a single bitmap or RLE sprite",
"object before you can view the alpha channel",
NULL, "Sorry", NULL, 13, 0);
return 0;
}
if (dat->type == DAT_RLE_SPRITE) {
rle = dat->dat;
bmp = al_create_bitmap_ex(rle->color_depth, rle->w, rle->h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_draw_rle_sprite(bmp, rle, 0, 0);
}
else
bmp = dat->dat;
tmpdat.dat = get_alpha_bitmap(bmp);
if (tmpdat.dat) {
tmpdat.type = DAT_BITMAP;
tmpdat.size = 0;
tmpdat.prop = NULL;
for (i=0; datedit_object_info[i]->type != DAT_END; i++) {
if ((datedit_object_info[i]->type == DAT_BITMAP) && (datedit_object_info[i]->dclick)) {
ret = datedit_object_info[i]->dclick(&tmpdat);
break;
}
}
al_destroy_bitmap(tmpdat.dat);
}
else
al_show_alert("There is no alpha channel in this image", NULL, NULL, "Sorry", NULL, 13, 0);
if (dat->type == DAT_RLE_SPRITE)
al_destroy_bitmap(bmp);
return ret;
}
/* exports the current alpha channel */
static int export_alpha(void)
{
AL_DATAFILE *dat = grabber_single_selection();
AL_DATAFILE tmpdat;
AL_RLE_SPRITE *rle;
AL_BITMAP *bmp;
char buf[256], name[FILENAME_LENGTH] = EMPTY_STRING;
AL_CONST char *ext;
int ret = 0;
if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
al_show_alert("You must select a single bitmap or RLE sprite",
"object before you can export the alpha channel",
NULL, "Sorry", NULL, 13, 0);
return 0;
}
if (dat->type == DAT_RLE_SPRITE) {
rle = dat->dat;
bmp = al_create_bitmap_ex(rle->color_depth, rle->w, rle->h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_draw_rle_sprite(bmp, rle, 0, 0);
}
else
bmp = dat->dat;
tmpdat.dat = get_alpha_bitmap(bmp);
if (tmpdat.dat) {
tmpdat.type = DAT_BITMAP;
tmpdat.size = 0;
tmpdat.prop = NULL;
ext = datedit_export_ext(DAT_BITMAP);
sprintf(buf, "Export alpha (%s)", ext);
strcpy(name, grabber_import_file);
*get_filename(name) = 0;
if (al_select_file(buf, name, ext, sizeof(name), 0, 0)) {
al_fix_filename_case(name);
strcpy(grabber_import_file, name);
grabber_busy_mouse(TRUE);
datedit_export(&tmpdat, name);
grabber_busy_mouse(FALSE);
}
al_destroy_bitmap(tmpdat.dat);
ret = D_REDRAW;
}
else
al_show_alert("There is no alpha channel in this image", NULL, NULL, "Sorry", NULL, 13, 0);
if (dat->type == DAT_RLE_SPRITE)
al_destroy_bitmap(bmp);
return ret;
}
/* deletes the current alpha channel */
static int delete_alpha(void)
{
AL_DATAFILE *dat = grabber_single_selection();
AL_RLE_SPRITE *rle;
AL_BITMAP *bmp;
int got = FALSE;
int ret = 0;
int x, y, c, r, g, b, a;
if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
al_show_alert("You must select a single bitmap or RLE sprite",
"object before you can delete the alpha channel",
NULL, "Sorry", NULL, 13, 0);
return 0;
}
if (dat->type == DAT_RLE_SPRITE) {
rle = dat->dat;
bmp = al_create_bitmap_ex(rle->color_depth, rle->w, rle->h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_draw_rle_sprite(bmp, rle, 0, 0);
}
else
bmp = dat->dat;
if (al_bitmap_color_depth(bmp) == 32) {
for (y=0; y<bmp->h; y++) {
for (x=0; x<bmp->w; x++) {
c = al_get_pixel(bmp, x, y);
r = al_get_r32(c);
g = al_get_g32(c);
b = al_get_b32(c);
a = al_get_a32(c);
al_put_pixel(bmp, x, y, al_make_color_32(r, g, b));
if (a)
got = TRUE;
}
}
}
if (got) {
if (dat->type == DAT_RLE_SPRITE) {
al_destroy_rle_sprite(dat->dat);
dat->dat = al_create_rle_sprite(bmp);
}
al_show_alert("Success: alpha channel moved to /dev/null", NULL, NULL, "Cool", NULL, 13, 0);
ret = D_REDRAW;
}
else
al_show_alert("There is no alpha channel in this image", NULL, NULL, "Sorry", NULL, 13, 0);
if (dat->type == DAT_RLE_SPRITE)
al_destroy_bitmap(bmp);
return ret;
}
/* worker function for importing alpha channels */
static AL_BITMAP *do_alpha_import(AL_BITMAP *bmp, int *changed, AL_RGB *pal)
{
AL_BITMAP *newbmp;
AL_DATAFILE *alpha;
char buf[256], name[FILENAME_LENGTH];
AL_CONST char *ext;
int x, y, c, r, g, b, a;
*changed = FALSE;
ext = datedit_grab_ext(DAT_BITMAP);
sprintf(buf, "Import alpha (%s)", ext);
strcpy(name, grabber_import_file);
*get_filename(name) = 0;
if (al_select_file(buf, name, ext, sizeof(name), 0, 0)) {
al_fix_filename_case(name);
strcpy(grabber_import_file, name);
grabber_busy_mouse(TRUE);
alpha = datedit_grab(name, name, DAT_BITMAP, -1, -1, -1, -1, -1);
if ((alpha) && (alpha->dat)) {
if (pal)
al_select_palette(pal);
newbmp = al_create_bitmap_ex(32, bmp->w, bmp->h);
al_blit(bmp, newbmp, 0, 0, 0, 0, bmp->w, bmp->h);
al_destroy_bitmap(bmp);
bmp = newbmp;
if (pal)
al_unselect_palette();
al_select_palette(datedit_last_read_pal);
for (y=0; y<bmp->h; y++) {
for (x=0; x<bmp->w; x++) {
if (al_get_pixel(bmp, x, y) != al_bitmap_mask_color(bmp)) {
c = al_get_pixel(alpha->dat, x, y);
r = al_get_r_depth(al_bitmap_color_depth(alpha->dat), c);
g = al_get_g_depth(al_bitmap_color_depth(alpha->dat), c);
b = al_get_b_depth(al_bitmap_color_depth(alpha->dat), c);
a = (r+g+b)/3;
bmp->al_draw_line[y][x*4+_rgb_a_shift_32/8] = a;
}
}
}
al_unselect_palette();
_unload_datafile_object(alpha);
*changed = TRUE;
}
grabber_busy_mouse(FALSE);
}
return bmp;
}
/* imports an alpha channel over the top of the current selection */
static int import_alpha(void)
{
AL_DATAFILE *dat = grabber_single_selection();
AL_RLE_SPRITE *rle;
AL_BITMAP *bmp;
int changed;
if ((!dat) || ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE))) {
al_show_alert("You must select a single bitmap or RLE sprite",
"object before you can import an alpha channel",
NULL, "Sorry", NULL, 13, 0);
return 0;
}
if (dat->type == DAT_RLE_SPRITE) {
rle = dat->dat;
bmp = al_create_bitmap_ex(rle->color_depth, rle->w, rle->h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_draw_rle_sprite(bmp, rle, 0, 0);
bmp = do_alpha_import(bmp, &changed, NULL);
al_destroy_rle_sprite(rle);
dat->dat = al_create_rle_sprite(bmp);
al_destroy_bitmap(bmp);
}
else
dat->dat = do_alpha_import(dat->dat, &changed, NULL);
if (changed)
view_alpha();
return D_REDRAW;
}
/* reads an alpha channel over the top of the grab source bitmap */
static int read_alpha(void)
{
int changed;
if (!grabber_graphic) {
al_show_alert("You must read in a bitmap file before", "you can add an alpha channel to it", NULL, "OK", NULL, 13, 0);
return 0;
}
grabber_graphic = do_alpha_import(grabber_graphic, &changed, grabber_palette);
if (changed)
al_show_alert("Alpha channel imported successfully: this will be", "used when you next grab a bitmap or RLE sprite", NULL, "OK", NULL, 13, 0);
return D_REDRAW;
}
/* menu commands for doing stuff to the alpha channel */
static AL_MENU alpha_sub_menu[] =
{
{ "&View Alpha", view_alpha, NULL, 0, NULL },
{ "&Import Alpha", import_alpha, NULL, 0, NULL },
{ "&Export Alpha", export_alpha, NULL, 0, NULL },
{ "&Delete Alpha", delete_alpha, NULL, 0, NULL },
{ NULL, NULL, NULL, 0, NULL }
};
/* per-object alpha channel menu */
static AL_MENU alpha_menu =
{
"Alpha Channel",
NULL,
alpha_sub_menu,
0,
NULL
};
/* alpha channel command for the file menu */
static AL_MENU read_alpha_menu =
{
"Read Alpha Channel",
read_alpha,
NULL,
0,
NULL
};
/* plugin interface header */
DATEDIT_MENU_INFO datalpha_menu1 =
{
&alpha_menu,
alpha_query,
DATEDIT_MENU_POPUP | DATEDIT_MENU_OBJECT,
0
};
DATEDIT_MENU_INFO datalpha_menu2 =
{
&read_alpha_menu,
NULL,
DATEDIT_MENU_FILE,
0
};
See more files for this project here