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

使用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;//只能载入项目中的位图,要载入外部的使用LoadImage
	CBrush 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());
	}
}





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值