第二章 图像的显示
Posted 和优秀的人一起成长
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第二章 图像的显示相关的知识,希望对你有一定的参考价值。
VC++图像处理程序设计(第1版) 杨淑莹 编著 边奠英 主审
第二章 图像的显示
Joanna-In-Hdu&Hust 手工打,印象更深刻
使用工具 VS2010 mfc
声明:这一章开始的代码都是本人实际演示过的,按照本人的操作可以运行。程序并没有很强的健壮性,只能对正确的操作做出符合预期的响应。
整本书的代码文件、测试图片和程序运行exe请在这里下载:https://github.com/CaptainLYN/VCPictureProcessing
由于这本书我已经做完很长时间了,对于文章中的文字的重点现在已是不甚记得了,所以在此为了避免误导,只贴出代码,代码中大都有我写这个代码时候的心得,基本上都是书中的代码,很多地方都有写注释哦,有问题的同学可以直接再代码中找一找答案~
相对于(错误百出的)原书有修改的地方大多都有说明。
说了这么多,突然想把这本书更新完,只是想做事情有始有终U•ェ•*U
正文:
一、CViewImage.h 中是第二章用到的所有函数的声明,其实是建了一个类:
1 #pragma once 2 class CDib; 3 class CViewImage:public CView 4 { 5 protected: 6 CPalette *hPalette;//这两个变量都是指针,为什么不是实体类呢?假如程序一次运行只打开一次文件,类是可以的;多次打开会出现内存错误(大家可以试一下),指针的话,没打开一次都是新建一个类,打开完了即没了,适合用指针 7 CDib *dib; 8 9 public: 10 11 void GetDib(CDib *dib2);//CObject是不能直接作为参数传递的,因为不能被复制,是私有函数 12 13 void virtual OnDraw(CDC *pDC);//CDC类是设备上下文类,用于绘图输出的,实现虚函数 14 void OnDraw2(CDC *pC,int x_move,int y_move);//原图像显示位置可以移动的绘图函数 15 void OnDraw3(CDC *pDC,LPBYTE temp,int x_move,int y_move); 16 void OnDraw4(CDC *pC,int x_move,int y_move,int need_width,int need_height);//可以在原图绘制想要的大小,并没有修改原图的info 17 18 CPalette* CreateBitmapPalette(CDib *pBitmap); 19 void OnXiangxia(CDC *pDC);//改成了有参数的,CDC在对话框中获取,在这个函数里面获取有中断问题,没解决为什么 20 void OnXiangshang(CDC *pDC);//向上扫描 21 void OnXiangyou(CDC *pDC);//向右扫描 22 void OnXiangzuo(CDC *pDC);//向左扫描 23 void ToShuiPingYouYi(CDC *pDC);//水平右移 24 void ToChuiZhiShangYi(CDC *pDC);//垂直上移 25 void ToJiaoChaFeiRu(CDC *pDC);//交叉飞入 26 void ToSiZhouKuoZhang(CDC *pDC);//四周扩张 27 void ToZhongJianShouSuo(CDC *pDC);//中间收缩 28 void ToShuiPingShanTiao(CDC *pDC);//水平栅条 29 void TOShuZhiShanTiao(CDC *pDC);//竖直栅条 30 void ToTuXiangJianXian(CDC *pDC);//图像渐显 31 void ToShuiPingBaiYeChuang(CDC* pDC);//水平百叶窗 32 void ToShuZhiBaiYeChuang(CDC* pDC);//垂直百叶窗 33 void ToMaSaiKeXianShi(CDC *pDC);//马赛克显示 34 35 };//这边少一个分号就多了20几个错误,因为include后面没有分号
二、CViewImage.cpp 是相应函数的实现,这里是要重点看的:
1 #include"stdafx.h" 2 #include"CDib.h" 3 #include<WindowsX.h> 4 5 #include"CViewImage.h" 6 7 8 void CViewImage::GetDib(CDib *dib2) 9 { 10 dib=dib2; 11 } 12 13 CPalette* CViewImage::CreateBitmapPalette(CDib* pBitmap) 14 { 15 struct mPalette//这里加上名字 16 { 17 WORD Version; 18 WORD NumberOfEntries; 19 PALETTEENTRY aEntries[256];//PALETTEENTRY指向一个逻辑调色板 20 }palette={0x300,256};//version是0x300 21 22 LPRGBQUAD pRGBTable=pBitmap->GetRGB();//LPRGBQUAD是调色板指针,只有前面是LP的都是指针 23 UINT numberOfColors=pBitmap->GetNumberOfColors(); 24 for(UINT x=0;x<numberOfColors;++x) 25 { 26 palette.aEntries[x].peRed=pRGBTable[x].rgbRed;//这是第二步,对数组元素和成员变量进行设置 27 palette.aEntries[x].peGreen=pRGBTable[x].rgbGreen; 28 palette.aEntries[x].peBlue=pRGBTable[x].rgbBlue; 29 palette.aEntries[x].peFlags=0;//指定调色板如何使用:PC_EXPLICIT(2) PC_NOCOLLAPSE(4) PC_RESERVED(1) 30 } 31 hPalette=new CPalette; 32 hPalette->CreatePalette((LPLOGPALETTE)&palette);//初始化调色板对象, 33 return hPalette; 34 } 35 36 void CViewImage::OnDraw(CDC* pDC)//这个函数是一个必须要实现的虚函数,所以即使不大实用也要实现 37 { 38 int m_scale=1;//控制缩放比例 39 BYTE* pBitmapData=dib->GetData();//CDib类的指针对象,其内容还没有想好赋值 40 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 41 int bitmapHeight=dib->GetHeight(); 42 int bitmapWidth=dib->GetWidth(); 43 int scaledWidth=(int)(bitmapWidth* m_scale); 44 int scaledHeight=(int)(bitmapHeight* m_scale); 45 if(dib->GetRGB()) 46 { 47 CPalette* hPalette=CreateBitmapPalette(dib);//建立CPlalette对象并初始化调色板对象 48 CPalette* hOldPalette=pDC->SelectPalette(hPalette,true);//为true表示后台调色板,将已创建的调色板调用到设备上下文中,并且返回旧的调色板 49 //上面这个SelectPalette返回的就是老的调色板 50 pDC->RealizePalette();//使调色板生效 51 //前面加::表面调用的是win api,是全局函数,不是局部继承的函数 52 ::StretchDIBits(pDC->GetSafeHdc(),0,0,scaledWidth,scaledHeight,0,0,bitmapWidth,bitmapHeight,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 53 //设备上下文句柄 54 pDC->SelectPalette(hOldPalette,true); 55 ::DeleteObject(hPalette);//释放关于hPalette调色板的一切资源(逻辑笔、画笔、字体、位图、区域或调色板) 56 } 57 else//24位真彩色 58 { 59 ::StretchDIBits(pDC->GetSafeHdc(),0,0,scaledWidth,scaledHeight,0,0,bitmapWidth,bitmapHeight,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 60 } 61 62 } 63 64 void CViewImage::OnDraw2(CDC* pDC,int x_move,int y_move)//这个才是我们需要用的绘制函数 65 { 66 int m_scale=1;//控制缩放比例 67 BYTE* pBitmapData=dib->GetData();//CDib类的指针对象 68 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 69 int bitmapHeight=dib->GetHeight(); 70 int bitmapWidth=dib->GetWidth(); 71 int scaledWidth=(int)(bitmapWidth* m_scale); 72 int scaledHeight=(int)(bitmapHeight* m_scale); 73 if(dib->GetRGB()) 74 { 75 CPalette* hPalette=CreateBitmapPalette(dib);//建立CPlalette对象并初始化调色板对象 76 CPalette* hOldPalette=pDC->SelectPalette(hPalette,true);//为true表示后台调色板,将已创建的调色板调用到设备上下文中,并且返回旧的调色板 77 //上面这个SelectPalette返回的就是老的调色板 78 pDC->RealizePalette();//使调色板生效 79 //前面加::表面调用的是win api,是全局函数,不是局部继承的函数 80 ::StretchDIBits(pDC->GetSafeHdc(),0+x_move,0+y_move,scaledWidth,scaledHeight,0,0,bitmapWidth,bitmapHeight,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 81 //设备上下文句柄 82 pDC->SelectPalette(hOldPalette,true); 83 ::DeleteObject(hPalette);//释放关于hPalette调色板的一切资源(逻辑笔、画笔、字体、位图、区域或调色板) 84 } 85 else//24位真彩色 86 { 87 ::StretchDIBits(pDC->GetSafeHdc(),0+x_move,0+y_move,scaledWidth,scaledHeight,0,0,bitmapWidth,bitmapHeight,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 88 } 89 90 } 91 92 void CViewImage::OnDraw3(CDC *pDC,LPBYTE temp,int x_move,int y_move) 93 { 94 int m_scale=1;//控制缩放比例 95 //BYTE* pBitmapData=dib->GetData();//CDib类的指针对象 96 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 97 int bitmapHeight=dib->GetHeight(); 98 int bitmapWidth=dib->GetWidth(); 99 int scaledWidth=(int)(bitmapWidth* m_scale); 100 int scaledHeight=(int)(bitmapHeight* m_scale); 101 if(dib->GetRGB()) 102 { 103 CPalette* hPalette=CreateBitmapPalette(dib);//建立CPlalette对象并初始化调色板对象 104 CPalette* hOldPalette=pDC->SelectPalette(hPalette,true);//为true表示后台调色板,将已创建的调色板调用到设备上下文中,并且返回旧的调色板 105 //上面这个SelectPalette返回的就是老的调色板 106 pDC->RealizePalette();//使调色板生效 107 //前面加::表面调用的是win api,是全局函数,不是局部继承的函数 108 ::StretchDIBits(pDC->GetSafeHdc(),0+x_move,0+y_move,scaledWidth,scaledHeight,0,0,bitmapWidth,bitmapHeight,temp,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 109 //设备上下文句柄 110 pDC->SelectPalette(hOldPalette,true); 111 ::DeleteObject(hPalette);//释放关于hPalette调色板的一切资源(逻辑笔、画笔、字体、位图、区域或调色板) 112 } 113 else//24位真彩色 114 { 115 ::StretchDIBits(pDC->GetSafeHdc(),0+x_move,0+y_move,scaledWidth,scaledHeight,0,0,bitmapWidth,bitmapHeight,temp,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 116 } 117 118 } 119 120 void CViewImage::OnDraw4(CDC *pDC,int x_move,int y_move,int need_width,int need_height) 121 { 122 int m_scale=1;//控制缩放比例 123 //BYTE* pBitmapData=dib->GetData();//CDib类的指针对象 124 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 125 /*int bitmapHeight=dib->GetHeight(); 126 int bitmapWidth=dib->GetWidth();*/ 127 int scaledWidth=(int)(need_width* m_scale); 128 int scaledHeight=(int)(need_height* m_scale); 129 if(dib->GetRGB()) 130 { 131 CPalette* hPalette=CreateBitmapPalette(dib);//建立CPlalette对象并初始化调色板对象 132 CPalette* hOldPalette=pDC->SelectPalette(hPalette,true);//为true表示后台调色板,将已创建的调色板调用到设备上下文中,并且返回旧的调色板 133 //上面这个SelectPalette返回的就是老的调色板 134 pDC->RealizePalette();//使调色板生效 135 //前面加::表面调用的是win api,是全局函数,不是局部继承的函数 136 ::StretchDIBits(pDC->GetSafeHdc(),0+x_move,0+y_move,scaledWidth,scaledHeight,0,0,need_width,need_height,dib->GetData(),pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 137 //设备上下文句柄 138 pDC->SelectPalette(hOldPalette,true); 139 ::DeleteObject(hPalette);//释放关于hPalette调色板的一切资源(逻辑笔、画笔、字体、位图、区域或调色板) 140 } 141 else//24位真彩色 142 { 143 ::StretchDIBits(pDC->GetSafeHdc(),0+x_move,0+y_move,scaledWidth,scaledHeight,0,0,need_width,need_height,dib->GetData(),pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 144 } 145 146 } 147 148 void CViewImage::OnXiangxia(CDC *pDC)//向下扫描 149 { 150 //CDC *pDC=GetDC(); 151 152 // clearmem();//复制图像数据,取得原始图像的拷贝文件???找不到 153 CDocument *pDoc=GetDocument();//返回与本视图连接的文档类对象指针,这边改了 154 155 //ASSERT_VALID(pDoc);//判断指向的对象是否为空,debug下有效 156 //if(!pDoc->stateddoc&&state2==1)//??????????? 157 //{ 158 BYTE* pBitmapData=dib->GetData();//将书中的伪变量换成了自己设的 159 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 160 int bitmapHeight=dib->GetHeight(); 161 int bitmapWidth=dib->GetWidth(); 162 163 if(dib->GetRGB())//如果颜色表指针不为空 164 { 165 CRect rect(bitmapWidth+5,0,2*bitmapWidth+5,bitmapHeight);//一个矩形类 166 CBrush brush(RGB(255,255,255)); 167 pDC->FillRect(&rect,&brush);//将整个矩阵用白色填满,图像的区域是不包含右边和下边 168 169 CPalette* hPalette=CreateBitmapPalette(dib); 170 CPalette* hOldPalette=pDC->SelectPalette(hPalette,true); 171 pDC->RealizePalette(); 172 for(int j=0;j<bitmapHeight;j++) 173 { 174 //修改了第7个参数,比原书-1,书那样是不对的 175 //图像横着是x轴,竖着向下是y轴 176 ::StretchDIBits(pDC->GetSafeHdc(),bitmapWidth+5,j,bitmapWidth,1,0,bitmapHeight-j-1,bitmapWidth,1,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 177 //1是设备上下文句柄,2、3参数是绘制图像左上角坐标,4、5是绘制图像的宽度和高度,6、7是要绘制的原图的左下角坐标(--假如坐标超出了,绘制图像相应区域会以白色代替--)(注意,位图行的存储是颠倒的,所以是倒着复制),8、9是原图宽度和高度,10是指向图像数据的指针,11是指向图像BITMAPINFO结构的指针,12是bmiColors包含真实的RGB值还是调色板中的索引值,13指定要进行的光栅运算 178 //如果目标矩阵大于要复制的原图区域就进行行和列的拉伸,反之利用光栅操作进行压缩 179 Sleep(5);//延时5毫秒 180 } 181 pDC->SelectPalette(hOldPalette,true); 182 ::DeleteObject(hPalette); 183 } 184 // } 185 //Invalidate();//刷新,调用会出现中断 186 } 187 void CViewImage::OnXiangshang(CDC *pDC)//向上扫描 188 { 189 //CDocument *pDoc=GetDocument(); 190 BYTE* pBitmapData=dib->GetData(); 191 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 192 int bitmapHeight=dib->GetHeight(); 193 int bitmapWidth=dib->GetWidth(); 194 195 if(dib->GetRGB()) 196 { 197 CRect rect(bitmapWidth+5,0,bitmapWidth*2+5,bitmapHeight);//一个矩形类 198 CBrush brush(RGB(255,255,255)); 199 pDC->FillRect(&rect,&brush);//将整个矩阵用白色填满,但是只包括矩阵的左上边界,不包括右下边界 200 201 CPalette* hPalette=CreateBitmapPalette(dib); 202 CPalette* hOldPalette=pDC->SelectPalette(hPalette,true); 203 pDC->RealizePalette(); 204 for(int j=0;j<bitmapHeight;j++) 205 { 206 207 ::StretchDIBits(pDC->GetSafeHdc(),bitmapWidth+5,bitmapHeight-j-1,bitmapWidth,1,0,j,bitmapWidth,1,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 208 Sleep(5); 209 } 210 pDC->SelectPalette(hOldPalette,true); 211 ::DeleteObject(hPalette); 212 } 213 } 214 void CViewImage::OnXiangyou(CDC *pDC)//向右扫描 215 { 216 //CDocument *pDoc=GetDocument(); 217 BYTE* pBitmapData=dib->GetData(); 218 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 219 int bitmapHeight=dib->GetHeight(); 220 int bitmapWidth=dib->GetWidth(); 221 222 if(dib->GetRGB()) 223 { 224 225 CRect rect(bitmapWidth+5,0,2*bitmapWidth+5,bitmapHeight); 226 CBrush brush(RGB(255,255,255)); 227 pDC->FillRect(&rect,&brush); 228 229 CPalette *hPalette=CreateBitmapPalette(dib); 230 CPalette *hOldPalette=pDC->SelectPalette(hPalette,true); 231 pDC->RealizePalette(); 232 for(int i=0;i<bitmapWidth;i++) 233 { 234 ::StretchDIBits(pDC->GetSafeHdc(),i+bitmapWidth+5,0,1,bitmapHeight,i,0,1,bitmapHeight,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 235 Sleep(5); 236 } 237 pDC->SelectPalette(hOldPalette,true); 238 ::DeleteObject(hPalette); 239 } 240 } 241 void CViewImage::OnXiangzuo(CDC *pDC)//向左扫描 242 { 243 //CDocument *pDoc=GetDocument(); 244 BYTE* pBitmapData=dib->GetData(); 245 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 246 int bitmapHeight=dib->GetHeight(); 247 int bitmapWidth=dib->GetWidth(); 248 249 if(dib->GetRGB()) 250 { 251 CRect rect(bitmapWidth+5,0,2*bitmapWidth+5,bitmapHeight); 252 CBrush brush(RGB(255,255,255)); 253 pDC->FillRect(&rect,&brush); 254 255 CPalette* hPalette=CreateBitmapPalette(dib); 256 CPalette *hOldPalette=pDC->SelectPalette(hPalette,true); 257 pDC->RealizePalette(); 258 for(int i=0;i<bitmapWidth;i++) 259 { 260 ::StretchDIBits(pDC->GetSafeHdc(),2*bitmapWidth-i+4,0,1,bitmapHeight,bitmapWidth-i-1,0,1,bitmapHeight,pBitmapData,pBitmapInfo,DIB_RGB_COLORS,SRCCOPY); 261 Sleep(5); 262 } 263 pDC->SelectPalette(hOldPalette,true); 264 ::DeleteObject(hPalette); 265 } 266 } 267 void CViewImage::ToShuiPingYouYi(CDC *pDC)//水平右移 268 { 269 //CDocument *pDoc=GetDocument(); 270 271 BYTE* pBitmapData=dib->GetData(); 272 LPBITMAPINFO pBitmapInfo=dib->GetInfo(); 273 int bitmapHeight=dib->GetHeight(); 274 int bitmapWidth=dib->GetWidth(); 275 276 if(dib->GetRGB()) 277 { 278 CRect rect(bitmapWidth+5,0,2*bitmapWidth+5,bitmapHeight); 279 CBrush brush(RGB(255,255,255)); 280 pDC->FillRect(&rect,&brush); 281 282 CPalette *hPalette=CreateBitmapPalette(dib); 283 CPalette *hOldPalette=pDC->SelectPalette(hPalette,true); 284 pDC->RealizePalette(); 以上是关于第二章 图像的显示的主要内容,如果未能解决你的问题,请参考以下文章