533 lines
12 KiB
C++
533 lines
12 KiB
C++
|
|
/***********************************************************************
|
|
*
|
|
* BitMap Openration modules
|
|
*
|
|
* Copyright (c) 1997-1999 Microsoft Corporation.
|
|
*
|
|
***********************************************************************
|
|
* BitMap Specifications
|
|
*
|
|
* Coordinate
|
|
* (0,0) X (255,0)
|
|
* +--------------*
|
|
* |
|
|
* Y |
|
|
* |
|
|
* |
|
|
* |
|
|
* *
|
|
* (0,255)
|
|
* Memory Boundary : Word Boundary
|
|
*
|
|
* Entry List
|
|
* BMPDefine,
|
|
* BMPZoomUp,
|
|
* BMPOutline
|
|
***********************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include "vdata.h"
|
|
#include "extfunc.h"
|
|
#define BMPWIDMAX 256
|
|
#define BMPDEPMAX 256
|
|
|
|
#define BMPMAX 8
|
|
|
|
struct BMPDef {
|
|
int width, depth;
|
|
unsigned char *buf;
|
|
int bWid;
|
|
};
|
|
|
|
|
|
void BMPInit(void);
|
|
int BMPDefine(unsigned char *buf,int xWid,int yWid);
|
|
int BMPFreDef(int bmpno);
|
|
int BMPMkCont(int BMPNo,int wkBMP,int refBMP,int lsthdl);
|
|
static int SearchON(int BMPNo,int x,int y);
|
|
static int outline(int BMPNo,int x,int y,int lsthdl,int wkBMP,int refBMP);
|
|
static int ContributeOutside(int BMPNo,int wkBMP,struct vecdata *org,int lsthdl);
|
|
static int ContributeInside(int BMPNo,int wkBMP,struct vecdata *org,int lsthdl);
|
|
int rdot(int BMP,int x,int y);
|
|
void wdot(int BMP,int x,int y,int onoff);
|
|
int ReverseRight(int BMPNo,int x,int y);
|
|
static void cpybuf(int src,int dst);
|
|
int BMPReverse(int bmpNo);
|
|
int BMPClear(int bmpNo);
|
|
|
|
struct BMPDef BMPTbl[BMPMAX]={0};
|
|
|
|
/* On Bit Most left position */
|
|
static unsigned char bitptbl[256] = {
|
|
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
static unsigned char wmaskB[8]={
|
|
0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01
|
|
};
|
|
static unsigned char rightmask[8] = {
|
|
0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01
|
|
};
|
|
/***********************************************************************
|
|
* BMP Initialize
|
|
*/
|
|
/* */ void
|
|
/* */ BMPInit()
|
|
/*
|
|
* returns; none
|
|
***********************************************************************/
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0; i < BMPMAX; i++)
|
|
BMPTbl[i].buf=(unsigned char *)0;
|
|
return;
|
|
}
|
|
/***********************************************************************
|
|
* Define BitMap
|
|
*/
|
|
/* */ int
|
|
/* */ BMPDefine(
|
|
/* */ unsigned char *buf,
|
|
/* */ int xWid,
|
|
/* */ int yWid)
|
|
/*
|
|
* returns : 0-(BMPMAX-1), -1
|
|
***********************************************************************/
|
|
{
|
|
int i;
|
|
|
|
/* Check Size */
|
|
if ( xWid > BMPWIDMAX || xWid < 0
|
|
|| yWid > BMPWIDMAX || yWid < 0)
|
|
goto ERET;
|
|
|
|
/* Set Define */
|
|
for ( i = 0; i < BMPMAX; i++) {
|
|
if (BMPTbl[i].buf==(unsigned char *)0) {
|
|
BMPTbl[i].bWid = (xWid + 15)/16*2;
|
|
BMPTbl[i].width = xWid;
|
|
BMPTbl[i].depth = yWid;
|
|
BMPTbl[i].buf = buf;
|
|
|
|
return(i);
|
|
}
|
|
}
|
|
ERET:
|
|
return( -1);
|
|
}
|
|
/***********************************************************************
|
|
* Free BMP define
|
|
*/
|
|
/* */ int
|
|
/* */ BMPFreDef( int bmpno)
|
|
/*
|
|
* returns : 0, -1
|
|
***********************************************************************/
|
|
{
|
|
if ( bmpno < 0 || bmpno >= BMPMAX)
|
|
return -1;
|
|
else {
|
|
BMPTbl[bmpno].buf = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
/***********************************************************************
|
|
* Get Outline
|
|
*/
|
|
/* */ int
|
|
/* */ BMPMkCont( int BMPNo, int wkBMP, int refBMP, int lsthdl)
|
|
/*
|
|
* returns : Number of Contour, -1
|
|
* REMARKS : Used BMP be destroyed
|
|
***********************************************************************/
|
|
{
|
|
int x, y;
|
|
int ncont;
|
|
int sts;
|
|
|
|
VDNew( lsthdl);
|
|
sts = 0;
|
|
ncont = 0;
|
|
cpybuf( BMPNo, wkBMP);
|
|
cpybuf( BMPNo, refBMP);
|
|
for ( y = 0; y < BMPTbl[BMPNo].depth; y++) {
|
|
x = 0;
|
|
while ( (x = SearchON( wkBMP, x, y)) <BMPTbl[BMPNo].width) {
|
|
if ((sts = outline( BMPNo, x, y,lsthdl, wkBMP, refBMP))<0)
|
|
goto RET;
|
|
|
|
ncont++;
|
|
x++;
|
|
}
|
|
}
|
|
sts = ncont;
|
|
cpybuf(refBMP,BMPNo);
|
|
RET:
|
|
return( sts);
|
|
}
|
|
/***********************************************************************
|
|
* Search ON dot
|
|
*/
|
|
/* */ static int
|
|
/* */ SearchON( int BMPNo, int x, int y)
|
|
/*
|
|
* returns : found position, Width(Not Found case)
|
|
***********************************************************************/
|
|
{
|
|
int bpos; /* byte position */
|
|
int sbitpos; /* Start Byte Bit position */
|
|
unsigned char *p;
|
|
|
|
bpos = x/8;
|
|
sbitpos = x % 8;
|
|
p = BMPTbl[BMPNo].buf + BMPTbl[BMPNo].bWid*y + bpos;
|
|
/* First Byte */
|
|
if ( *p & rightmask[sbitpos])
|
|
x = bpos*8 + bitptbl[(int)(*p& rightmask[sbitpos])];
|
|
else {
|
|
bpos++;
|
|
x = bpos*8;
|
|
for ( ; bpos < BMPTbl[BMPNo].bWid; bpos++, x+=8) {
|
|
p++;
|
|
if (*p) {
|
|
x += bitptbl[(int)*p];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return( x);
|
|
}
|
|
/***********************************************************************
|
|
* make outline data
|
|
*/
|
|
/* */ static int
|
|
/* */ outline(
|
|
/* */ int BMPNo,
|
|
/* */ int x,
|
|
/* */ int y,
|
|
/* */ int lsthdl,
|
|
/* */ int wkBMP,
|
|
/* */ int refBMP)
|
|
/*
|
|
* returns : 0, -1
|
|
**********************************************************************/
|
|
{
|
|
int inout;
|
|
struct vecdata vd;
|
|
int sts;
|
|
|
|
/* Check Inside/Outside */
|
|
if ( rdot( refBMP, x, y) ==rdot( wkBMP, x, y)) /* OUTSIDE */
|
|
inout = 0;
|
|
else /* INSIDE */
|
|
inout = 1;
|
|
|
|
/* copy buffer */
|
|
cpybuf( wkBMP, BMPNo);
|
|
/* contribute */
|
|
vd.x = (short)x;
|
|
vd.y = (short)y;
|
|
vd.atr = 0;
|
|
if ( inout==0)
|
|
sts = ContributeOutside( BMPNo, wkBMP, &vd, lsthdl);
|
|
else
|
|
sts = ContributeInside( BMPNo, wkBMP, &vd, lsthdl);
|
|
return( sts);
|
|
}
|
|
/***********************************************************************
|
|
* Contribute Outside Contour
|
|
*/
|
|
/* */ static int
|
|
/* */ ContributeOutside(int BMPNo, int wkBMP, struct vecdata *org, int lsthdl)
|
|
/*
|
|
* returns : 0, -1
|
|
* Direction 2
|
|
* |
|
|
* |
|
|
* 3-------+-------1
|
|
* |
|
|
* |
|
|
* 0
|
|
***********************************************************************/
|
|
{
|
|
int orgx, orgy;
|
|
struct vecdata vd;
|
|
int dir;
|
|
|
|
orgx = org->x;
|
|
orgy = org->y;
|
|
vd = *org;
|
|
dir = 0;
|
|
/*
|
|
if (ReverseRight( wkBMP, vd.x, vd.y))
|
|
return( -1);
|
|
*/
|
|
do {
|
|
if (VDSetData( lsthdl, &vd))
|
|
return(-1);
|
|
switch( dir) {
|
|
case 0:
|
|
if (ReverseRight( wkBMP, vd.x, vd.y))
|
|
return( -1);
|
|
vd.y++;
|
|
if ( rdot( BMPNo, vd.x-1, vd.y))
|
|
dir = 3;
|
|
else if ( rdot( BMPNo, vd.x, vd.y))
|
|
dir = 0;
|
|
else dir = 1;
|
|
break;
|
|
case 1:
|
|
vd.x++;
|
|
if ( rdot( BMPNo, vd.x, vd.y))
|
|
dir = 0;
|
|
else if ( rdot( BMPNo, vd.x, vd.y-1))
|
|
dir = 1;
|
|
else dir = 2;
|
|
break;
|
|
case 2:
|
|
vd.y--;
|
|
if (ReverseRight( wkBMP, vd.x, vd.y))
|
|
return( -1);
|
|
if ( rdot( BMPNo, vd.x, vd.y-1))
|
|
dir = 1;
|
|
else if ( rdot( BMPNo, vd.x-1, vd.y-1))
|
|
dir = 2;
|
|
else dir = 3;
|
|
break;
|
|
case 3:
|
|
vd.x--;
|
|
if ( rdot( BMPNo, vd.x-1, vd.y-1))
|
|
dir = 2;
|
|
else if ( rdot( BMPNo, vd.x-1, vd.y))
|
|
dir = 3;
|
|
else dir = 0;
|
|
break;
|
|
}
|
|
|
|
} while( vd.x!=orgx || vd.y != orgy);
|
|
VDClose(lsthdl);
|
|
return( 0);
|
|
}
|
|
/***********************************************************************
|
|
* Contribute Outside Contour
|
|
*/
|
|
/* */ static int
|
|
/* */ ContributeInside( int BMPNo, int wkBMP, struct vecdata *org, int lsthdl)
|
|
/*
|
|
* returns : 0, -1
|
|
***********************************************************************/
|
|
{
|
|
int orgx, orgy;
|
|
struct vecdata vd;
|
|
int dir;
|
|
|
|
orgx = org->x;
|
|
orgy = org->y;
|
|
vd = *org;
|
|
dir = 1;
|
|
do {
|
|
if (VDSetData( lsthdl, &vd))
|
|
return(-1);
|
|
switch( dir) {
|
|
case 0:
|
|
if (ReverseRight( wkBMP, vd.x, vd.y))
|
|
return( -1);
|
|
vd.y++;
|
|
if ( rdot( BMPNo, vd.x-1, vd.y)==0) /* right */
|
|
dir = 3;
|
|
else if ( rdot( BMPNo, vd.x, vd.y)==0) /* left */
|
|
dir = 0;
|
|
else dir = 1;
|
|
break;
|
|
case 1:
|
|
vd.x++;
|
|
if ( rdot( BMPNo, vd.x, vd.y)==0) /* right */
|
|
dir = 0;
|
|
else if ( rdot( BMPNo, vd.x, vd.y-1)==0) /* left */
|
|
dir = 1;
|
|
else dir = 2;
|
|
break;
|
|
case 2:
|
|
vd.y--;
|
|
if (ReverseRight( wkBMP, vd.x, vd.y))
|
|
return( -1);
|
|
if ( rdot( BMPNo, vd.x, vd.y-1)==0)
|
|
dir = 1;
|
|
else if ( rdot( BMPNo, vd.x-1, vd.y-1)==0)
|
|
dir = 2;
|
|
else dir = 3;
|
|
break;
|
|
case 3:
|
|
vd.x--;
|
|
if ( rdot( BMPNo, vd.x-1, vd.y-1)==0)
|
|
dir = 2;
|
|
else if ( rdot( BMPNo, vd.x-1, vd.y)==0)
|
|
dir = 3;
|
|
else dir = 0;
|
|
break;
|
|
}
|
|
} while( vd.x!=orgx || vd.y != orgy);
|
|
VDClose(lsthdl);
|
|
|
|
return( 0);
|
|
}
|
|
/***********************************************************************
|
|
* Read Dot
|
|
*/
|
|
/* */ int
|
|
/* */ rdot( int BMP, int x, int y)
|
|
/*
|
|
* returns : 0, nonzero
|
|
***********************************************************************/
|
|
{
|
|
unsigned char *radd;
|
|
int rbit;
|
|
int onoff;
|
|
|
|
if ( x < 0 || y < 0 || x>=BMPTbl[BMP].width ||y>=BMPTbl[BMP].depth)
|
|
return( 0);
|
|
|
|
radd = BMPTbl[BMP].buf + BMPTbl[BMP].bWid*y + x/8;
|
|
rbit = x % 8;
|
|
onoff = (int)(wmaskB[rbit] & *radd);
|
|
return onoff;
|
|
}
|
|
/***********************************************************************
|
|
* Write Dot
|
|
*/
|
|
/* */ void
|
|
/* */ wdot( int BMP, int x, int y, int onoff)
|
|
/*
|
|
* returns : none
|
|
***********************************************************************/
|
|
{
|
|
unsigned char *radd;
|
|
int rbit;
|
|
|
|
if ( x < 0 || y < 0 || x>=BMPTbl[BMP].width ||y>=BMPTbl[BMP].depth)
|
|
return;
|
|
|
|
radd = BMPTbl[BMP].buf + BMPTbl[BMP].bWid*y + x/8;
|
|
rbit = x % 8;
|
|
|
|
if ( onoff) *radd |= wmaskB[rbit];
|
|
else *radd &= ~wmaskB[rbit];
|
|
return;
|
|
}
|
|
/***********************************************************************
|
|
* Reverse right side ( Edge fill method)
|
|
*/
|
|
/* */ int
|
|
/* */ ReverseRight( int BMPNo, int x, int y)
|
|
/*
|
|
* returns : 0, -1
|
|
***********************************************************************/
|
|
{
|
|
int rb;
|
|
int bitp;
|
|
unsigned char *wp;
|
|
|
|
if ( BMPNo < 0 || BMPNo >= BMPMAX)
|
|
return 0;
|
|
if ( x < 0 || x >= BMPTbl[BMPNo].width
|
|
|| y < 0 || y >= BMPTbl[BMPNo].depth)
|
|
return 0;
|
|
rb = BMPTbl[BMPNo].bWid - x/8 -1;
|
|
bitp = x%8;
|
|
wp = BMPTbl[BMPNo].buf + y*BMPTbl[BMPNo].bWid + x/8;
|
|
|
|
/* First Byte */
|
|
*wp ^= rightmask[bitp];
|
|
|
|
/* to right limit */
|
|
while( rb-->0) {
|
|
wp++;
|
|
*wp = (unsigned char)~(*wp);
|
|
}
|
|
return ( 0);
|
|
}
|
|
/***********************************************************************
|
|
* Copy Buffer
|
|
*/
|
|
/* */ static void
|
|
/* */ cpybuf( int src, int dst)
|
|
/*
|
|
* returns : none
|
|
***********************************************************************/
|
|
{
|
|
int siz;
|
|
|
|
if ( src < 0 || src >= BMPMAX)
|
|
return;
|
|
if ( dst < 0 || dst >= BMPMAX)
|
|
return;
|
|
siz = BMPTbl[src].bWid * BMPTbl[src].depth;
|
|
memcpy( BMPTbl[dst].buf, BMPTbl[src].buf, siz);
|
|
}
|
|
/***********************************************************************
|
|
* Reverse bitmap
|
|
*/
|
|
/* */ int
|
|
/* */ BMPReverse( int bmpNo)
|
|
/*
|
|
* returns : none
|
|
***********************************************************************/
|
|
{
|
|
int siz;
|
|
char *buf;
|
|
|
|
if ( bmpNo < 0 || bmpNo >= BMPMAX)
|
|
return -1;
|
|
else if (BMPTbl[bmpNo].buf==(unsigned char *)0)
|
|
return -1;
|
|
else {
|
|
siz = BMPTbl[bmpNo].bWid * BMPTbl[bmpNo].depth;
|
|
buf = (char *)BMPTbl[bmpNo].buf;
|
|
while ( siz-->0) {
|
|
*buf = (char)~*buf;
|
|
buf++;
|
|
}
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
/***********************************************************************
|
|
* Clear BMP
|
|
*/
|
|
/* */ int
|
|
/* */ BMPClear( int bmpNo)
|
|
/*
|
|
* returns : 0,-1
|
|
***********************************************************************/
|
|
{
|
|
int siz;
|
|
|
|
if ( bmpNo < 0 || bmpNo >= BMPMAX)
|
|
return -1;
|
|
else if (BMPTbl[bmpNo].buf==(unsigned char *)0)
|
|
return -1;
|
|
siz = BMPTbl[bmpNo].bWid * BMPTbl[bmpNo].depth;
|
|
memset( BMPTbl[bmpNo].buf, 0, siz);
|
|
return 0;
|
|
}
|
|
|
|
/* EOF */
|