home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
g
/
gs241j11.zip
/
ZIMPATH.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-05-02
|
6KB
|
329 lines
/*
* Bitmap Image Utility Routines
*
* Copyright (C) 1991 Norio Katayama.
* Aug. 28, 1991 Programmed by N.Katayama (katayama@nacsis.ac.jp)
*/
#include "memory_.h"
#include "ghost.h"
#include "oper.h"
#include "errors.h"
#include "gsmatrix.h"
#include "gspath.h"
#include "state.h"
#include "store.h"
/* Forward declaration */
int gs_imagebbox(P6(int, int, int, gs_matrix *, byte *, gs_rect *));
private int imagepath(P5(int, int, int, gs_matrix *, byte *));
private int trace_path(P6(byte *bp, int, int, int, gs_matrix *, int));
/*
* imagepath
*/
int
zimagepath(register os_ptr op)
{
int code;
gs_matrix mat;
check_type(op[-4], t_integer);
check_type(op[-3], t_integer);
check_type(op[-2], t_boolean);
if((code = read_matrix(op - 1, &mat)) < 0)
return code;
check_type(*op, t_string);
if((code =
imagepath((int)op[-4].value.intval, (int)op[-3].value.intval,
(int)op[-2].value.index, &mat, op[0].value.bytes)) < 0)
return code;
pop(5);
return 0;
}
/*
* imagebbox
*/
int
zimagebbox(register os_ptr op)
{
int code;
gs_rect bbox;
gs_matrix mat;
check_type(op[-4], t_integer);
check_type(op[-3], t_integer);
check_type(op[-2], t_boolean);
if((code = read_matrix(op - 1, &mat)) < 0)
return code;
check_type(*op, t_string);
if((code =
gs_imagebbox((int)op[-4].value.intval, (int)op[-3].value.intval,
(int)op[-2].value.index, &mat, op[0].value.bytes,
&bbox)) < 0)
return code;
pop(1);
op --;
make_real(op - 3, bbox.p.x);
make_real(op - 2, bbox.p.y);
make_real(op - 1, bbox.q.x);
make_real(op, bbox.q.y);
return 0;
}
/* -------- Initialization procedure -------- */
op_def zimpath_op_defs[] = {
{"5imagepath", zimagepath},
{"5imagebbox", zimagebbox},
op_def_end(0)
};
/* -------- Library routines -------- */
/*
* Retrieve the boundary box of bitmap image
*/
int
gs_imagebbox(int width, int height, int bool,
gs_matrix *pmat, byte *image, gs_rect *pbbox)
{
int code, x, y, offx, offy;
int width8 = width / 8 + (width % 8 ? 1 : 0);
int minx, miny, maxx, maxy;
byte mask;
gs_matrix imat;
minx = width;
maxx = 0;
miny = height;
maxy = 0;
for(y=0, offy=0; y<height; y++, offy+=width8) {
mask = 0x80;
for(x=0, offx=offy; x<width; x++) {
if((image[offx] & mask) ? bool : !bool) {
if(x < minx)
minx = x;
if(x > maxx)
maxx = x;
if(y < miny)
miny = y;
if(y > maxy)
maxy = y;
}
if((mask = (mask >> 1)) == 0) {
mask = 0x80;
offx ++;
}
}
}
if((code = gs_matrix_invert(pmat, &imat)) < 0)
return code;
gs_point_transform((floatp)minx, (floatp)miny, &imat, &pbbox->p);
gs_point_transform((floatp)maxx+1, (floatp)maxy+1, &imat, &pbbox->q);
if(pbbox->p.x > pbbox->q.x) {
floatp temp;
temp = pbbox->p.x;
pbbox->p.x = pbbox->q.x;
pbbox->q.x = temp;
}
if(pbbox->p.y > pbbox->q.y) {
floatp temp;
temp = pbbox->p.y;
pbbox->p.y = pbbox->q.y;
pbbox->q.y = temp;
}
return 0;
}
/* -------- Internal routines -------- */
/*
* imagepath
*/
#define BIT_ON 0x01
#define WEST_EDGE_DONE 0x02
#define FIRST_BIT 0x04
#define moveto(x, y) { gs_point pt; \
gs_point_transform((float)(x)/4.0, (float)(y)/4.0, pmat, &pt); \
gs_moveto(igs, pt.x, pt.y); }
#define lineto(x, y) { gs_point pt; \
gs_point_transform((float)(x)/4.0, (float)(y)/4.0, pmat, &pt); \
gs_lineto(igs, pt.x, pt.y); }
#define closepath() gs_closepath(igs)
private int
imagepath(int width, int height, int fine, gs_matrix *pmat, byte *image)
{
byte *bitmap, *bpx, *bpy;
int code, x, y, offx, offy;
int width8 = width / 8 + (width % 8 ? 1 : 0);
int bwidth = width + 2;
int bheight = height + 2;
int bsize = bwidth*bheight;
byte mask;
gs_matrix imat;
if((code = gs_matrix_invert(pmat, &imat)) < 0)
return code;
if((bitmap = (byte *)gs_malloc(1, bsize, "imagepath(bitmap)")) == 0)
return e_VMerror;
memset(bitmap, 0, bsize);
for(y=0, bpy=bitmap+bwidth, offy=0; y<height;
y++, bpy+=bwidth, offy+=width8) {
mask = 0x80;
for(x=0, bpx=bpy+1, offx=offy; x<width; x++, bpx++) {
if(image[offx] & mask)
*bpx = 1;
if((mask = (mask >> 1)) == 0) {
mask = 0x80;
offx ++;
}
}
}
for(y=0, bpy=bitmap+bwidth; y<height; y++,bpy+=bwidth) {
for(x=0, bpx=bpy+1; x<width; x++, bpx++) {
if(*(bpx - 1) == 0 && *bpx == BIT_ON)
trace_path(bpx, bwidth, x, y, &imat, fine);
}
}
gs_free((char *)bitmap, 1, bsize, "imagepath(bitmap)");
return 0;
}
private int
trace_path(byte *bp, int bwidth, int x, int y, gs_matrix *pmat, int fine)
{
#define EAST 0
#define SOUTH 1
#define WEST 2
#define NORTH 3
static int bd[] = {
1, /* east */
-1, /* south */
-1, /* west */
1, /* north */
};
static struct xy {
int x, y;
} xy[] = {
{ 1, 0 }, /* east */
{ 0, -1 }, /* south */
{ -1, 0 }, /* west */
{ 0, 1 }, /* north */
};
int edge = WEST;
int dir = NORTH;
int straight = 0;
int ex, ey, dx, dy;
int bd_edge, bd_dir;
int temp;
bd[NORTH] = bwidth;
bd[SOUTH] = -bwidth;
x = x*4;
y = y*4 + 2;
moveto(x, y);
*bp |= FIRST_BIT;
do {
if(edge == WEST)
*bp |= WEST_EDGE_DONE;
ex = xy[edge].x;
ey = xy[edge].y;
dx = xy[dir].x;
dy = xy[dir].y;
bd_edge = bd[edge];
bd_dir = bd[dir];
if(*(bp + bd_dir + bd_edge)) {
if(fine) {
if(*(bp + bd_dir)) {
x += dx;
y += dy;
lineto(x, y);
x += dx + ex;
y += dy + ey;
lineto(x, y);
x += ex;
y += ey;
}
else {
lineto(x, y);
x += (dx << 1) + (ex << 1);
y += (dy << 1) + (ey << 1);
lineto(x, y);
}
}
else {
if(straight)
lineto(x, y);
x += (dx << 1) + (ex << 1);
y += (dy << 1) + (ey << 1);
lineto(x, y);
}
bp += bd_dir + bd_edge;
temp = edge;
edge = (dir + 2) & 3;
dir = temp;
straight = 0;
}
else if(*(bp + bd_dir)) {
x += dx << 2;
y += dy << 2;
bp += bd_dir;
straight = 1;
}
else {
if(fine) {
x += dx;
y += dy;
lineto(x, y);
x += dx - ex;
y += dy - ey;
lineto(x, y);
x += - ex;
y += - ey;
}
else {
if(straight)
lineto(x, y);
x += (dx << 1) - (ex << 1);
y += (dy << 1) - (ey << 1);
lineto(x, y);
}
temp = edge;
edge = dir;
dir = (temp + 2) & 3;
straight = 0;
}
} while( edge != WEST || !(*bp & FIRST_BIT));
closepath();
*bp &= ~FIRST_BIT;
return 0;
}