基於CButton編寫的圖片控件

頭文件:ButtonPicture.hios

#pragma once
#include <atlimage.h>
#include <string>
using namespace ATL;

struct IMAGEPARAMENT {          
	int     nWidth;   
	int     nHeight;   
	int     nBitCount;   
	int     nBytesPerLine;   
	int     nBytesPerPixel;   
	int     nNumColors;   
	int     nSize;   
};   
class CButtonPic : public CButton
{
public:
	CButtonPic();
	virtual ~CButtonPic();
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
protected:	
	DECLARE_MESSAGE_MAP()
	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
	afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);

public:
	void ShowImage(std::string strimgpath,HWND parent_wnd);
	void OnSelectStampPos();
	void OnRorateUp90();
	void OnRorateUp180();
	void OnRorateDown90();
	void OnRorateDown180();
	void OnBlownUp();
	void OnBlownDown();
	void OnRightSize();
private:
	void DrawImage(void);
	void GetRightImageSize(double &imgscale,int &right_width,int &right_height);
	bool CreateBitMap(CBitmap &mBitmap);
	void ResetScrollInfo(void);
	void RorateImage(CImage &in_image,CImage &out_image,double angle);
	bool ResizeImage(CImage &image,int destWidth, int destHeight,CImage &newimg);
	bool ImageCopy(CImage &srcImage, CImage &destImage);

private:
	HWND m_parent_wnd;
	std::string m_imgpath;
	CImage m_img;
	double m_imgscale;
	int m_angle;
	double m_rightscale;
	int m_right_width;
	int m_right_height;
	int m_scale_idx;

	//滾動條
	int m_scrollmaxsize_h;
	int m_scrollpos_h;
	int m_scrollpagesize_h;
	int m_scrollmaxsize_w;
	int m_scrollpos_w;
	int m_scrollpagesize_w;
	int m_onestep;
	//
	bool selstampflag;
	POINT m_stamppoint;
	POINT m_realstamppoint;
	int m_stamp_r;
public:
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
};

源文件:ButtonPicture.cpp數組

#include "stdafx.h"
#include "ButtonPicture.h"
#include "CIProcess.h"
#include <sstream>
#include <iostream>
#if 0
#include<opencv2/imgproc/imgproc.hpp>  
#include<opencv2/highgui/highgui.hpp> 
#include <cv.h>
#endif
#include <math.h>

//using namespace cv; 
using namespace std;

const double g_scale_arr[9] = {1.0,1.1,1.2,1.5,1.8,2.0,3.0,4.0,5.0};

CButtonPic::CButtonPic()
{	
	m_parent_wnd = NULL;
	m_imgpath = "";
	m_imgscale = 1.0;
	m_angle = 0;

	m_rightscale = 1.0;
	m_right_width = 0;
	m_right_height = 0;
	m_scale_idx = 0;

	m_scrollmaxsize_h = 0;
	m_scrollpos_h = 0;
	m_scrollpagesize_h = 0;
	m_scrollmaxsize_w = 0;
	m_scrollpos_w = 0;
	m_scrollpagesize_w = 0;
	m_onestep = 0;

	selstampflag = false;
	m_stamppoint.x = 0;
	m_stamppoint.y = 0;
	m_realstamppoint.x = 0;
	m_realstamppoint.y = 0;
	m_stamp_r = 40;
}

CButtonPic::~CButtonPic()
{
}

BEGIN_MESSAGE_MAP(CButtonPic, CButton)	
	ON_WM_DRAWITEM()
	ON_WM_HSCROLL()
	ON_WM_VSCROLL()
	ON_WM_LBUTTONUP()
	ON_WM_MOUSEMOVE()
END_MESSAGE_MAP()

void CButtonPic::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
	// TODO: Add your code to draw the specified item
	//設置背景色
	CDC* pDC = this->GetDC();
	CRect rc;
	this->GetClientRect(&rc);
	FillRect(this->GetDC()->GetSafeHdc(),&rc,CBrush(RGB(99,99,99)));
	if (m_imgpath.empty())
	{
		return;
	}
	//做圖
	DrawImage();
}
void CButtonPic::DrawImage(void)
{
	//	
	CDC* pDC = this->GetDC();
	CRect rc;
	this->GetClientRect(&rc);
	CBitmap cbmp;
	BITMAP bm;
	CreateBitMap(cbmp);
	cbmp.GetBitmap(&bm);
	CDC dcImage;

	dcImage.CreateCompatibleDC(pDC); 
	dcImage.SelectObject(&cbmp);

	//畫圖
	int cx = (rc.Width() - bm.bmWidth)/2>0?(rc.Width() - bm.bmWidth)/2:0;
	int	cy = (rc.Height() - bm.bmHeight)/2>0?(rc.Height() - bm.bmHeight)/2:0; 
	pDC->StretchBlt(cx,cy,rc.Width(),rc.Height(), &dcImage,m_scrollpos_w ,m_scrollpos_h,rc.Width(),rc.Height(),SRCCOPY);
	DeleteObject(cbmp);
	DeleteDC(dcImage);
}
bool CButtonPic::CreateBitMap(CBitmap &mBitmap)
{
	//轉換成位圖
	CDC *pDC = GetDC();
	CDC memDC;	

	memDC.CreateCompatibleDC(pDC);
	mBitmap.CreateCompatibleBitmap(pDC,m_img.GetWidth(),m_img.GetHeight());
	CBitmap *OldBitmap =memDC.SelectObject(&mBitmap);
	m_img.Draw(memDC.m_hDC,0,0);
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{		
		CPen  pen;
		pen.CreatePen(PS_INSIDEFRAME,2,RGB(255,0,0));	
		CPen  *oldpen=memDC.SelectObject(&pen); 
		CBrush brs;  
		brs.CreateHatchBrush(HS_CROSS,RGB(255,0,0));
		CBrush *pOldBrush = memDC.SelectObject(&brs);
		//畫圓心
		memDC.Ellipse(m_stamppoint.x-2,m_stamppoint.y-2,m_stamppoint.x+2,m_stamppoint.y+2);
		//畫圓圈
		memDC.SelectObject(CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH)));
		memDC.Ellipse(m_stamppoint.x-m_stamp_r,m_stamppoint.y-m_stamp_r,m_stamppoint.x+m_stamp_r,m_stamppoint.y+m_stamp_r);
		memDC.SelectObject(pOldBrush);
		memDC.SelectObject(oldpen);
		brs.DeleteObject(); 
		pen.DeleteObject();
	}
	memDC.SelectObject(OldBitmap);
	DeleteDC(memDC);	
	OldBitmap = NULL;

	return true;
}
void CButtonPic::ResetScrollInfo(void)
{
	LPSCROLLINFO  lpsi = NULL;
	lpsi = new SCROLLINFO;
	CRect rc;
	this->GetClientRect(&rc);

	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();

	m_scrollmaxsize_w = img_width;
	m_scrollmaxsize_h = img_height;
	m_scrollpagesize_w = rc.Width();
	m_scrollpagesize_h = rc.Height();
	m_onestep = 10;
	m_scrollpos_w = 0;
	m_scrollpos_h = 0;

	this->SetScrollRange( SB_HORZ,0,m_scrollmaxsize_w);
	this->SetScrollRange( SB_VERT,0,m_scrollmaxsize_h);
	this->GetScrollInfo(SB_HORZ,lpsi);
	lpsi->nPage = m_scrollpagesize_w;
	this->SetScrollInfo(SB_HORZ,lpsi);
	this->GetScrollInfo(SB_VERT,lpsi);
	lpsi->nPage = m_scrollpagesize_h;
	this->SetScrollInfo(SB_VERT,lpsi);
	if (lpsi!=NULL)
	{
		delete lpsi;
		lpsi = NULL;
	}
}
bool CButtonPic::ImageCopy(CImage &srcImage, CImage &destImage)  
{  
	int i,j;//循環變量  
	if(srcImage.IsNull())  
		return FALSE;  
	//源圖像參數  
	BYTE* srcPtr=(BYTE*)srcImage.GetBits();  
	int srcBitsCount=srcImage.GetBPP();  
	int srcWidth=srcImage.GetWidth();  
	int srcHeight=srcImage.GetHeight();  
	int srcPitch=srcImage.GetPitch();   
	//銷燬原有圖像  
	if( !destImage.IsNull())  
	{  
		destImage.Destroy();  
	}  
	//建立新圖像  
	if(srcBitsCount==32)   //支持alpha通道  
	{  
		destImage.Create(srcWidth,srcHeight,srcBitsCount,1);  
	}  
	else  
	{  
		destImage.Create(srcWidth,srcHeight,srcBitsCount,0);  
	}  
	//加載調色板  
	if(srcBitsCount<=8&&srcImage.IsIndexed())//須要調色板  
	{  
		RGBQUAD pal[256];  
		int nColors=srcImage.GetMaxColorTableEntries();  
		if(nColors>0)  
		{       
			srcImage.GetColorTable(0,nColors,pal);  
			destImage.SetColorTable(0,nColors,pal);//複製調色板程序  
		}     
	}   
	//目標圖像參數  
	BYTE *destPtr=(BYTE*)destImage.GetBits();  
	int destPitch=destImage.GetPitch();  
	//複製圖像數據  
	for(i=0 ; i<srcHeight;i++)  
	{  
		memcpy( destPtr+i*destPitch, srcPtr+i*srcPitch, abs(srcPitch) );  
	}   

	return TRUE;  
} 
void CButtonPic::RorateImage(CImage &in_image,CImage &out_image,double angle)
{
#if 0
	in_image.Save("src.jpg");
	IplImage *in_src_img = NULL;  
	IplImage *out_dest_img = NULL;  

	in_src_img = cvLoadImage("src.jpg",CV_LOAD_IMAGE_COLOR);  
	if (in_src_img == NULL)
	{
		return ;
	}
	double tmpangle = angle * CV_PI / 180.;
	double a = sin(tmpangle), b = cos(tmpangle);
	int width = in_src_img->width;  
	int height = in_src_img->height;  
	int width_rotate= int(height * fabs(a) + width * fabs(b));  
	int height_rotate=int(width * fabs(a) + height * fabs(b));
	float map[6];
	CvMat map_matrix = cvMat(2, 3, CV_32F, map);
	CvPoint2D32f center = cvPoint2D32f(width / 2, height / 2);  
	cv2DRotationMatrix(center, angle, 1.0, &map_matrix);  
	map[2] += (width_rotate - width) / 2;  
	map[5] += (height_rotate - height) / 2; 
	out_dest_img = cvCreateImage(cvSize(width_rotate, height_rotate), in_src_img->depth, in_src_img->nChannels); 
	cvWarpAffine( in_src_img,out_dest_img, &map_matrix, CV_INTER_LINEAR | CV_WARP_FILL_OUTLIERS, cvScalarAll(0));  
	cvSaveImage("rorate.jpg",out_dest_img);
	if (in_src_img)
	{
		cvReleaseImage(&in_src_img);
		in_src_img = NULL;
	}
	if (out_dest_img)
	{
		cvReleaseImage(&out_dest_img);
		out_dest_img = NULL;
	}
	out_image.Load("rorate.jpg");
#endif
}
void CButtonPic::GetRightImageSize(double &imgscale,int &right_width,int &right_height)
{
	CImage src_img;	
	ImageCopy(m_img,src_img);
	if (src_img.IsNull())
	{
		return;
	}	
	
	CRect rc;
	this->GetClientRect(&rc);
	int wnd_width = rc.Width();
	int wnd_height = rc.Height();
	int src_img_width = src_img.GetWidth();
	int src_img_height = src_img.GetHeight();
	if ((src_img_width * wnd_height) > (src_img_height * wnd_width))
		{
			right_width = wnd_width;
			right_height = (wnd_width * src_img_height) / src_img_width;
			imgscale = src_img_width * 1.0 / wnd_width;
		}
		else
		{
			right_height = wnd_height;
			right_width = (src_img_width * wnd_height) / src_img_height;
			imgscale = src_img_height * 1.0 / wnd_height;
		}
	ResizeImage(src_img,right_width,right_height,m_img);
	src_img.Destroy();
}
void CButtonPic::ShowImage(std::string strimgpath,HWND parent_wnd)
{
	m_parent_wnd = parent_wnd;
	m_imgpath = strimgpath;
	CString imgpath = m_imgpath.c_str();
	if (!m_img.IsNull())
	{
		m_img.Destroy();
	}
	m_img.Load(imgpath);
	if (m_img.IsNull())
	{
		return;
	}	
	GetRightImageSize(m_rightscale,m_right_width,m_right_height);	
	m_scale_idx = 0;
	m_imgscale = m_rightscale;	
	m_stamppoint.x = 0;
	m_stamppoint.y = 0;
	
	ResetScrollInfo();
	Invalidate();
}

void CButtonPic::OnSelectStampPos()
{
	// TODO: 在此添加命令處理程序代碼
	selstampflag = true;
}


void CButtonPic::OnRorateUp90()
{
	// TODO: 在此添加命令處理程序代碼
	m_angle = m_angle + 90;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,270);
	CIProcess::RotateCimage(&m_img,&rorate_img,270);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印點
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		int i_val = m_stamppoint.x;
		m_stamppoint.x = m_stamppoint.y;
		m_stamppoint.y = m_img.GetHeight() - i_val;
	}
	ResetScrollInfo();
	Invalidate();
}


void CButtonPic::OnRorateUp180()
{
	// TODO: 在此添加命令處理程序代碼
	m_angle = m_angle + 180;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,180);
	CIProcess::RotateCimage(&m_img,&rorate_img,180);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印點
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		m_stamppoint.x = m_img.GetWidth() - m_stamppoint.x;
		m_stamppoint.y = m_img.GetHeight() - m_stamppoint.y;
	}
	ResetScrollInfo();
	Invalidate();
}


void CButtonPic::OnRorateDown90()
{
	// TODO: 在此添加命令處理程序代碼
	m_angle = m_angle + 270;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,90);
	CIProcess::RotateCimage(&m_img,&rorate_img,90);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印點
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		int i_val = m_stamppoint.y;
		m_stamppoint.y = m_stamppoint.x;		
		m_stamppoint.x = m_img.GetWidth() - i_val;
	}
	ResetScrollInfo();
	Invalidate();
}


void CButtonPic::OnRorateDown180()
{
	// TODO: 在此添加命令處理程序代碼
	m_angle = m_angle + 180;
	CImage rorate_img;
	//RorateImage(m_img,rorate_img,180);
	CIProcess::RotateCimage(&m_img,&rorate_img,180);
	ImageCopy(rorate_img,m_img);
	rorate_img.Destroy();
	//用印點
	if (m_stamppoint.x>m_stamp_r&&m_stamppoint.y>m_stamp_r)
	{
		m_stamppoint.x = m_img.GetWidth() - m_stamppoint.x;
		m_stamppoint.y = m_img.GetHeight() - m_stamppoint.y;
	}
	ResetScrollInfo();
	Invalidate();
}

bool CButtonPic::ResizeImage(CImage &image,int destWidth, int destHeight,CImage &newimg)
{
	//銷燬原有圖像  
	if( !newimg.IsNull())  
	{  
		newimg.Destroy();  
	}  
	if(!newimg.CreateEx(destWidth, destHeight, 24, BI_RGB))
	{
		return false;
	}
	int nPreMode = ::SetStretchBltMode(newimg.GetDC(),  HALFTONE);
	newimg.ReleaseDC();
	image.Draw(newimg.GetDC(), 0, 0, destWidth, destHeight, 0, 0, image.GetWidth(), image.GetHeight());
	newimg.ReleaseDC();
	::SetBrushOrgEx(newimg.GetDC(), 0, 0, NULL); 
	newimg.ReleaseDC();
	::SetStretchBltMode(newimg.GetDC(), nPreMode);
	newimg.ReleaseDC();	
	return true;
}
void CButtonPic::OnBlownUp()
{
	// TODO: 在此添加命令處理程序代碼
	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();
	if (m_scale_idx>=0&&m_scale_idx<8)
	{
		m_scale_idx = m_scale_idx + 1;
		m_imgscale = m_imgscale * g_scale_arr[m_scale_idx];
		img_width = img_width * g_scale_arr[m_scale_idx];
		img_height = img_height * g_scale_arr[m_scale_idx];	
		m_stamppoint.x = m_stamppoint.x * g_scale_arr[m_scale_idx];	
		m_stamppoint.y = m_stamppoint.y * g_scale_arr[m_scale_idx];	
		m_stamp_r = m_stamp_r * g_scale_arr[m_scale_idx];
		 
		CImage newimage;
		ResizeImage(m_img,img_width,img_height,newimage);
		ImageCopy(newimage,m_img);
		newimage.Destroy();
		ResetScrollInfo();
		Invalidate();
	}
	else
	{
		MessageBox("已經放大到最大");
	}
}


void CButtonPic::OnBlownDown()
{
	// TODO: 在此添加命令處理程序代碼
	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();
	if (m_scale_idx<=8&&m_scale_idx>0)
	{
		m_imgscale = m_imgscale / g_scale_arr[m_scale_idx];
		img_width = img_width / g_scale_arr[m_scale_idx];
		img_height = img_height / g_scale_arr[m_scale_idx];
		m_stamppoint.x = m_stamppoint.x / g_scale_arr[m_scale_idx];	
		m_stamppoint.y = m_stamppoint.y / g_scale_arr[m_scale_idx];	
		m_stamp_r = m_stamp_r / g_scale_arr[m_scale_idx];
		m_scale_idx = m_scale_idx - 1;	
		CImage newimage;
		ResizeImage(m_img,img_width,img_height,newimage);
		ImageCopy(newimage,m_img);
		newimage.Destroy();
		ResetScrollInfo();
		Invalidate();
	}
	else
	{
		MessageBox("已經縮放到最小");
	}
}


void CButtonPic::OnRightSize()
{
	// TODO: 在此添加命令處理程序代碼
	//ShowImage(m_imgpath,m_parent_wnd);
	int img_width = m_img.GetWidth();
	int img_height = m_img.GetHeight();
	double d_scale = m_imgscale / m_rightscale;
	m_imgscale = m_rightscale;
	m_scale_idx = 0 ;
	img_width = img_width / d_scale;
	img_height = img_height / d_scale;
	m_stamppoint.x = m_stamppoint.x / d_scale;	
	m_stamppoint.y = m_stamppoint.y / d_scale;	
	m_stamp_r = m_stamp_r / d_scale;
	CImage newimage;
	ResizeImage(m_img,img_width,img_height,newimage);
	ImageCopy(newimage,m_img);
	newimage.Destroy();
	ResetScrollInfo();
	Invalidate();	
		
	
}


void CButtonPic::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息處理程序代碼和/或調用默認值
	CRect rc;
	this->GetClientRect(&rc);
	switch(nSBCode)
	{
	case SB_LEFT:

		m_scrollpos_w = 0;
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);		
		break;
	case SB_LINELEFT:
	case SB_PAGELEFT:
		m_scrollpos_w -= m_onestep;

		if(m_scrollpos_w<0)
		{
			m_scrollpos_w = 0;
		}
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		break;
	case SB_LINERIGHT:
	case SB_PAGERIGHT:
		if (m_img.GetWidth()-rc.Width()<=(m_scrollpos_w+m_onestep)||
			m_img.GetWidth()<rc.Width())
		{
			break;
		}
		m_scrollpos_w += m_onestep;

		if(m_scrollpos_w>m_scrollmaxsize_w)
		{
			m_scrollpos_w = m_scrollmaxsize_w;
		}
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		break;
	case SB_RIGHT:

		m_scrollpos_w = m_scrollmaxsize_w;
		this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		if (m_img.GetWidth()-rc.Width()>=nPos&&
			m_img.GetWidth()>rc.Width())
		{
			m_scrollpos_w = nPos;
			this->SetScrollPos(SB_HORZ,m_scrollpos_w);
		}
		
		break;
	default:
		break;
	}
	DrawImage();
	CButton::OnHScroll(nSBCode, nPos, pScrollBar);
}


void CButtonPic::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
	// TODO: 在此添加消息處理程序代碼和/或調用默認值
	CRect rc;
	this->GetClientRect(&rc);
	switch(nSBCode)
	{
	case SB_LEFT:

		m_scrollpos_h = 0;
		this->SetScrollPos(SB_VERT,m_scrollpos_h);		
		break;
	case SB_LINELEFT:
	case SB_PAGELEFT:

		m_scrollpos_h -= m_onestep;

		if(m_scrollpos_h<0)
		{
			m_scrollpos_h = 0;
		}
		this->SetScrollPos(SB_VERT,m_scrollpos_h);
		break;
	case SB_LINERIGHT:
	case SB_PAGERIGHT:
		if (m_img.GetHeight()-rc.Height()<=m_scrollpos_h+m_onestep||
			m_img.GetHeight()<rc.Height())
		{
			break;
		}
		m_scrollpos_h += m_onestep;

		if(m_scrollpos_h>m_scrollmaxsize_h)
		{
			m_scrollpos_h = m_scrollmaxsize_h;
		}
		this->SetScrollPos(SB_VERT,m_scrollpos_h);
		break;
	case SB_RIGHT:

		m_scrollpos_h = m_scrollmaxsize_h;
		this->SetScrollPos(SB_VERT,m_scrollpos_h);
		break;
	case SB_THUMBPOSITION:
	case SB_THUMBTRACK:
		if (m_img.GetHeight()-rc.Height()>=nPos&&
			m_img.GetHeight()>rc.Height())
		{
			m_scrollpos_h = nPos;
			this->SetScrollPos(SB_VERT,m_scrollpos_h);
		}
		
		break;
	default:
		break;
	}
	DrawImage();
	CButton::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CButtonPic::OnLButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息處理程序代碼和/或調用默認值
	std::stringstream strbuf;
	CString msgbox = "";
	if (selstampflag)
	{		
		CRect rc;
		this->GetClientRect(&rc);
		int move_x = (rc.Width() - m_img.GetWidth())/2>0?(rc.Width() - m_img.GetWidth())/2:0;
		int move_y = (rc.Height() - m_img.GetHeight())/2>0?(rc.Height() - m_img.GetHeight())/2:0;
		ScreenToClient(&rc);
		if (point.x>m_stamp_r+move_x&&point.x< rc.Width()-m_stamp_r-move_x
			&& point.y>m_stamp_r+move_y &&point.y<rc.Height()-m_stamp_r-move_y)
		{
			m_stamppoint.x = point.x + m_scrollpos_w-move_x;
			m_stamppoint.y = point.y +m_scrollpos_h-move_y;

			selstampflag = false;
			m_angle = m_angle%360>0?m_angle%360:m_angle%360+360;
			double d_scale = m_imgscale/m_rightscale;
			m_realstamppoint.x = (m_stamppoint.x-m_img.GetWidth()/2)*m_rightscale/d_scale;
			m_realstamppoint.y = (m_stamppoint.y-m_img.GetHeight()/2)*m_rightscale/d_scale;
			strbuf << "你選擇了用印點("<< m_realstamppoint.x << "," << m_realstamppoint.y <<"),準備開始用印!";
			msgbox = "肯定";
		}
		else
		{
			strbuf << "選擇的蓋章點("<< m_stamppoint.x << "," << m_stamppoint.y <<")超出用印範圍,請從新選擇!";
			msgbox = "錯誤";			
		}
		string strmsg;
		strbuf >> strmsg;
		MessageBox(strmsg.c_str(),msgbox);
	}
	Invalidate();
	CButton::OnLButtonUp(nFlags, point);
}


void CButtonPic::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息處理程序代碼和/或調用默認值
	if (selstampflag)
	{
		CRect rc;
		this->GetClientRect(&rc);
		int move_x = (rc.Width() - m_img.GetWidth())/2>0?(rc.Width() - m_img.GetWidth())/2:0;
		int move_y = (rc.Height() - m_img.GetHeight())/2>0?(rc.Height() - m_img.GetHeight())/2:0;
		ScreenToClient(&rc);
		if (point.x>m_stamp_r+move_x&&point.x< rc.Width()-m_stamp_r-move_x
			&& point.y>m_stamp_r+move_y &&point.y<rc.Height()-m_stamp_r-move_y)
		{
			HCURSOR hCur = LoadCursor( NULL,IDC_CROSS) ;
			::SetCursor(hCur);
		}
	}
	CButton::OnMouseMove(nFlags, point);
}

圖像旋轉頭文件:CIProcess.hui

#pragma once
#include <atlimage.h>
namespace CIProcess
{
	struct IMAGEPARAMENT {          
		int     nWidth;   
		int     nHeight;   
		int     nBitCount;   
		int     nBytesPerLine;   
		int     nBytesPerPixel;   
		int     nNumColors;   
		int     nSize;   
	};   
	void  GetImageParament(CImage *pImg,struct IMAGEPARAMENT *ppImgParam);   
	int   InImage(CImage *pImg,int x,int y);   
	void  SetRectValue(CImage *pImg,int x,int y,int Dx,int Dy,BYTE *buf); 
	void  GetAllPalette(CImage *pImg,RGBQUAD *ColorTab);   
	void  SetAllPalette(CImage *pImg,RGBQUAD *ColorTab);   
	int   PaletteType(RGBQUAD   *ColorTab);   
	int   ImageType(CImage *pImgm);   
	void RotateCimage(CImage *Imgm, CImage *Imgn, double alpha);  

};

圖像旋轉源碼:CIProcess.cppthis

#include "StdAfx.h"
#include "CIProcess.h"
#include <math.h>  

void CIProcess::GetImageParament(CImage *pImg,struct IMAGEPARAMENT *ppImgParam)  
{  
	if (pImg->IsNull()) return;  

	ppImgParam->nWidth   = pImg->GetWidth();      //圖像寬度  
	ppImgParam->nHeight   = pImg->GetHeight();        //圖像高度  
	ppImgParam->nBitCount  = pImg->GetBPP();      //每像素位數  
	ppImgParam->nBytesPerLine   = (pImg->GetWidth()*pImg->GetBPP()+31)/32*4;   //每行字節數  
	ppImgParam->nBytesPerPixel   = pImg->GetBPP()/8;      //每像素字節數  
	if (pImg->GetBPP()<=8)   
		ppImgParam->nNumColors= 1 << pImg->GetBPP();        //調色板單元數  
	else   
		ppImgParam->nNumColors= 0;  
	ppImgParam->nSize  = ppImgParam->nBytesPerLine*ppImgParam->nHeight;        //像素總字節數  
}  

int  CIProcess::InImage(CImage *pImg,int x,int y)  
{  
	struct  IMAGEPARAMENT  P;  

	GetImageParament(pImg,&P);  
	if ((x<0)||(y<0)||(x>=P.nWidth)||(y>=P.nHeight))  return 0;  
	else  return 1;  
}  
void CIProcess::SetRectValue(CImage *pImg,int x,int y,int Dx,int Dy,BYTE *buf)  
{  
	struct  IMAGEPARAMENT  P;  
	BYTE    *lp;  
	int     i,dw,dh,x1,y1,alpha,delta,Dxb,dwb;  

	GetImageParament(pImg,&P);  
	if (P.nBitCount<8) return;  
	x1=x;  
	y1=y;  
	alpha=delta=0;  
	if (x<0) {   
		alpha=-x;    x1=0;  
	}  
	if (y<0) {   
		delta=-y;    y1=0;  
	}  
	if (!InImage(pImg,x1,y1)) return;  
	dw=min(Dx,(int) P.nWidth-x1);      
	dh=min(Dy,(int) P.nHeight-y1);  
	dw -= alpha;  
	dh -= delta;  

	Dxb = Dx*P.nBytesPerPixel;  
	dwb = dw*P.nBytesPerPixel;  
	lp = (BYTE*) pImg->GetPixelAddress(x1,y1);  
	buf += (delta*Dx+alpha)*P.nBytesPerPixel;  
	for (i=0;i<dh;i++) {  
		memcpy(lp,buf,dwb);    
		buf += Dxb;   
		lp -= P.nBytesPerLine;  
	}  
} 
void CIProcess::GetAllPalette(CImage *pImg,RGBQUAD *ColorTab)  
{  
	struct  IMAGEPARAMENT P;  

	GetImageParament(pImg,&P);  
	pImg->GetColorTable(0, P.nNumColors, ColorTab);  
}  

void CIProcess::SetAllPalette(CImage *pImg, RGBQUAD *ColorTab)  
{  
	struct  IMAGEPARAMENT P;  

	GetImageParament(pImg,&P);  
	pImg->SetColorTable(0, P.nNumColors, ColorTab);  
}
int   CIProcess::PaletteType(RGBQUAD  *ColorTab)  
{  
	int     i,k,m,n,r,g,b;  

	m=n=0;  
	for (i=0; i<256; i++)  
	{  
		r = ColorTab[i].rgbRed;  
		g = ColorTab[i].rgbGreen;  
		b = ColorTab[i].rgbBlue;  
		if ((r != g)||(r != b)) m=0;  
		if ((i>0)&&(r>ColorTab[i-1].rgbRed)) m++;  
		if (r+g+b==0) n++;  
	}  
	k=3;  
	if (m == 255) k=2;      
	else  if (256-n==1) k=0;                       
	else  if (256-n==15) k=1;                       
	return(k);  
}  

int CIProcess::ImageType(CImage *pImgm)            //判斷圖像類型   
{  
	RGBQUAD ColorTab[256];  
	int     k;  

	if (pImgm->IsNull()) return(0);  

	switch(pImgm->GetBPP())  
	{  
	case 1:  k=0;   break;   
	case 4:  k=1;   break;   
	case 8:  k=3;   break;   
	default: k=4;   break;   
	}  

	if (k==3)                    
	{  
		pImgm->GetColorTable(0,256,ColorTab);  
		k=PaletteType(ColorTab);  
	}  
	return(k);  
} 
void CIProcess::RotateCimage(CImage *Imgm, CImage *Imgn, double alpha)  
{  
	IMAGEPARAMENT P;   
	RGBQUAD ColorTab[256];   
	int i, j, ww, Xd, Yd, Dx, Dy,nSize;   
	double centerx, centery, sintheta, costheta;   
	double X1, Y1, X2, Y2, theta, xx, yy, rr;   
	BYTE **list, *sc;   
	int x1, y1, x2, y2, flag;   
	double p, q, a, b, c, d, t1, t2, t3;   

	if (ImageType(Imgm) == 2)  flag = 1; //flag爲標誌位,當取值爲1時,表示雙線性內插法 ,此時圖像類型爲灰階圖像  
	else flag = 0; //0表示最近鄰點法   
	GetImageParament(Imgm, &P);   

	Dx = P.nWidth;   
	Dy = P.nHeight;   
	nSize = 0;  
	if (Dx < Dy)  
	{  
		nSize = Dy;  
	}  
	else  
	{  
		nSize = Dx;  
	}  
	int nLineBytes = (nSize * P.nBitCount + 31) / 32 * 4;  

	//還有一點要修改,否則當圖像高度遠大於寬度時會崩潰  
	sc = (BYTE*) malloc(2 * nLineBytes);    // * P.nBytesPerLine); //申請工做單元   
	//  
	list = (BYTE**) malloc(Dy * sizeof(BYTE*)); //對原位圖創建二維數組   
	for (i = 0; i < Dy; i++)   
		list[i] = (BYTE*)  Imgm ->GetPixelAddress(0, i);   

	centerx = Dx / 2; //計算位圖中心位置   
	centery = Dy / 2;   
	rr = sqrt(centerx * centerx + centery *centery); //計算對角線長度   

	theta = atan((double) centery / (double) centerx);   
	alpha = alpha*3.14159265/180;
	X1 = fabs(rr * cos(alpha + theta)) + 0.5;   
	Y1 = fabs(rr * sin(alpha + theta)) + 0.5;   
	X2 = fabs(rr * cos(alpha - theta)) + 0.5;   
	Y2 = fabs(rr * sin(alpha - theta)) + 0.5;   

	if (X2 > X1) X1 = X2; //得外接矩形寬度   
	if (Y2 > Y1) Y1 = Y2; //外接矩形高度   
	ww = (int) (2 * X1);   

	Imgn ->Destroy();   

	Imgn ->Create(ww, (int) (2 * Y1), P.nBitCount ); //創建結果位圖   
	if (P.nBitCount == 8)   
	{   
		GetAllPalette(Imgm, ColorTab);   
		//修改一,設置目標調色板  
		SetAllPalette(Imgn, ColorTab); //複製調色板   
	}   
	sintheta = sin(alpha);   
	costheta = cos(alpha);   

	for (j = (int) (centery - Y1), Yd = 0; j <= (centery + Y1); j++, Yd++)   
	{   
		if (P.nBitCount == 8)   
			memset (sc, 0, ww); //256色位圖像素行置背景值   
		else   
			memset(sc, 0, ww * P.nBytesPerPixel); //真彩色位圖像素行置背景值   

		for (i = (int) (centerx - X1), Xd = 0; i <= centerx + X1; i++, Xd += P.nBytesPerPixel)   
		{   
			xx = centerx + costheta * (i - centerx) + sintheta * (j - centery);   
			yy = centery - sintheta * (i - centerx) + costheta * (j - centery);   
			x1 = (int) xx;   
			x2 = x1 + 1;   
			p = xx - x1;   
			y1 = (int) yy;   
			y2 = y1 + 1;   
			q = yy - y1;   
			if (((x1 < 0)||(x2 >= P.nWidth )||(y1 < 0)||(y2 >= P.nHeight )))   
				continue;   
			if (flag == 0)   
			{   
				if (q > 0.5)  y1 = y2;   
				if (p > 0.5)  x1 = x2;   
				//修改二, sc[Xd]  
				memcpy(&sc[Xd], &list[y1][x1 * P.nBytesPerPixel], P.nBytesPerPixel); //從源位圖複製像素數據   
			}   
			else   
			{ // flag等於1,雙線性內插法   
				a = (double) list[y1][x1]; //從源位圖取數據   
				b = (double) list[y1][x2];   
				c = (double) list[y2][x1];   
				d = (double) list[y2][x2];   
				t1 = (1 - p) * a + p * b; //雙線性內插計算   
				t2 = (1 - p) * c + p * d;   
				t3 = (1 - q) * t1 + q * t2;   
				//修改三  
				sc[Xd] = (BYTE) t3;   
			}   
		}   
		SetRectValue(Imgn, 0, Yd, ww, 1, sc);   
	}   
	free(list); //釋放工做單元   
	free(sc);  
}
相關文章
相關標籤/搜索