Show datgrab.c syntax highlighted
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* Grabber plugin for implementing the interactive bitmap grab
* command (where you select an image region using the mouse).
* This file provides a special version of the "grab" function
* for use with bitmap images, and adds the "box grab" and
* "ungrab" routines.
*
* By Shawn Hargreaves.
*
* See readme.txt for copyright information.
*/
#include <stdio.h>
#include <string.h>
#include "allegro.h"
#include "../datedit.h"
/* handles grabbing data from a bitmap */
static void grabbit(AL_DATAFILE *dat, int box)
{
int xgrid, ygrid;
int using_mouse;
int x, y, w, h;
int ox = -1, oy = -1, ow = -1, oh = -1;
char buf[80];
AL_BITMAP *graphiccopy;
AL_BITMAP *pattern;
AL_BITMAP *bmp;
AL_RLE_SPRITE *spr;
grabber_get_grid_size(&xgrid, &ygrid);
al_show_mouse(NULL);
grabber_sel_palette(grabber_palette);
if (al_bitmap_color_depth(al_screen) == 8)
al_clear_to_color(al_screen, al_gui_mg_color);
graphiccopy = al_create_bitmap(grabber_graphic->w, grabber_graphic->h);
al_blit(grabber_graphic, graphiccopy, 0, 0, 0, 0, grabber_graphic->w, grabber_graphic->h);
if (al_bitmap_color_depth(al_screen) != 8)
al_clear_to_color(al_screen, al_gui_mg_color);
al_blit(graphiccopy, al_screen, 0, 0, 0, 0, AL_SCREEN_W, AL_SCREEN_H);
pattern = al_create_bitmap(2, 2);
al_put_pixel(pattern, 0, 0, al_gui_bg_color);
al_put_pixel(pattern, 1, 1, al_gui_bg_color);
al_put_pixel(pattern, 0, 1, al_gui_fg_color);
al_put_pixel(pattern, 1, 0, al_gui_fg_color);
do {
al_poll_mouse();
} while (al_mouse_b);
al_set_mouse_range(0, 0, grabber_graphic->w-1, grabber_graphic->h-1);
do {
al_poll_mouse();
x = al_mouse_x;
y = al_mouse_y;
if ((x >= grabber_graphic->w) || (y >= grabber_graphic->h)) {
x = MID(0, x, grabber_graphic->w-1);
y = MID(0, y, grabber_graphic->h-1);
al_position_mouse(x, y);
}
if (!box) {
x = (x / xgrid) * xgrid;
y = (y / ygrid) * ygrid;
}
if ((x != ox) || (y != oy)) {
al_acquire_screen();
al_blit(graphiccopy, al_screen, 0, 0, 0, 0, grabber_graphic->w, grabber_graphic->h);
al_draw_hline(al_screen, 0, grabber_graphic->h, grabber_graphic->w, 0);
al_draw_vline(al_screen, grabber_graphic->w, 0, grabber_graphic->h, 0);
al_drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
if (box) {
al_draw_hline(al_screen, 0, y-1, grabber_graphic->w, 0);
al_draw_vline(al_screen, x-1, 0, grabber_graphic->h, 0);
}
else {
al_draw_hline(al_screen, x-1, y-1, grabber_graphic->w, 0);
al_draw_vline(al_screen, x-1, y-1, grabber_graphic->h, 0);
}
al_drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
sprintf(buf, "%d, %d", x, y);
al_text_mode(-1);
al_draw_rect_fill(al_screen, 0, AL_SCREEN_H-8, AL_SCREEN_W, AL_SCREEN_H, al_gui_fg_color);
al_put_text(al_screen, al_font_8x8, buf, 0, AL_SCREEN_H-8, al_gui_bg_color);
al_release_screen();
ox = x;
oy = y;
}
if (al_key_pressed()) {
switch (al_read_key() >> 8) {
case AL_KEY_UP:
al_position_mouse(al_mouse_x, MAX(al_mouse_y-ygrid, 0));
break;
case AL_KEY_DOWN:
al_position_mouse(al_mouse_x, al_mouse_y+ygrid);
break;
case AL_KEY_RIGHT:
al_position_mouse(al_mouse_x+xgrid, al_mouse_y);
break;
case AL_KEY_LEFT:
al_position_mouse(MAX(al_mouse_x-xgrid, 0), al_mouse_y);
break;
case AL_KEY_ENTER:
case AL_KEY_SPACE:
goto gottheposition;
case AL_KEY_ESC:
goto getmeoutofhere;
}
}
} while (!al_mouse_b);
if (al_mouse_b & 2)
goto getmeoutofhere;
gottheposition:
if (box) {
int xx, yy, ww, hh;
xx = 0;
yy = 0;
datedit_find_character(grabber_graphic, &xx, &yy, &ww, &hh);
while ((ww > 0) && (hh > 0)) {
if ((x > xx) && (x <= xx+ww) &&
(y > yy) && (y <= yy+hh)) {
x = xx+1;
y = yy+1;
w = ww;
h = hh;
goto gotthesize;
}
xx += ww;
datedit_find_character(grabber_graphic, &xx, &yy, &ww, &hh);
}
x = 0;
y = 0;
w = grabber_graphic->w;
h = grabber_graphic->h;
}
else {
using_mouse = (al_mouse_b & 1);
do {
al_poll_mouse();
w = al_mouse_x;
h = al_mouse_y;
if ((w < x) || (w > grabber_graphic->w) || ( h < y) || (h > grabber_graphic->h)) {
w = MID(x, w, grabber_graphic->w);
h = MID(y, h, grabber_graphic->h);
al_position_mouse(w, h);
}
w = ((w - x) / xgrid + 1) * xgrid;
if (x+w > grabber_graphic->w)
w = grabber_graphic->w - x;
h = ((h - y) / ygrid + 1) * ygrid;
if (y+h > grabber_graphic->h)
h = grabber_graphic->h - y;
if ((w != ow) || (h != oh)) {
al_acquire_screen();
al_blit(graphiccopy, al_screen, 0, 0, 0, 0, grabber_graphic->w, grabber_graphic->h);
al_draw_hline(al_screen, 0, grabber_graphic->h, grabber_graphic->w, 0);
al_draw_vline(al_screen, grabber_graphic->w, 0, grabber_graphic->h, 0);
al_drawing_mode(DRAW_MODE_COPY_PATTERN, pattern, 0, 0);
al_draw_hline(al_screen, x-1, y-1, x+w, 0);
al_draw_hline(al_screen, x-1, y+h, x+w, 0);
al_draw_vline(al_screen, x-1, y-1, y+h, 0);
al_draw_vline(al_screen, x+w, y-1, y+h, 0);
al_drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
sprintf(buf, "%d, %d (%dx%d)", x, y, w, h);
al_text_mode(-1);
al_draw_rect_fill(al_screen, 0, AL_SCREEN_H-8, AL_SCREEN_W, AL_SCREEN_H, al_gui_fg_color);
al_put_text(al_screen, al_font_8x8, buf, 0, AL_SCREEN_H-8, al_gui_bg_color);
al_release_screen();
ow = w;
oh = h;
}
if (al_key_pressed()) {
switch (al_read_key() >> 8) {
case AL_KEY_UP:
al_position_mouse(al_mouse_x, MAX(al_mouse_y-ygrid, 0));
break;
case AL_KEY_DOWN:
al_position_mouse(al_mouse_x, al_mouse_y+ygrid);
break;
case AL_KEY_RIGHT:
al_position_mouse(al_mouse_x+xgrid, al_mouse_y);
break;
case AL_KEY_LEFT:
al_position_mouse(MAX(al_mouse_x-xgrid, 0), al_mouse_y);
break;
case AL_KEY_ENTER:
case AL_KEY_SPACE:
goto gotthesize;
case AL_KEY_ESC:
goto getmeoutofhere;
}
}
if (al_mouse_b & 2)
goto getmeoutofhere;
} while (((al_mouse_b) && (using_mouse)) || ((!al_mouse_b) && (!using_mouse)));
}
gotthesize:
if ((w > 0) && (h > 0)) {
bmp = al_create_bitmap_ex(al_bitmap_color_depth(grabber_graphic), w, h);
al_clear_to_color(bmp, bmp->vtable->mask_color);
al_blit(grabber_graphic, bmp, x, y, 0, 0, w, h);
if (dat->type == DAT_RLE_SPRITE) {
spr = al_create_rle_sprite(bmp);
al_destroy_bitmap(bmp);
al_destroy_rle_sprite(dat->dat);
dat->dat = spr;
}
else {
al_destroy_bitmap(dat->dat);
dat->dat = bmp;
}
sprintf(buf, "%d", x);
datedit_set_property(dat, DAT_XPOS, buf);
sprintf(buf, "%d", y);
datedit_set_property(dat, DAT_YPOS, buf);
sprintf(buf, "%d", w);
datedit_set_property(dat, DAT_XSIZ, buf);
sprintf(buf, "%d", h);
datedit_set_property(dat, DAT_YSIZ, buf);
datedit_set_property(dat, DAT_ORIG, grabber_graphic_origin);
datedit_set_property(dat, DAT_DATE, grabber_graphic_date);
}
getmeoutofhere:
if (al_mouse_b)
al_clear_to_color(al_screen, al_gui_mg_color);
al_set_mouse_range(0, 0, AL_SCREEN_W-1, AL_SCREEN_H-1);
al_destroy_bitmap(graphiccopy);
al_destroy_bitmap(pattern);
al_show_mouse(al_screen);
do {
al_poll_mouse();
} while (al_mouse_b);
}
/* checks whether our grab command is allowed at the moment */
static int grabber_query(int popup)
{
AL_DATAFILE *dat = grabber_single_selection();
if ((!dat) || (!grabber_graphic))
return FALSE;
return ((dat->type == DAT_BITMAP) || (dat->type == DAT_RLE_SPRITE) ||
(dat->type == DAT_C_SPRITE) || (dat->type == DAT_XC_SPRITE));
}
/* menu hook for our special grab command */
static int grabber(void)
{
AL_DATAFILE *dat = grabber_single_selection();
if ((!dat) || (!grabber_graphic))
return D_O_K;
if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE))
return D_O_K;
grabbit(dat, FALSE);
datedit_sort_properties(dat->prop);
grabber_select_property(DAT_NAME);
grabber_modified(1);
return D_REDRAW;
}
/* checks whether our box grab command is allowed at the moment */
static int boxgrab_query(int popup)
{
AL_DATAFILE *dat = grabber_single_selection();
if (!dat) {
if (popup)
return FALSE;
else
al_show_alert("You must create and select a single object to", "contain the data before you can box-grab it", NULL, "OK", NULL, 13, 0);
}
else if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE)) {
if (popup)
return FALSE;
else
al_show_alert("You can only box-grab to a bitmap object!", NULL, NULL, "OK", NULL, 13, 0);
}
else if (!grabber_graphic) {
if (popup)
return FALSE;
else
al_show_alert("You must read in a bitmap file", "before you can box-grab data from it", NULL, "OK", NULL, 13, 0);
}
return TRUE;
}
/* menu hook for the box grab command */
static int boxgrab(void)
{
AL_DATAFILE *dat = grabber_single_selection();
if ((!dat) || (!grabber_graphic))
return D_O_K;
if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE))
return D_O_K;
grabbit(dat, TRUE);
datedit_sort_properties(dat->prop);
grabber_select_property(DAT_NAME);
grabber_modified(1);
return D_REDRAW;
}
/* checks whether our ungrab command is allowed at the moment */
static int ungrab_query(int popup)
{
AL_DATAFILE *dat = grabber_single_selection();
if ((!dat) ||
((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE))) {
if (popup)
return FALSE;
else
al_show_alert("Only bitmap objects can be ungrabbed!", NULL, NULL, "OK", NULL, 13, 0);
}
return TRUE;
}
/* menu hook for the ungrab command */
static int ungrab(void)
{
AL_DATAFILE *dat = grabber_single_selection();
if (!dat)
return D_O_K;
if ((dat->type != DAT_BITMAP) && (dat->type != DAT_RLE_SPRITE) &&
(dat->type != DAT_C_SPRITE) && (dat->type != DAT_XC_SPRITE))
return D_O_K;
if (grabber_graphic)
al_destroy_bitmap(grabber_graphic);
if (dat->type == DAT_RLE_SPRITE) {
AL_RLE_SPRITE *spr = (AL_RLE_SPRITE *)dat->dat;
grabber_graphic = al_create_bitmap_ex(spr->color_depth, spr->w, spr->h);
al_clear_bitmap(grabber_graphic);
al_draw_rle_sprite(grabber_graphic, spr, 0, 0);
}
else {
AL_BITMAP *bmp = (AL_BITMAP *)dat->dat;
grabber_graphic = al_create_bitmap_ex(al_bitmap_color_depth(bmp), bmp->w, bmp->h);
al_blit(bmp, grabber_graphic, 0, 0, 0, 0, bmp->w, bmp->h);
}
if (al_bitmap_color_depth(grabber_graphic) == 8)
memcpy(grabber_palette, datedit_current_palette, sizeof(AL_PALETTE));
else
al_generate_optimized_palette(grabber_graphic, grabber_palette, NULL);
al_show_alert("Bitmap data copied to the input buffer", NULL, NULL, "OK", NULL, 13, 0);
return D_O_K;
}
/* hook ourselves into the grabber menu system */
static AL_MENU grabber_menu =
{
"Grab",
grabber,
NULL,
0,
NULL
};
DATEDIT_MENU_INFO datgrab_grabber_menu =
{
&grabber_menu,
grabber_query,
DATEDIT_MENU_OBJECT,
0
};
static AL_MENU boxgrab_menu =
{
"Box Grab\t(ctrl+B)",
boxgrab,
NULL,
0,
NULL
};
DATEDIT_MENU_INFO datgrab_boxgrab_menu =
{
&boxgrab_menu,
boxgrab_query,
DATEDIT_MENU_OBJECT | DATEDIT_MENU_POPUP,
2 /* ctrl+B */
};
static AL_MENU ungrab_menu =
{
"Ungrab",
ungrab,
NULL,
0,
NULL
};
DATEDIT_MENU_INFO datgrab_ungrab_menu =
{
&ungrab_menu,
ungrab_query,
DATEDIT_MENU_OBJECT | DATEDIT_MENU_POPUP,
0
};
See more files for this project here