第二章 图像的显示

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后面没有分号
View Code

 

 

 

二、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();
以上是关于第二章 图像的显示的主要内容,如果未能解决你的问题,请参考以下文章

片段不起作用并且有错误

如何从片段中检索gridview中的图像?

相同的片段与不同选项卡上的列表视图

如何在来自 Firebase 存储的片段 ImageView 中显示图像

滚动时在另一个片段视频视图中重叠一个片段的视频拇指

使用选项卡第二次返回片段显示空白片段