求图像边界点坐标c语言,三、Windows图像处理—画点和线(边框函数)
下面我想討論的是Arc函數(shù),它繪制橢圓曲線。然而,如果不先討論一下Ellipse函數(shù),那么Arc函數(shù)將難以理解;而如果不先討論Rectangle函數(shù),那么Ellipse函數(shù)又將難以理解;而如果討論Ellipse和Rectangle函數(shù),那么我又會討論RoundRect、Chord和Pie函數(shù)。
問題在于,Rectangle、Ellipse、RoundRect、Chord和Pie函數(shù)嚴格來說不是畫線函數(shù)。沒錯,這些函數(shù)是在畫線,但它們同時又填入畫刷填入一個封閉區(qū)域。這個畫刷內定為白色,因此當您第一次使用這些函數(shù)時,您可能不會注意到它們不只是畫線。嚴格地說,這些函數(shù)屬于后面「填入區(qū)域」的小節(jié),不過,我還是在這里討論它們。
上面提到的函數(shù)有一個共同特性,即它們都是依據一個矩形邊界框來繪圖的。您定義一個包含該對象的框,即「邊界框(bounding box)」;Windows就在這個框內畫出該物件。
這些函數(shù)中最簡單的就是畫一個矩形:
Rectangle (hdc, xLeft, yTop, xRight, yBottom) ;
點(xLeft, yTop)是矩形的左上角,(xRight, yBottom)是矩形的右下角。用函數(shù)Rectangle畫出的圖形如圖5-6所示,矩形的邊總是平行于顯示器的水平和垂直邊。
以前寫過圖形程序的程序寫作者熟悉圖素偏差的問題。有些圖形系統(tǒng)畫出的圖形包含右坐標和底坐標,而有些則只畫到(而不包含)右坐標和底坐標。Windows采用后一種方法,不過有一種更簡單的方法來思考這個問題。
考慮下面的函數(shù)呼叫:
Rectangle (hdc, 1, 1, 5, 4) ;
上面我們提到,Windows在邊界框內畫圖。可以將顯示器想象成一個網格,其中,每個圖素都在一個網格單元內。邊界框畫在網格上,然后在邊界框內畫矩形,下面說明了圖形畫出來時的樣子:
我以前提到過,Rectangle嚴格地說不是畫線函數(shù),GDI也填入封閉區(qū)域。然而,因為內定用白色填入區(qū)域,因此GDI填入區(qū)域并不明顯。
您知道了如何畫矩形,也就知道了如何畫橢圓,因為它們使用的參數(shù)都是相同的:
Ellipse (hdc, xLeft, yTop, xRight, yBottom) ;
用Ellipse函數(shù)畫出的圖形如圖5-7所示(加上了虛線構成的邊界框)。
畫圓角矩形的函數(shù)使用與函數(shù)Rectangle及Ellipse函數(shù)相同的邊界框,還包含另外兩個參數(shù):
RoundRect (hdc, xLeft, yTop, xRight, yBottom,
xCornerEllipse, yCornerEllipse) ;
用這個函數(shù)畫出的圖形如5-8所示。
Windows使用一個小橢圓來畫圓角,這個橢圓的寬為xCornerEllipse,高為yCornerEllipse。可以想象這個小橢圓分為了四個部分,一個象限一個,每個剛好用在矩形的一個角上。xCornerEllipse和yCornerEllipse的值越大,角就越明顯。如果xCornerEllipse等于xLeft與xRight的差,且yCornerEllipse等于yTop與yBottom的差,那么RoundRect函數(shù)將畫出一個橢圓。
在繪制圖5-8所示的圓角矩形時,用了下面的公式來計算角上橢圓的尺寸。
xCornerEllipse = (xRight - xLeft) / 4 ;
yCornerEllipse = (yBottom- yTop) / 4 ;
這是一種簡單的方法,但是結果看起來有點不對勁,因為角的彎曲部分在矩形長的一邊要大些。要矯正這一問題,您可以讓xCornerEllipse與yCornerEllipse的值相等。
Arc、Chord和Pie函數(shù)都只要相同的參數(shù):
Arc(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
Chord (hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
Pie(hdc, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd) ;
用Arc函數(shù)畫出的線如圖5-9所示;用Chord和Pie函數(shù)畫出的線分別如圖5-10和5-11所示。Windows用一條假想的線將(xStart, yStart)與橢圓的中心連接,從該線與邊界框的交點開始,Windows按反時針方向,沿著橢圓畫一條弧。Windows還用另一條假想的線將(xEnd,yEnd)與橢圓的中心連接,在該線與邊界框的交點處,Windows停止畫弧。
對于Arc函數(shù),這樣就結束了。因為弧只是一條橢圓形的線而已,而不是一個填入區(qū)域。對于Chord函數(shù),Windows連接弧線的端點。而對于Pie函數(shù),Windows將弧的兩個端點與橢圓的中心相連接。弦與扇形圖的內部以目前畫刷填入。
您可能不太明白在Arc、Chord和Pie函數(shù)中開始和結束位置的用法,為什么不簡單地在橢圓的周在線指定開始和結束點呢?是的,您可以這么做,但是您將不得不算出這些點。Windows的方法在不要求這種精確性的條件下,卻完成了相同的工作。
程序5-3 LINEDEMO畫一個矩形、一個橢圓、一個圓角矩形和兩條線段,不過不是按這一順序。程序表明了定義封閉區(qū)域的函數(shù)實際上對這些區(qū)域進行了填入,因為在橢圓后面的線被遮住了,結果如圖5-12中所示。
程序5-3 LINEDEMO
LINEDEMO.C
/*---------------------------------------------------------
LINEDEMO.C -- Line-Drawing Demonstration Program
(c) Charles Petzold, 1998
----------------------------------------------------------*/
#include
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("LineDemo") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc= WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground= (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName= NULL ;
wndclass.lpszClassName= szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("Line Demonstration"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxClient, cyClient ;
HDC hdc ;
PAINTSTRUCT ps ;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
Rectangle (hdc, cxClient / 8, cyClient / 8,
7 * cxClient / 8, 7 * cyClient / 8) ;
MoveToEx (hdc, 0, 0, NULL) ;
LineTo (hdc, cxClient, cyClient) ;
MoveToEx (hdc, 0, cyClient, NULL) ;
LineTo (hdc, cxClient, 0) ;
Ellipse (hdc, cxClient / 8, cyClient / 8,
7 * cxClient / 8, 7 * cyClient / 8) ;
RoundRect (hdc, cxClient / 4, cyClient / 4,
3 * cxClient / 4, 3 * cyClient / 4,
cxClient / 4, cyClient / 4) ;
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
總結
以上是生活随笔為你收集整理的求图像边界点坐标c语言,三、Windows图像处理—画点和线(边框函数)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用python实现一个自动保存复制图片的
- 下一篇: 为什么医疗行业需要完整的API管理系统?