⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imageotherspreadview.cpp

📁 visual c++数字图像与图形处理中的光盘内容
💻 CPP
字号:
// ImageOtherSpreadView.cpp : implementation of the CImageOtherSpreadView class
//

#include "stdafx.h"
#include "ImageOtherSpread.h"

#include "ImageOtherSpreadDoc.h"
#include "ImageOtherSpreadView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#include "math.h"
#include "BorderRect.h"
#include "ImageSSDialog.h"

/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView

IMPLEMENT_DYNCREATE(CImageOtherSpreadView,  CView)

BEGIN_MESSAGE_MAP(CImageOtherSpreadView,  CView)
	//{{AFX_MSG_MAP(CImageOtherSpreadView)
	ON_WM_CREATE()
	ON_COMMAND(IDM_OTHER_SPREAD_WAY,  OnOtherSpreadWay)
	ON_UPDATE_COMMAND_UI(IDM_OTHER_SPREAD_WAY,  OnUpdateOtherSpreadWay)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView construction/destruction

CImageOtherSpreadView::CImageOtherSpreadView()
{
	// TODO: add construction code here
	m_nWay = rhombus_outward;
}

CImageOtherSpreadView::~CImageOtherSpreadView()
{
}

BOOL CImageOtherSpreadView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView drawing

void CImageOtherSpreadView::OnDraw(CDC* pDC)
{
	BeginWaitCursor();
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap* pOldBitmap = memDC.SelectObject(&m_bitmap);
	
	CRect clientRect;
	GetClientRect(&clientRect);

	int cx = clientRect.Width();
	int cy = clientRect.Height();

	pDC->BitBlt(0, 0, cx, cy, &memDC, 0, 0, SRCCOPY);	
	memDC.SelectObject(pOldBitmap);
	EndWaitCursor();

	SpreadInto(pDC);

}

/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView diagnostics

#ifdef _DEBUG
void CImageOtherSpreadView::AssertValid() const
{
	CView::AssertValid();
}

void CImageOtherSpreadView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CImageOtherSpreadDoc* CImageOtherSpreadView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CImageOtherSpreadDoc)));
	return (CImageOtherSpreadDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CImageOtherSpreadView message handlers

int CImageOtherSpreadView::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	// TODO: Add your specialized creation code here
	//打开文件
	CDib* pBackDib = new CDib("back.bmp");

	if (!pBackDib->IsValid())
		MessageBox("文件打开出错", "文件 \"back.bmp\"", 
			MB_OK | MB_ICONEXCLAMATION);

	//
	CClientDC dc(this);

	m_bitmap.CreateCompatibleBitmap(&dc, 800, 600);

	CDC memDC;
	memDC.CreateCompatibleDC(&dc);

	CBitmap* pOldBitmap = memDC.SelectObject(&m_bitmap);
	CBrush* pBrush = new CBrush(RGB(255, 255, 255));
	CRect rect(0, 0, 800, 600);
	memDC.FillRect(rect, pBrush);

	//绘制背景位图
	if (pBackDib)
	{
		BYTE* pBackDibData = pBackDib->GetDibData();
		LPBITMAPINFO pBackBmpInfo = pBackDib->GetBmpInfo();
		int nWidth = (int)pBackDib->GetWidth();
		int nHeight = (int)pBackDib->GetHeight();
		StretchDIBits(memDC.m_hDC,  0,  0,  nWidth,  nHeight, 
			0,  0,  nWidth,  nHeight,  pBackDibData,  pBackBmpInfo, 
			DIB_RGB_COLORS,  SRCCOPY);
	}
	memDC.SelectObject(pOldBitmap);
	delete pBrush;	
	ReleaseDC(&dc);

	if (pBackDib)
	{
		delete pBackDib;
		pBackDib = NULL;
	}

	return 0;
}

void CImageOtherSpreadView::Delay(DWORD ms)
{
	DWORD time = GetTickCount();
	do{;}while((GetTickCount() - time) < ms);
}

void CImageOtherSpreadView::SpreadInto(CDC *pDC)
{
	CImageOtherSpreadDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here

	//第一步, 获取在文档中已经打开的位图
	//获取外部DIB信息
	CDib* pDib = pDoc->m_pDib;

	if(!pDib)return;

	int nWidth = (int)pDib->GetWidth();
	int nHeight = (int)pDib->GetHeight();

	//第二步, 将位图绘制到内存设备
	CDC memDC;
	memDC.CreateCompatibleDC(pDC);
	CBitmap ddb;
	ddb.CreateCompatibleBitmap(pDC, nWidth, nHeight);
	CBitmap* pOldBitmap = memDC.SelectObject(&ddb);

	//把整个位图绘制到内存, 
	//更快的办法是将图像直接绘制到pDC
	pDib->Draw(memDC.m_hDC, 0, 0, nWidth, nHeight, 
				0, 0, nWidth, nHeight, DIB_RGB_COLORS, SRCCOPY);

	//第三步, 从内存设备中读出位图

	CRect clientRect;
	GetClientRect(&clientRect);

	//左上角点
	int cx = clientRect.Width();
	int cy = clientRect.Height();

	cx = (cx - nWidth) / 2;
	cy = (cy - nHeight) / 2;

	//绘制一个内嵌框
	CBorderRect br(cx - 2, cy - 2, nWidth + 4, nHeight + 4);
	br.Draw(pDC, FALSE);


	//绘制坐标步长, 
	int nStepX, nStepY;

	//求出宽度和高度的最大者
	if(nWidth >= nHeight)
	{
		nStepX = 10;
		nStepY = (int)(10.0f * ((float)nHeight / (float)nWidth) + 0.5f);
	}
	else
	{
		nStepY = 10;
		nStepX = (int)(10.0f * ((float)nWidth / (float)nHeight) + 0.5f);
	}

	switch(m_nWay)
	{
		//菱形向外渐铺
		//
		case rhombus_outward:
		{
			//图像中心坐标
			int nCenterX = cx + (nWidth / 2);
			int nCenterY = cy + (nHeight / 2);

			for(int x = nStepX,  y = nStepY; x < nWidth; x += nStepX, y += nStepY)
			{
				//创建矩形剪切区域
				CRgn rgn;
				rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
				pDC->SelectClipRgn(&rgn, RGN_COPY);
				
				//创建菱形剪切区域, 并求交运算
				CRgn rgnRhombus;
				//菱形坐标
				POINT point[4] = {nCenterX, (nCenterY - y), (nCenterX + x), nCenterY, 
					nCenterX, (nCenterY + y), (nCenterX - x), nCenterY};
				
				rgnRhombus.CreatePolygonRgn(point, 4, WINDING);
				pDC->SelectClipRgn(&rgnRhombus, RGN_AND);
				pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
				rgnRhombus.DeleteObject();
				pDC->SelectClipRgn(NULL, RGN_COPY);
				Delay(20);
			}
			
			//由于少绘制一次, 所以必须补画最后一次
			//如果把循环的判断变为(x < nWidth + nStepX)
			//那么下面这条语句就没有必要了
			//但是, 这样处理有两个好处:
			//第一, 每做一次循环就少做一次加法运算
			//第二, 少最后一次区域求交运算.
			//但是, 这两点在视觉上是不会体会到的.
			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
			break;
		}
		
		//菱形向里渐铺
		case rhombus_inward:
		{
			//图像中心坐标
			int nCenterX = cx + (nWidth / 2);
			int nCenterY = cy + (nHeight / 2);

			for(int x = (nWidth - nStepX),  y = (nHeight - nStepY); x > nStepX; x -= nStepX, y -= nStepY)
			{
				
				//创建矩形剪切区域
				CRgn rgn;
				rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
				pDC->SelectClipRgn(&rgn, RGN_COPY);
				
				//创建菱形剪切区域, 并求交运算
				CRgn rgnRhombus;
				POINT point[4] = {nCenterX, (nCenterY - y), (nCenterX + x), nCenterY, 
					nCenterX, (nCenterY + y), (nCenterX - x), nCenterY};
				
				rgnRhombus.CreatePolygonRgn(point, 4, WINDING);
				
				pDC->SelectClipRgn(&rgnRhombus, RGN_DIFF);//RGN_XOR略慢
				pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
				rgnRhombus.DeleteObject();
				pDC->SelectClipRgn(NULL, RGN_COPY);
				Delay(20);
			}

			//循环少画一次, 再这里补一次
			//如果循环多画一次, 可能在最后区域留下一点缺陷
			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
			break;
		}

		//圆形向外渐铺
		case circle_outward:
		{
			//图像中心坐标
			int nCenterX = cx + (nWidth / 2);
			int nCenterY = cy + (nHeight / 2);

			//圆的最大半径
			int nMaxRadius = (int)sqrt(nWidth * nWidth + nHeight * nHeight) / 2; 

			for(int r = 10; r < nMaxRadius; r += 10)
			{
				//创建矩形剪切区域
				CRgn rgn;
				rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
				pDC->SelectClipRgn(&rgn, RGN_COPY);
				
				//创建圆形剪切区域, 并求交运算
				CRgn rgnCirlce;
				rgnCirlce.CreateEllipticRgn((nCenterX - r), (nCenterY - r), (nCenterX + r), (nCenterY + r));
				pDC->SelectClipRgn(&rgnCirlce, RGN_AND);
				pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
				rgnCirlce.DeleteObject();
				pDC->SelectClipRgn(NULL, RGN_COPY);
				Delay(25);
			}

			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
			break;
		}
		//圆形向里渐铺
		case circle_inward:
		{
			//图像中心坐标
			int nCenterX = cx + (nWidth / 2);
			int nCenterY = cy + (nHeight / 2);

			//圆的最大半径
			int nMaxRadius = (int)sqrt(nWidth * nWidth + nHeight * nHeight) / 2; 

			for(int r = (nMaxRadius - 10); r > 10; r -= 10)
			{
				//创建矩形剪切区域
				CRgn rgn;
				rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
				pDC->SelectClipRgn(&rgn, RGN_COPY);
				
				//创建圆形剪切区域, 并求交运算
				CRgn rgnCirlce;
				rgnCirlce.CreateEllipticRgn((nCenterX - r), (nCenterY - r), (nCenterX + r), (nCenterY + r));
				pDC->SelectClipRgn(&rgnCirlce, RGN_DIFF);
				pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
				rgnCirlce.DeleteObject();
				pDC->SelectClipRgn(NULL, RGN_COPY);
				Delay(25);
			}

			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
			break;
		}
		//椭圆形向外渐铺
		case ellipse_outward:
		{
			//图像中心坐标
			int nCenterX = cx + (nWidth / 2);
			int nCenterY = cy + (nHeight / 2);

			//最大水平半轴
			int nMaxAxisX = (int)(1.414f * nWidth + 0.5f) / 2;

			for(int x = nStepX,  y = nStepY; x < nMaxAxisX; x += nStepX, y += nStepY)
			{
				//创建矩形剪切区域
				CRgn rgn;
				rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
				pDC->SelectClipRgn(&rgn, RGN_COPY);
				
				//创建椭圆形剪切区域, 并求交运算
				CRgn rgnEllipse;
				rgnEllipse.CreateEllipticRgn((nCenterX - x), (nCenterY - y), (nCenterX + x), (nCenterY + y));
				pDC->SelectClipRgn(&rgnEllipse, RGN_AND);
				pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
				rgnEllipse.DeleteObject();
				pDC->SelectClipRgn(NULL, RGN_COPY);
				Delay(25);
			}
			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);

			break;
		}
		//椭圆形向里渐铺
		case ellipse_inward:
		{
			//图像中心坐标
			int nCenterX = cx + (nWidth / 2);
			int nCenterY = cy + (nHeight / 2);

			//最大水平半轴
			int nMaxAxisX = (int)(1.414f * nWidth + 0.5f) / 2;

			//最大垂直半轴
			int nMaxAxisY = (int)(1.414f * nHeight + 0.5f) / 2;

			for(int x = (nMaxAxisX - nStepX),  y = (nMaxAxisY - nStepY); x > nStepX; x -= nStepX, y -= nStepY)
			{
				//创建矩形剪切区域
				CRgn rgn;
				rgn.CreateRectRgn(cx, cy, cx + nWidth, cy + nHeight);
				pDC->SelectClipRgn(&rgn, RGN_COPY);
				
				//创建椭圆形剪切区域, 并求交运算
				CRgn rgnEllipse;
				rgnEllipse.CreateEllipticRgn((nCenterX - x), (nCenterY - y), (nCenterX + x), (nCenterY + y));
				pDC->SelectClipRgn(&rgnEllipse, RGN_DIFF);
				pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
				rgnEllipse.DeleteObject();
				pDC->SelectClipRgn(NULL, RGN_COPY);
				Delay(25);
			}
			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
			break;
		}
		//水平帘窗式进入
		case curtain_horizontal:
		{
			//条状高度
			int nStripHeight = 16;

			//条数
			int nStrips = nHeight / 16;


			//是否在最后还残留一点
			BOOL bRemnant = (nHeight > nStrips * 16) ? TRUE : FALSE;

			//可能的残留高度
			int nRemnantHeight = nHeight - nStrips * 16;

			for(int i = 1;i < nStripHeight;i++)
			{   
				//坐标
				int y = 0;
				for(int n = 0; n < nStrips; n++)
				{
					pDC->BitBlt(cx, (cy + y), nWidth, i, &memDC, 0, y, SRCCOPY);
					y += nStripHeight;
				}
				
				if((bRemnant) && (i < nRemnantHeight))
					pDC->BitBlt(cx, (cy + y), nWidth, i, &memDC, 0, y, SRCCOPY);

				Delay(35);
			}
			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);
			break;
		}
		//垂直帘窗式进入
		case curtain_vertical:
		{
			//条状高度
			int nStripWidth = 16;

			//条数
			int nStrips = nWidth / 16;


			//是否在最后还残留一点
			BOOL bRemnant = (nWidth > nStrips * 16) ? TRUE : FALSE;

			//可能的残留宽度
			int nRemnantWidth = nWidth - nStrips * 16;

			
			for(int i = 1;i < nStripWidth;i++)
			{   
				//坐标
				int x = 0;
				for(int n = 0; n < nStrips; n++)
				{
					pDC->BitBlt((cx + x), cy, i, nHeight, &memDC, x, 0, SRCCOPY);
					x += nStripWidth;
				}
				
				if((bRemnant) && (i < nRemnantWidth))
					pDC->BitBlt((cx + x), cy, i, nHeight, &memDC, x, 0, SRCCOPY);

				Delay(35);
			}
			pDC->BitBlt(cx, cy, nWidth, nHeight, &memDC, 0, 0, SRCCOPY);

			break;
		}
	}

	ddb.DeleteObject();
	memDC.SelectObject(pOldBitmap);
}

void CImageOtherSpreadView::OnOtherSpreadWay() 
{
	// TODO: Add your command handler code here
	CImageSSDialog dlg;
	dlg.m_nWay = m_nWay;

	int responeDlg = dlg.DoModal();
	if(responeDlg == IDOK)
	{
		m_nWay = dlg.m_nWay;
		Invalidate();
	}	
}

void CImageOtherSpreadView::OnUpdateOtherSpreadWay(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -