頭文件: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); }