图形与图像编程(二)-基础图像技术

来源:互联网 发布:软件本地数据库查找 编辑:程序博客网 时间:2024/06/03 19:57

使用GDI+程序时,注意返回值检测

 

Status status = GenericError;Graphics graphics(m_hWnd);status = graphics.GetLastStatus();if (status != Ok)        return;



一、位图画刷

//位图画刷void CGDIBaseSampleView::OnMenuitemBmpbrush() {CDC* pDC = GetDC();CRect rect;GetClientRect(&rect);rect.top = rect.Height()/4;rect.bottom = rect.top*3;rect.left = rect.Width()/4;rect.right = rect.left*3;CBitmap bitmap;if (!bitmap.LoadBitmap(IDB_BITMAP_BABY))        return;//只能载入项目中的位图,要载入外部的使用LoadImageCBrush newBrush;if (newBrush.CreatePatternBrush(&bitmap))pDC->FillRect(&rect, &newBrush);}


二、保存屏幕抓图文件

通过GDI+可以保存屏幕抓图文件
1.使用CrateDC() 函数获取屏幕抓图,并通过GetSystemMetrics函数计算屏幕的大小
2.将屏幕复制到Bitmap对象中
3.将Bitmap内容保存到文件中


//保存屏幕抓图文件void CGDIBaseSampleView::OnMenuitemSavescreentofile() {int cx = GetSystemMetrics(SM_CXSCREEN);       int cy = GetSystemMetrics(SM_CYSCREEN);   HDC hScrDC = CreateDC("DISPLAY",   NULL,   NULL,   NULL); Graphics graphics1(hScrDC);Bitmap  bitmap(cx, cy, &graphics1);   Graphics graphics2(&bitmap);HDC dc1 = graphics1.GetHDC();HDC dc2 = graphics2.GetHDC();   BitBlt(dc2,0,0,cx,cy,dc1,0,0,13369376);graphics1.ReleaseHDC(dc1);graphics2.ReleaseHDC(dc2);CLSID clsid;char propertyValue[] = "屏幕截图";PropertyItem* propertyItem = new PropertyItem;GetEncoderClsid(L"image/jpeg", &clsid);propertyItem->id = PropertyTagImageTitle;propertyItem->length = 16; propertyItem->type = PropertyTagTypeASCII;propertyItem->value = propertyValue;bitmap.SetPropertyItem(propertyItem);bitmap.Save(L"screen.jpg", &clsid, NULL);CDC* pDC = GetDC();pDC->TextOut(0,0,"保存屏幕抓图到screen.jpg文件");}



三、利用内存画布防止绘图时出现屏幕闪烁-双缓冲

//利用内存画布防止绘图时出现屏幕闪烁void CGDIBaseSampleView::OnMenuitemMemdc() {Bitmap bmp(300, 300);Graphics g(&bmp);Rect rect(0, 0, 300, 300);LinearGradientBrush brush(rect, Color::Green, Color::Blue,LinearGradientModeHorizontal);//线性渐变绘制 for(int j = 0; j < 60; j ++){for(int i = 0; i < 60; i++){g.FillEllipse(&brush, i*5, j*5, 5, 5);}}Graphics graphics(m_hWnd);graphics.DrawImage(&bmp, 0, 0);}


四、创建几何画笔



// 几何画笔void CGDIBaseSampleView::OnMenuitemGeometricpen() {CDC* pDC= GetDC();LOGBRUSH lb;lb.lbStyle = BS_SOLID;     lb.lbColor = RGB(0,0,255);     lb.lbHatch = HS_CROSS; HPEN hPen = ExtCreatePen(PS_GEOMETRIC|PS_ENDCAP_SQUARE|PS_JOIN_ROUND, 10, &lb, 0, NULL); if (hPen == NULL) return;CPen newPen;    if(newPen.Attach(hPen))    {                CPen* pOldPen = pDC->SelectObject( &newPen );     CRect rect;GetClientRect(&rect);rect.top = rect.Height()/4;rect.bottom = rect.top*3;rect.left = rect.Width()/4;rect.right = rect.left*3;pDC->Rectangle(&rect);          }}


五、绘制网格

//绘制网格void CGDIBaseSampleView::OnMenuitemDrawCrossline() {CDC* pDC= GetDC();CPen newPen;      if( newPen.CreatePen( PS_SOLID, 2, RGB(125,125,125) ) )    {        const int HC = 9;const int VC = 9;        CPen* pOldPen = pDC->SelectObject( &newPen );CRect rect;GetClientRect(&rect);int dx = rect.Width()/(HC-1);   int dy = rect.Height()/(VC-1); CPoint (*Point)[VC] = new CPoint[HC][VC];    for(int i=0;i<HC;i++)   {   for(int   j=0;j<VC;j++)   {   Point[i][j].x =  i*dx;   Point[i][j].y =  j*dy;   }   }   for(int i=0;i<HC;i++)   {   pDC->MoveTo(Point[i][0]);   pDC->LineTo(Point[i][VC-1]);   }   for(int j=0;j<VC;j++)   {   pDC->MoveTo(Point[0][j]);   pDC->LineTo(Point[HC-1][j]);   }         pDC->SelectObject( pOldPen );    }}




六、创建不同画刷

//创建不同的画刷void CGDIBaseSampleView::OnMenuitemMultibrush() {CDC* pDC = GetDC();CBrush newBrush;newBrush.CreateSolidBrush(RGB(255, 255, 0));CRect rect;GetClientRect(&rect);int width = rect.Width()/4;rect.right = width;pDC->FillRect(&rect, &newBrush);::DeleteObject((HGDIOBJ)newBrush);CBrush newBrush1;newBrush1.CreateHatchBrush(HS_CROSS, RGB(0,255,255));//创建纹理画笔rect.left += width;rect.right += width;pDC->FillRect(&rect, &newBrush1);::DeleteObject((HGDIOBJ)newBrush1);LOGBRUSH logBrush;logBrush.lbColor = RGB(255, 0, 255);logBrush.lbHatch = HS_HORIZONTAL;logBrush.lbStyle = BS_HATCHED;CBrush newBrush2;newBrush2.CreateBrushIndirect(&logBrush);//创建纹理画笔rect.left += width;rect.right += width;pDC->FillRect(&rect, &newBrush2);::DeleteObject((HGDIOBJ)newBrush2);CBrush newBrush3;newBrush3.CreateSysColorBrush(HS_VERTICAL);rect.left += width;rect.right += width;pDC->FillRect(&rect, &newBrush3);::DeleteObject((HGDIOBJ)newBrush3);}


七、填充矩形

//填充矩形void CGDIBaseSampleView::OnMenuitemFillRect() {CDC* pDC= GetDC();    CBrush backBrush(RGB(255, 128, 128));        CRect rect;GetClientRect(&rect);rect.top = rect.Height()/4;rect.bottom = rect.top*3;rect.left = rect.Width()/4;rect.right = rect.left*3;pDC->FillRect(&rect, &backBrush);   }


八、模拟时钟

1.绘制表盘
2.绘制刻度
3.绘制3个指针
//模拟时钟void CGDIBaseSampleView::OnMenuitemClock() {SetTimer(200, 1000, NULL);}void CGDIBaseSampleView::OnTimer(UINT nIDEvent) {if (nIDEvent == 200){//绘制钟表盘Graphics graphics(m_hWnd);int width = 300;int height = 300;Rect outRect(0, 0, width, height); Rect midRect(6, 6, 288, 288); Rect inRect(9, 9, 282, 282); LinearGradientBrush outBrush(outRect, Color(0, 125, 0), Color(0, 255, 0), LinearGradientModeBackwardDiagonal); LinearGradientBrush midBrush(midRect, Color(0, 255, 0), Color(0, 125, 0), LinearGradientModeBackwardDiagonal); LinearGradientBrush inBrush(inRect, Color(0, 125, 0), Color(0, 255, 0), LinearGradientModeBackwardDiagonal); graphics.FillEllipse(&outBrush, outRect); graphics.FillEllipse(&midBrush, midRect); graphics.FillEllipse(&inBrush, inRect); //绘制刻度FontFamily fontFamily(L"Arial");Font font(&fontFamily, 20, FontStyleBold, UnitPixel); SolidBrush whiteBrush(Color(255,255,255,255)); graphics.DrawString(L"12", -1, &font, PointF(130, 10), &whiteBrush); graphics.DrawString(L"6", -1, &font, PointF(140, 265), &whiteBrush); graphics.DrawString(L"3", -1, &font, PointF(270, 140), &whiteBrush);  graphics.DrawString(L"9", -1, &font, PointF(10, 140), &whiteBrush);  graphics.DrawString(L"1", -1, &font, PointF(200, 30), &whiteBrush);  graphics.DrawString(L"2", -1, &font, PointF(250, 80), &whiteBrush);  graphics.DrawString(L"5", -1, &font, PointF(205, 245), &whiteBrush);  graphics.DrawString(L"4", -1, &font, PointF(250, 200), &whiteBrush);  graphics.DrawString(L"11", -1, &font, PointF(65, 30), &whiteBrush);  graphics.DrawString(L"10", -1, &font, PointF(20, 80), &whiteBrush);  graphics.DrawString(L"7", -1, &font, PointF(65, 245), &whiteBrush);  graphics.DrawString(L"8", -1, &font, PointF(25, 200), &whiteBrush);//绘制指针 graphics.TranslateTransform(150, 150, MatrixOrderAppend); Pen hourPen(Color(255, 0, 255, 0), 7); //时针hourPen.SetLineCap(LineCapRoundAnchor, LineCapArrowAnchor, DashCapFlat); Pen minutePen(Color(255, 0, 0,255), 4); //分针minutePen.SetLineCap(LineCapRoundAnchor, LineCapArrowAnchor, DashCapFlat); Pen secondPen(Color(255, 255, 0, 0), 2); //秒针CTime time = CTime::GetCurrentTime();int sec = time.GetSecond();int min = time.GetMinute(); int hour = time.GetHour();  const double pi = 3.1415926;double secondAngle = 2.0 * pi * sec / 60.0; double minuteAngle = 2.0 * pi * (min + sec / 60.0) / 60.0; double hourAngle = 2.0 * pi * (hour + min / 60.0) / 12.0; Point centre(0, 0); Point hourHand((int)(40 * sin(hourAngle)), (int)(-40 * cos(hourAngle))); graphics.DrawLine(&hourPen, centre, hourHand); Point minHand((int)(80 * sin(minuteAngle)), (int)(-80 * cos(minuteAngle))); graphics.DrawLine(&minutePen, centre, minHand); Point secHand((int)(80 * sin(secondAngle)), (int)(-80 * cos(secondAngle))); graphics.DrawLine(&secondPen, centre, secHand);}CView::OnTimer(nIDEvent);}



九、颜色渐变算法

实现红色和绿色两种颜色的颜色渐变。RGB颜色值实际上是一个DWORD值0x00000000,本例中使用当前像素点在矩阵中的横坐标值和纵坐标值分别定义了颜色值和绿色值。
// 颜色渐变算法void CGDIBaseSampleView::OnMenuitemColorchange() {CDC* pDC= GetDC();int  i=0,j=0;   for(i=0;i<255;i++)   {   for(j=0;j<255;j++)   {   DWORD dwColor = (unsigned long)(0x00000000|0|j<<8|i);pDC->SetPixel(i,j,dwColor);}   }}




十、绘制渐变颜色



GradientFill函数填充矩形和三角形结构,并实现绘制渐变颜色
BOOL GradientFill(
HDC hdc,//目标设备上下文句柄
CONST PTRIVERTEX pVertex,//指向TRIVWERTEX结构的数组,用于定义三角矢量
DWORD dwNumVertex,//表示三角矢量点的个数
CONST PVOID pMesh,//指定点的信息
DWORD dwNumMesh,//pMesh参数中的元素数目
Dword dwMode);//指定填充模式,分为垂直填充矩形,水平填充矩形,填充三角形
//绘制渐变颜色void CGDIBaseSampleView::OnMenuitemDrawColorchange() {CDC* pDC=GetDC();CRect rect;GetClientRect(&rect);TRIVERTEX vert[2];   GRADIENT_RECT gRect; vert[0].x = rect.left;   vert[0].y = rect.top;   vert[0].Red = 0xff00;   vert[0].Green = 0x0000;   vert[0].Blue = 0x0000;   vert[0].Alpha = 0; vert[1].x = rect.right;   vert[1].y = rect.bottom;     vert[1].Red = 0x0000;   vert[1].Green = 0xff00;   vert[1].Blue = 0x0000;   vert[1].Alpha = 0;gRect.UpperLeft=0;   gRect.LowerRight=1;   GradientFill(pDC->GetSafeHdc(),vert,2,&gRect,1,GRADIENT_FILL_RECT_H);}



十一、图元文件的保存与打开

图元文件即矢量文件,是存储设备无关格式图片的结构集合。
此对象支持的图元文件的扩展名为emf和emf+格式。
//打开图元文件void CGDIBaseSampleView::OnMenuitemOpenmetafile() {Status status = GenericError;Graphics graphics(m_hWnd);status = graphics.GetLastStatus();if (status != Ok)        return;Image image(L"MFSample.emf");status = image.GetLastStatus();if (status != Ok)        return;graphics.DrawImage(&image, 0, 0);}



//保存图元文件void CGDIBaseSampleView::OnMenuitemSavemetafile() {CDC* pDC = GetDC();Status status = GenericError;Metafile metafile(L"MFSample.emf", pDC->m_hDC);{Graphics graphics(&metafile);status = graphics.GetLastStatus();if (status != Ok) return;Pen pen(Color(255, 0, 255, 0));status = pen.GetLastStatus();if (status != Ok) return;SolidBrush solidBrush(Color(255, 0, 255, 255));status = solidBrush.GetLastStatus();if (status != Ok) return;CRect rect;GetClientRect(&rect);int nLeft = (rect.Width())/2;int nTop = (rect.Height())/2;graphics.DrawRectangle(&pen, Rect(0, 0, nLeft, nTop));graphics.FillEllipse(&solidBrush, Rect(nLeft, nTop, nLeft/2, nTop/2));graphics.SetSmoothingMode(SmoothingModeHighQuality);}Graphics graphics(pDC->m_hDC);graphics.DrawImage(&metafile, 0, 0);}


十二、图像居中显示

//图像居中显示void CGDIBaseSampleView::OnMenuitemShowpiccenter() {Status status = GenericError;Graphics graphics(m_hWnd);status = graphics.GetLastStatus();if (status != Ok)        return;Image image(L"baby.JPG");status = image.GetLastStatus();if (status != Ok)        return;CRect rect;GetClientRect(&rect);int nLeft = 10;int nTop = 20;graphics.DrawImage(&image, nLeft, nTop, rect.Width()-2*nLeft, rect.Height()-2*nTop);}


十三、图片融合效果

//图片融合效果void CGDIBaseSampleView::OnMenuitemPicturecomb() {Graphics  graphics(m_hWnd);   Bitmap bg(L"girl1.jpg");   int bgWidth = bg.GetWidth();int bgHeight = bg.GetHeight();graphics.DrawImage(&bg, 0, 0, bgWidth, bgHeight);   Bitmap fg(L"girl2.jpg");   int   fgWidth = fg.GetWidth();   int   fgHeight = fg.GetHeight();   //分别设置前景图中的每一个像素的透明度   Color color, colorTemp;   for(int iRow =0; iRow < fgHeight; iRow++)   {   for(int iColumn =0; iColumn <fgWidth; iColumn++)   {   fg.GetPixel(iColumn, iRow, &color);   colorTemp.SetValue(color.MakeARGB(150, color.GetRed(),color.GetGreen(),color.GetBlue()));   fg.SetPixel(iColumn, iRow, colorTemp);   }   }   graphics.DrawImage(&fg, 0, 0, fgWidth, fgHeight);   }



十四、保存设备上下文

//保存设备上下文void CGDIBaseSampleView::OnMenuitemSavedc() {CDC* pDC=GetDC();CPen newPen;      if( newPen.CreatePen( PS_SOLID, 2, RGB(255,0,255) ) )    {int saved = pDC->SaveDC();pDC->SelectObject( &newPen );CRect rect;GetClientRect(&rect);pDC->MoveTo(0,0);   pDC->LineTo(rect.Width(),rect.Height());  pDC->RestoreDC(saved);pDC->MoveTo(rect.Width(),0);   pDC->LineTo(0,rect.Height());}}