Show datimage.c syntax highlighted
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* Grabber plugin for managing bitmapped image objects. Regular
* bitmaps, RLE sprites, and compiled sprites are all handled in
* this one file, because they can share a lot of common code.
*
* 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"
/* checks whether this bitmap has an alpha channel */
static int bitmap_has_alpha(AL_BITMAP *bmp)
{
int x, y, c;
if (al_bitmap_color_depth(bmp) != 32)
return FALSE;
for (y=0; y<bmp->h; y++) {
for (x=0; x<bmp->w; x++) {
c = al_get_pixel(bmp, x, y);
if (al_get_a32(c))
return TRUE;
}
}
return FALSE;
}
/* checks whether this RLE sprite has an alpha channel */
static int rle_has_alpha(AL_CONST AL_RLE_SPRITE *spr)
{
signed long *p32;
int x, y, c;
if (spr->color_depth != 32)
return FALSE;
p32 = (signed long *)spr->dat;
for (y=0; y<spr->h; y++) {
while ((unsigned long)*p32 != AL_MASK_COLOR_32) {
if (*p32 < 0) {
p32++;
}
else {
x = *p32;
p32++;
while (x-- > 0) {
c = (unsigned long)*p32;
if (al_get_a32(c))
return TRUE;
p32++;
}
}
}
p32++;
}
return FALSE;
}
/* creates a new bitmap object */
static void *makenew_bitmap(long *size)
{
AL_BITMAP *bmp = al_create_bitmap_ex(8, 32, 32);
al_clear_bitmap(bmp);
al_text_mode(-1);
al_put_text_centre(bmp, al_font_8x8, "Hi!", 16, 12, 1);
return bmp;
}
/* returns a bitmap description string */
static void get_bitmap_desc(AL_CONST AL_DATAFILE *dat, char *s)
{
AL_BITMAP *bmp = (AL_BITMAP *)dat->dat;
sprintf(s, "bitmap (%dx%d, %d bit)", bmp->w, bmp->h, al_bitmap_color_depth(bmp));
if (bitmap_has_alpha(bmp))
strcat(s, " +alpha");
}
/* exports a bitmap into an external file */
static int export_bitmap(AL_CONST AL_DATAFILE *dat, AL_CONST char *filename)
{
return (al_save_bitmap(filename, (AL_BITMAP *)dat->dat, datedit_current_palette) == 0);
}
/* draws a bitmap onto the grabber object view window */
static void plot_bitmap(AL_CONST AL_DATAFILE *dat, int x, int y)
{
AL_BITMAP *b = dat->dat;
int w = b->w;
int h = b->h;
fixed scale;
if (w > AL_SCREEN_W-x-8) {
scale = al_int_to_fix(AL_SCREEN_W-x-8) / w;
w = (w * scale) >> 16;
h = (h * scale) >> 16;
}
if (h > AL_SCREEN_H-y-40) {
scale = al_int_to_fix(AL_SCREEN_H-y-40) / h;
w = (w * scale) >> 16;
h = (h * scale) >> 16;
}
al_draw_rect(al_screen, x, y+32, x+w+1, y+32+h+1, al_gui_fg_color);
if ((al_bitmap_color_depth(al_screen) == 8) && (al_bitmap_color_depth(b) > 8)) {
if ((w != b->w) || (h != b->h))
al_put_text(al_screen, al_font_8x8, "<reduced color scaled preview>", x, y+18, al_gui_fg_color);
else
al_put_text(al_screen, al_font_8x8, "<reduced color preview>", x, y+18, al_gui_fg_color);
}
else if ((w != b->w) || (h != b->h))
al_put_text(al_screen, al_font_8x8, "<scaled preview>", x, y+18, al_gui_fg_color);
if (al_bitmap_color_depth(b) == al_bitmap_color_depth(al_screen)) {
if (dat->type != DAT_BITMAP)
al_stretch_sprite(al_screen, b, x+1, y+33, w, h);
else
al_stretch(b, al_screen, 0, 0, b->w, b->h, x+1, y+33, w, h);
}
else {
AL_BITMAP *b2 = al_create_bitmap_ex(al_bitmap_color_depth(b), w, h);
al_clear_to_color(b2, al_make_color_depth(al_bitmap_color_depth(b2), 0x80, 0x80, 0x80));
if (dat->type != DAT_BITMAP) {
AL_RGB tmprgb = datedit_current_palette[0];
datedit_current_palette[0].r = 63;
datedit_current_palette[0].g = 0;
datedit_current_palette[0].b = 63;
al_select_palette(datedit_current_palette);
al_stretch_sprite(b2, b, 0, 0, w, h);
al_blit(b2, al_screen, 0, 0, x+1, y+33, w, h);
al_unselect_palette();
datedit_current_palette[0] = tmprgb;
}
else {
al_stretch(b, b2, 0, 0, b->w, b->h, 0, 0, w, h);
al_blit(b2, al_screen, 0, 0, x+1, y+33, w, h);
}
al_destroy_bitmap(b2);
}
}
/* handles double-clicking on a bitmap in the grabber */
static int view_bitmap(AL_DATAFILE *dat)
{
AL_BITMAP *b = dat->dat;
fixed scale = al_int_to_fix(1);
fixed prevscale = al_int_to_fix(1);
int x = 0;
int y = 0;
int prevx = 0;
int prevy = 0;
AL_BITMAP *bc = NULL;
int done = FALSE;
int c;
al_show_mouse(NULL);
al_clear_to_color(al_screen, al_gui_mg_color);
al_blit(b, al_screen, 0, 0, 0, 0, b->w, b->h);
al_clear_keybuf();
do {
al_poll_mouse();
} while (al_mouse_b);
do {
if ((x != prevx) || (y != prevy) || (scale != prevscale)) {
prevx = al_int_to_fix(AL_SCREEN_W) / scale;
prevy = al_int_to_fix(AL_SCREEN_H) / scale;
if ((b->w >= prevx) && (x+prevx > b->w))
x = b->w-prevx;
else if ((b->w < prevx) && (x > 0))
x = 0;
if ((b->h >= prevy) && (y+prevy > b->h))
y = b->h-prevy;
else if ((b->h < prevy) && (y > 0))
y = 0;
if (x < 0)
x = 0;
if (y < 0)
y = 0;
if (scale != prevscale)
al_clear_to_color(al_screen, al_gui_mg_color);
if (!bc) {
bc = al_create_bitmap(b->w, b->h);
al_blit(b, bc, 0, 0, 0, 0, b->w, b->h);
}
al_stretch(bc, al_screen, x, y, b->w-x, b->h-y, 0, 0, ((b->w-x)*scale)>>16, ((b->h-y)*scale)>>16);
prevx = x;
prevy = y;
prevscale = scale;
}
while (al_key_pressed()) {
c = al_read_key();
switch (c >> 8) {
case AL_KEY_DOWN:
y += 4;
break;
case AL_KEY_RIGHT:
x += 4;
break;
case AL_KEY_UP:
y -= 4;
break;
case AL_KEY_LEFT:
x -= 4;
break;
case AL_KEY_HOME:
x = 0;
y = 0;
break;
case AL_KEY_END:
x = 65536;
y = 65536;
break;
case AL_KEY_PGUP:
if (scale > al_int_to_fix(1)/16)
scale /= 2;
break;
case AL_KEY_PGDN:
if (scale < al_int_to_fix(16))
scale *= 2;
break;
default:
switch (c & 0xFF) {
case '+':
if (scale < al_int_to_fix(16))
scale *= 2;
break;
case '-':
if (scale > al_int_to_fix(1)/16)
scale /= 2;
break;
default:
done = TRUE;
break;
}
break;
}
}
al_poll_mouse();
if (al_mouse_b)
done = TRUE;
} while (!done);
if (bc)
al_destroy_bitmap(bc);
al_clear_keybuf();
do {
al_poll_mouse();
} while (al_mouse_b);
al_clear_bitmap(al_screen);
al_show_mouse(al_screen);
return D_REDRAW;
}
/* reads a bitmap from an external file */
static void *grab_bitmap(AL_CONST char *filename, long *size, int x, int y, int w, int h, int depth)
{
AL_BITMAP *bmp;
if (depth > 0) {
int oldcolordepth = _color_depth;
_color_depth = depth;
al_set_color_conversion(AL_COLORCONV_TOTAL);
bmp = al_load_bitmap(filename, datedit_last_read_pal);
_color_depth = oldcolordepth;
al_set_color_conversion(AL_COLORCONV_NONE);
}
else
bmp = al_load_bitmap(filename, datedit_last_read_pal);
if (!bmp)
return NULL;
if ((x >= 0) && (y >= 0) && (w >= 0) && (h >= 0)) {
AL_BITMAP *b2 = al_create_bitmap_ex(al_bitmap_color_depth(bmp), w, h);
al_clear_to_color(b2, al_bitmap_mask_color(b2));
al_blit(bmp, b2, x, y, 0, 0, w, h);
al_destroy_bitmap(bmp);
return b2;
}
else
return bmp;
}
/* saves a bitmap into the datafile format */
static void save_datafile_bitmap(AL_DATAFILE *dat, int packed, int packkids, int strip, int verbose, int extra, AL_PACKFILE *f)
{
AL_BITMAP *bmp = (AL_BITMAP *)dat->dat;
int x, y, c, r, g, b, a;
unsigned short *p16;
unsigned long *p32;
int depth;
if (bitmap_has_alpha(bmp))
depth = -32;
else
depth = al_bitmap_color_depth(bmp);
pack_mputw(depth, f);
pack_mputw(bmp->w, f);
pack_mputw(bmp->h, f);
switch (depth) {
case 8:
/* 256 colors */
for (y=0; y<bmp->h; y++)
for (x=0; x<bmp->w; x++)
pack_putc(bmp->al_draw_line[y][x], f);
break;
case 15:
case 16:
/* hicolor */
for (y=0; y<bmp->h; y++) {
p16 = (unsigned short *)bmp->al_draw_line[y];
for (x=0; x<bmp->w; x++) {
c = p16[x];
r = al_get_r_depth(depth, c);
g = al_get_g_depth(depth, c);
b = al_get_b_depth(depth, c);
c = ((r<<8)&0xF800) | ((g<<3)&0x7E0) | ((b>>3)&0x1F);
pack_iputw(c, f);
}
}
break;
case 24:
/* 24 bit truecolor */
for (y=0; y<bmp->h; y++) {
for (x=0; x<bmp->w; x++) {
r = bmp->al_draw_line[y][x*3+_rgb_r_shift_24/8];
g = bmp->al_draw_line[y][x*3+_rgb_g_shift_24/8];
b = bmp->al_draw_line[y][x*3+_rgb_b_shift_24/8];
pack_putc(r, f);
pack_putc(g, f);
pack_putc(b, f);
}
}
break;
case 32:
/* 32 bit truecolor */
for (y=0; y<bmp->h; y++) {
p32 = (unsigned long *)bmp->al_draw_line[y];
for (x=0; x<bmp->w; x++) {
c = p32[x];
r = al_get_r32(c);
g = al_get_g32(c);
b = al_get_b32(c);
pack_putc(r, f);
pack_putc(g, f);
pack_putc(b, f);
}
}
break;
case -32:
/* 32 bit truecolor with alpha channel */
for (y=0; y<bmp->h; y++) {
p32 = (unsigned long *)bmp->al_draw_line[y];
for (x=0; x<bmp->w; x++) {
c = p32[x];
r = al_get_r32(c);
g = al_get_g32(c);
b = al_get_b32(c);
a = al_get_a32(c);
pack_putc(r, f);
pack_putc(g, f);
pack_putc(b, f);
pack_putc(a, f);
}
}
break;
}
}
/* creates a new RLE sprite object */
static void *makenew_rle_sprite(long *size)
{
AL_BITMAP *bmp = makenew_bitmap(size);
AL_RLE_SPRITE *spr = al_create_rle_sprite(bmp);
al_destroy_bitmap(bmp);
return spr;
}
/* draws an RLE sprite onto the grabber object view window */
static void plot_rle_sprite(AL_CONST AL_DATAFILE *dat, int x, int y)
{
AL_RLE_SPRITE *s = dat->dat;
AL_BITMAP *b = al_create_bitmap_ex(s->color_depth, s->w, s->h);
AL_DATAFILE tmpdat;
tmpdat.dat = b;
tmpdat.type = DAT_RLE_SPRITE;
tmpdat.size = 0;
tmpdat.prop = NULL;
al_clear_to_color(b, b->vtable->mask_color);
al_draw_rle_sprite(b, s, 0, 0);
plot_bitmap(&tmpdat, x, y);
al_destroy_bitmap(b);
}
/* handles double-clicking on an RLE sprite in the grabber */
static int view_rle_sprite(AL_DATAFILE *dat)
{
AL_RLE_SPRITE *spr = dat->dat;
AL_BITMAP *bmp = al_create_bitmap_ex(spr->color_depth, spr->w, spr->h);
AL_DATAFILE tmpdat;
tmpdat.dat = bmp;
tmpdat.type = DAT_RLE_SPRITE;
tmpdat.size = 0;
tmpdat.prop = NULL;
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_draw_rle_sprite(bmp, spr, 0, 0);
view_bitmap(&tmpdat);
al_destroy_bitmap(bmp);
return D_REDRAW;
}
/* returns a description string for an RLE sprite */
static void get_rle_sprite_desc(AL_CONST AL_DATAFILE *dat, char *s)
{
AL_RLE_SPRITE *spr = (AL_RLE_SPRITE *)dat->dat;
sprintf(s, "RLE sprite (%dx%d, %d bit)", spr->w, spr->h, spr->color_depth);
if (rle_has_alpha(spr))
strcat(s, " +alpha");
}
/* exports an RLE sprite into an external file */
static int export_rle_sprite(AL_CONST AL_DATAFILE *dat, AL_CONST char *filename)
{
AL_BITMAP *bmp;
AL_RLE_SPRITE *rle = (AL_RLE_SPRITE *)dat->dat;
int ret;
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);
ret = (al_save_bitmap(filename, bmp, datedit_current_palette) == 0);
al_destroy_bitmap(bmp);
return ret;
}
/* reads an RLE sprite from an external file */
static void *grab_rle_sprite(AL_CONST char *filename, long *size, int x, int y, int w, int h, int depth)
{
AL_BITMAP *bmp;
AL_RLE_SPRITE *spr;
bmp = (AL_BITMAP *)grab_bitmap(filename, size, x, y, w, h, depth);
if (!bmp)
return NULL;
spr = al_create_rle_sprite(bmp);
al_destroy_bitmap(bmp);
return spr;
}
/* saves an RLE sprite into the datafile format */
static void save_rle_sprite(AL_DATAFILE *dat, int packed, int packkids, int strip, int verbose, int extra, AL_PACKFILE *f)
{
AL_RLE_SPRITE *spr = (AL_RLE_SPRITE *)dat->dat;
int x, y, c, r, g, b, a;
signed short *p16;
signed long *p32;
unsigned long eol_marker;
int depth;
if (rle_has_alpha(spr))
depth = -32;
else
depth = spr->color_depth;
pack_mputw(depth, f);
pack_mputw(spr->w, f);
pack_mputw(spr->h, f);
pack_mputl(spr->size, f);
switch (depth) {
case 8:
/* 256 colors, easy! */
pack_fwrite(spr->dat, spr->size, f);
break;
case 15:
case 16:
/* hicolor */
p16 = (signed short *)spr->dat;
eol_marker = (depth == 15) ? AL_MASK_COLOR_15 : AL_MASK_COLOR_16;
for (y=0; y<spr->h; y++) {
while ((unsigned short)*p16 != (unsigned short)eol_marker) {
if (*p16 < 0) {
/* skip count */
pack_iputw(*p16, f);
p16++;
}
else {
/* solid run */
x = *p16;
p16++;
pack_iputw(x, f);
while (x-- > 0) {
c = (unsigned short)*p16;
r = al_get_r_depth(depth, c);
g = al_get_g_depth(depth, c);
b = al_get_b_depth(depth, c);
c = ((r<<8)&0xF800) | ((g<<3)&0x7E0) | ((b>>3)&0x1F);
pack_iputw(c, f);
p16++;
}
}
}
/* end of al_draw_line */
pack_iputw(AL_MASK_COLOR_16, f);
p16++;
}
break;
case 24:
case 32:
/* truecolor */
p32 = (signed long *)spr->dat;
eol_marker = (depth == 24) ? AL_MASK_COLOR_24 : AL_MASK_COLOR_32;
for (y=0; y<spr->h; y++) {
while ((unsigned long)*p32 != eol_marker) {
if (*p32 < 0) {
/* skip count */
pack_iputl(*p32, f);
p32++;
}
else {
/* solid run */
x = *p32;
p32++;
pack_iputl(x, f);
while (x-- > 0) {
c = (unsigned long)*p32;
r = al_get_r_depth(depth, c);
g = al_get_g_depth(depth, c);
b = al_get_b_depth(depth, c);
pack_putc(r, f);
pack_putc(g, f);
pack_putc(b, f);
p32++;
}
}
}
/* end of al_draw_line */
pack_iputl(AL_MASK_COLOR_32, f);
p32++;
}
break;
case -32:
/* truecolor with alpha channel */
p32 = (signed long *)spr->dat;
for (y=0; y<spr->h; y++) {
while ((unsigned long)*p32 != AL_MASK_COLOR_32) {
if (*p32 < 0) {
/* skip count */
pack_iputl(*p32, f);
p32++;
}
else {
/* solid run */
x = *p32;
p32++;
pack_iputl(x, f);
while (x-- > 0) {
c = (unsigned long)*p32;
r = al_get_r32(c);
g = al_get_g32(c);
b = al_get_b32(c);
a = al_get_a32(c);
pack_putc(r, f);
pack_putc(g, f);
pack_putc(b, f);
pack_putc(a, f);
p32++;
}
}
}
/* end of al_draw_line */
pack_iputl(AL_MASK_COLOR_32, f);
p32++;
}
break;
}
}
/* returns a description string for a compiled sprite object */
static void get_c_sprite_desc(AL_CONST AL_DATAFILE *dat, char *s)
{
AL_BITMAP *bmp = (AL_BITMAP *)dat->dat;
sprintf(s, "compiled sprite (%dx%d, %d bit)", bmp->w, bmp->h, al_bitmap_color_depth(bmp));
}
/* returns a description string for a mode-X compiled sprite object */
static void get_xc_sprite_desc(AL_CONST AL_DATAFILE *dat, char *s)
{
AL_BITMAP *bmp = (AL_BITMAP *)dat->dat;
if (al_bitmap_color_depth(bmp) == 8)
sprintf(s, "mode-X compiled sprite (%dx%d)", bmp->w, bmp->h);
else
sprintf(s, "!!! %d bit XC sprite not possible !!!", al_bitmap_color_depth(bmp));
}
/* plugin interface header */
DATEDIT_OBJECT_INFO datbitmap_info =
{
DAT_BITMAP,
"Bitmap",
get_bitmap_desc,
makenew_bitmap,
save_datafile_bitmap,
plot_bitmap,
view_bitmap,
NULL
};
DATEDIT_GRABBER_INFO datbitmap_grabber =
{
DAT_BITMAP,
"bmp;lbm;pcx;tga",
"bmp;pcx;tga",
grab_bitmap,
export_bitmap
};
/* plugin interface header */
DATEDIT_OBJECT_INFO datrlesprite_info =
{
DAT_RLE_SPRITE,
"RLE sprite",
get_rle_sprite_desc,
makenew_rle_sprite,
save_rle_sprite,
plot_rle_sprite,
view_rle_sprite,
NULL
};
DATEDIT_GRABBER_INFO datrlesprite_grabber =
{
DAT_RLE_SPRITE,
"bmp;lbm;pcx;tga",
"bmp;pcx;tga",
grab_rle_sprite,
export_rle_sprite
};
/* plugin interface header */
DATEDIT_OBJECT_INFO datcsprite_info =
{
DAT_C_SPRITE,
"Compiled sprite",
get_c_sprite_desc,
makenew_bitmap,
save_datafile_bitmap,
plot_bitmap,
view_bitmap,
NULL
};
DATEDIT_GRABBER_INFO datcsprite_grabber =
{
DAT_C_SPRITE,
"bmp;lbm;pcx;tga",
"bmp;pcx;tga",
grab_bitmap,
export_bitmap
};
/* plugin interface header */
DATEDIT_OBJECT_INFO datxcsprite_info =
{
DAT_XC_SPRITE,
"Compiled X-sprite",
get_xc_sprite_desc,
makenew_bitmap,
save_datafile_bitmap,
plot_bitmap,
view_bitmap,
NULL
};
DATEDIT_GRABBER_INFO datxcsprite_grabber =
{
DAT_XC_SPRITE,
"bmp;lbm;pcx;tga",
"bmp;pcx;tga",
grab_bitmap,
export_bitmap
};
See more files for this project here