所给代码只用于说明算法,不要直接使用,使用时需增加各种边界检测代码。例子图象只包含直线,但对曲线一样适用,且适合实时处理。主要思想集中在dot()函数中。对算法进行文字说明需要制作一些说明图片,暂时无法完成,以后可能会加上。
效果图象
灰度索引位图
#define imageWidth 320 #define imageHeight 240
BYTE grayBuf[64*64];
//灰度索引数组,存贮的内容见灰度索引位图,既可以由文件读取,也可以由软件生成
//画点函数,由其它函数调用,提供浮点坐标,buf为图象缓冲区 void dot(BYTE *buf,float fx,float fy) { int j,k; int x,y,dx,dy,dx1,dy1; BYTE *p = buf,bt; x = (int)fx , y = (int)fy; dx = (int)(((float)x - fx)*16); dy = (int)(((float)y - fy)*16); p += y*imageWidth+x; for(j=-3;j<4;j++) // 画一个7*7的正方形区域 { for(k=-3;k<4;k++) { dx1 = k*16+dx; dy1 = j*16+dy; if(dx1 < 0) dx1 = -dx1; if(dy1 < 0) dy1 = -dy1; bt = grayBuf[dy1*64+dx1]; if(*p > bt) *p = bt; p++; } p += imageWidth-7; } }
void line(BYTE *buf,int x1,int y1,int x2,int y2) // 画线函数,采用浮点计算,算法相当简单 { int dx,dy,i; float fx,fy,fdx,fdy; if(x1 > x2) dx = x1 - x2; else dx = x2 - x1; if(y1 > y2) dy = y1 - y2; else dy = y2 - y1; fdx = (float)(x2 - x1); fdy = (float)(y2 - y1); fx = (float)x1; fy = (float)y1; if(dx > dy) { fdx = fdx/dx; fdy = fdy/dx; for(i=0;i<dx;i++) { dot(buf,fx,fy); fx += fdx; fy += fdy; } } else { fdx = fdx/dy; fdy = fdy/dy; for(i=0;i<dy;i++) { dot(buf,fx,fy); fx += fdx; fy += fdy; } } }
void show() // 使用directX,将workBuf中的内容显示在屏幕上 { DDSURFACEDESC ddsd; HRESULT ddrval; ddsd.dwSize = sizeof(ddsd); BYTE *p1,*p2; CGif89a gif("e:\\gray.gif",TRUE); if(!gif) return; LPCFRAME fm = gif.getNextFrame(); LPCGLOBAL_INFO gi = gif.getGlobalInfo(); p1 = fm->dataBuf; p2 = grayBuf; for(int j=0;j<fm->imageHeight;j++) { for(int k=0;k<fm->imageWidth;k++) { *p2++ = gi->gColorTable[(*p1++)*3]; } }
workBuf = new unsigned char[320*240]; if(workBuf == NULL) return; memset(workBuf,255,320*240);
// dot(workBuf,100.0,100); // dot(workBuf,110.2,100); // dot(workBuf,120.3,100); // dot(workBuf,130.4,100);
line(workBuf,20,20,300,60); line(workBuf,20,40,300,160); line(workBuf,20,60,200,220); line(workBuf,20,80,80,220);
DDBLTFX ddbltfx; ddbltfx.dwSize = sizeof(ddbltfx); ddbltfx.dwFillColor = 0x0000; lpDDSBack->Blt(NULL,NULL,NULL,DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx); while ((ddrval = lpDDSBack->Lock(NULL, &ddsd, 0, NULL)) == DDERR_WASSTILLDRAWING) ; if( ddrval == DD_OK ) { UINT imgX,imgY,dspX,dspY,dspWidth,dspHeight,j,k; WORD *p; if(imageWidth > 800) dspWidth = 800,dspX = 0,imgX = (imageWidth-800)/2; else dspWidth = imageWidth,imgX = 0,dspX = (800-imageWidth)/2; if(imageHeight > 600) dspHeight = 600,dspY = 0,imgY = (imageHeight-600)/2; else dspHeight = imageHeight,imgY = 0,dspY = (600-imageHeight)/2; p = (WORD*)ddsd.lpSurface; p2 = workBuf; p += 800*dspY+dspX; p2 += imageWidth*imgY+imgX; for(j=0;j<dspHeight;j++) { for(k=0;k<dspWidth;k++) { p[k] = (*RGBto16bit)(p2[k],p2[k],p2[k]); } p += 800; p2 += imageWidth; } lpDDSBack->Unlock(NULL); } while( 1 ) { ddrval = lpDDSPrimary->Flip( NULL, 0 ); if( ddrval == DD_OK ) { break; } if( ddrval == DDERR_SURFACELOST ) { ddrval = lpDDSPrimary->Restore(); if( ddrval != DD_OK ) break; } if( ddrval != DDERR_WASSTILLDRAWING ) break; } delete[] workBuf; } |