ImageSize[i]=black; countWidth++; continue;
}
elseif(i>=Place&&countWidth>=dlg.m_xPY*3){//图像像素平移区域
ImageSize[i]=m_pImage[m_pImagePlace];//原(0,0)像素赋值过去
m_pImagePlace++; countWidth++;
if(countWidth==m_nWidth*3){ //一行填满 m_pImagePlace走到(0,1)
number++; m_pImagePlace=number*m_nWidth*3;
}
}
}
5.写文件绘图fwrite(ImageSize,m_nImage,1,fpw)
第一步:
在ResourceView资源视图中,添加Menu子菜单如下:
(注意ID号)
第二步:
设置平移对话框。
将试图切换到ResourceView界面--选中Dialog,右键鼠标新建一个Dialog,并新建一个名为IDD_DIALOG_PY。
编辑框(X)IDC_EDIT_PYX和(Y)IDC_EDIT_PYY,确定为默认按钮。
设置成下图对话框:
第三步:
在对话框资源模板空白区域双击鼠标—Createanewclass创建一个新类--命名为CImagePYDlg。
会自动生成它的.h和.cpp文件。
打开类向导(CtrlW),选择类名:
CImagePYDlg添加成员变量如下图所示,同时在MessageMaps中生成ID_JHBH_PY实现函数。
第四步:
在CImageProcessingView.cpp中添加头文件#include"ImagePYDlg.h",并实现平移。
[cpp] viewplain copy
1./********************************************************/
2./* 图像空间几何变换:
图像平移 ID_JHBH_PY(几何变换-平移)
3./* 使用平移对话框:
CImagePYDlg dlg
4./* 算法:
f(x,y)=f(x+x0,y+y0)图像所有点平移,空的补黑'0'
5./* 注意该图像平移方法只是从左上角(0,0)处开始平移
6./* 其他方向原理相同 自己去实现
7./********************************************************/
8.
9.void CImageProcessingView:
:
OnJhbhPy()
10.{
11. if(numPicture==0) {
12. AfxMessageBox("载入图片后才能空间平移!
",MB_OK,0);
13. return;
14. }
15. //定义采样对话框也是用来空间变换平移的坐标
16. CImagePYDlg dlg;
17. if( dlg.DoModal()==IDOK ) //显示对话框
18. {
19. //采样坐标最初为图片的自身像素
20. if( dlg.m_xPY>m_nWidth || dlg.m_yPY>m_nHeight ) {
21. AfxMessageBox("图片平移不能为超过原图长宽!
",MB_OK,0);
22. return;
23. }
24. AfxMessageBox("图片空间变换-平移!
",MB_OK,0);
25.
26. //打开临时的图片 读写文件
27. FILE *fpo = fopen(BmpName,"rb");
28. FILE *fpw = fopen(BmpNameLin,"wb+");
29. fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
30. fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
31. fwrite(&bfh,sizeof(BITMAPFILEHEADER),1,fpw);
32. fwrite(&bih,sizeof(BITMAPINFOHEADER),1,fpw);
33. fread(m_pImage,m_nImage,1,fpo);
34.
35. /************************************************************/
36. /* 图片空间变换-平移
37. /* 坐标(dlg.m_xPY,dlg.m_yPY)表示图像平移的坐标
38. /* 先用Plave计算出平移后的起始坐标,其他的坐标赋值为'0'黑色
39. /* 然后依次平移坐标,空的赋为黑色,否则填充
40. /************************************************************/
41.
42. /******************************************************************/
43. /* 严重错误1:
数组变量赋值相等
44. /* 在View.h中定义变量 BYTE *m_pImage 读入图片数据后的指针
45. /* 建立临时变量数组,让它平移变换 unsigned char *ImageSize
46. /* ImageSize=m_pImage(错误)
47. /* 会导致ImageSize赋值变换时m_pImage也产生了变换,所以输出全为黑色
48. /* 因为它俩指向了相同的数组地址
49. /* 解决方法:
使用下面C++的new方法动态分配或for循环i=m_nImage赋值
50. /******************************************************************/
51.
52. /*临时变量存储的像素与m_pImage相同,便于处理图像*/
53. unsigned char *ImageSize;
54. ImageSize=new unsigned char[m_nImage]; //new和delete有效的进行动态存的分配和释放
55.
56. int Place; //建立临时坐标 记录起始坐标(0,0)平移过来的位置
57. int m_pImagePlace; //原始图像平移为(0,0) 图像把它平移到Place位置
58. unsigned char black; //填充黑色='0'
59.
60. /************************************************************/
61. /* for(int i=0 ; i62. /* for(int j=0 ; j63. /* 不能使用的上面的因为可能图像的最后一行没有完整的一行像素
64. /* 这样会出现exe报错,使用m_nImage读写所有像素比较正确
65. /************************************************************/
66.
67. Place=dlg.m_yPY*m_nWidth*3; //前m_yPY行都要填充为黑色
68. black=0; //颜色为黑色
69. m_pImagePlace=0; //图像处事位置为(0,0),把该点像素平移过去
70. int countWidth=0; //记录每行的像素个数,满行时变回0
71. int number=0; //数字记录使用的像素行数,平移时使用
72.
73. for(int i=0 ; i74. {
75. /*如果每行的像素填满时清为0*/
76. if(countWidth==m_nWidth*3) {
77. countWidth=0;
78. }
79.
80. /*第一部分:
到平移后像素位置前面的所有像素点赋值为黑色*/
81. if(i82. ImageSize[i]=black; //赋值为黑色
83. continue;
84. }
85.
86. /*第二部分:
平移区域的左边部分赋值为黑色*/
87. else if(i>=Place && countWidth88. ImageSize[i]=black; //赋值为黑色
89. countWidth++;
90. continue;
91. }
92.
93. /****************************/
94. /* 各部分如图所示:
95. /* 000000000000000000000000
96. /* 000000000000000000000000
97. /* 0000000.................
98. /* 0000000.................
99. /* 0000000.................
100. /* 0000000.................
101. /* 点表示像素部分,0为黑色
102. /****************************/
103.
104. /* 重点错误提示:
由于bmp图像显示是从左下角开始存储(0,0)点所以输出图像为 */
105. /* bmp图像是从左下角到右上角排列的 */
106.
107. /****************************/
108. /* 各部分如图所示:
109. /* 0000000.................
110. /* 0000000.................
111. /* 0000000.................
112. /* 0000000.................
113. /* 000000000000000000000000
114. /* 000000000000000000000000
115. /* 点表示像素部分,0为黑色
116. /****************************/
117.
118. /*第三部分:
图像像素平移区域*/
119. else if(i>=Place && countWidth>=dlg.m_xPY*3)
120. {
121. ImageSize[i]=m_pImage[m_pImagePlace];
122. m_pImagePlace++;
123. countWidth++;
124. if(countWidth==m_nWidth*3)
125. {
126. number++;
127. m_pImagePlace=number*m_nWidth*3;
128. }
129. }
130. }
131.
132. fwrite(ImageSize,m_nImage,1,fpw);
133. fclose(fpo);
134. fclose(fpw);
135. numPicture = 2;
136. level=200; //200表示几何变换
137. Invalidate();
138. }
139.}
同时在ShowBitmap中添加level标记重新绘制图片,代码如下:
[cpp] viewplain copy
1.else //图像几何变换
2.if(level=200)
3.{
4. m_hBitmapChange = (HBITMAP) LoadImage(NULL,BmpNameLin,IMAGE_BITMAP,0,0,
5. LR_LOADFROMFILE|LR_DEFAULTSIZE|LR_CREATEDIBSECTION);
6.}
运行时需要注意一点:
BMP图像在处理过程中可能会出现一些斜线,而平移(40,60)位移量时可能出现如下。
他是因为BMP格式有个非常重要的规定,要求每一扫描的字节数据必须能被4整除,也就是Dword对齐(长度4字节),如果图像的一行字节数不能被4整除,就需要在每行末尾不起0达到标准。
例如一行像素为97字节,我们就需要补3个字节吗,数值可以是0,但是我们在BMP格式的信息头里说明了其宽度,所以补齐后对我们没有影响,所以后面补若干个字节的0即可直到被4整除。
通过后面的图像缩放后,我从学做了一遍这个补齐的缩放。
代码如下,能够实现完美平移。
nice啊~
[cpp] viewplain copy
1.void CImageProcessingView:
:
OnJhbhPy()
2.{
3. if(numPicture==0) {
4. AfxMessageBox("载入图片后才能空间平移!
",MB_OK,0);
5. return;
6. }
7. //定义采样对话框也是用来空间变换平移的坐标
8. CImagePYDlg dlg;
9. if( dlg.DoModal()==IDOK ) //显示对话框
10. {
11. //采样坐标最初为图片的自身像素
12. if( dlg.m_xPY>m_nWidth || dlg.m_yPY>m_nHeight ) {
13. AfxMessageBox("图片平移不能为超过原图长宽!
",MB_OK,0);
14. return;
15. }
16. AfxMessageBox("图片空间变换-平移!
",MB_OK,0);
17.
18. //打开临时的图片 读写文件
19. FILE *fpo = fopen(BmpName,"rb");
20. FILE *fpw = fopen(BmpNameLin,"wb+");
21. fread(&bfh,sizeof(BITMAPFILEHEADER),1,fpo);
22. fread(&bih,sizeof(BITMAPINFOHEADER),1,fpo);
23.
24. int num; //记录每行多余的图像素数个数
25. int sfSize; //补齐后的图像大小
26. //重点:
图像的每行像素都必须是4的倍数:
1*1的图像为 r g b 00H
27. if(m_nWidth*3%4!
=0)
28. {
29. num=(4-m_nWidth*3%4);
30. sfSize=(m_nWidth*3+num)*m_nHeight; //每行多number个
31. }
32. else
33. {
34. num=0;
35. sfSize=m_nWidth*m_nHeight*3;
36. }
37. //注意:
假如最后一行像素不足,我默认处理为完整的一行,不足补00H
38. //总之处理后的图像总是m*n且为4倍数,每行都完整存在
39.
40. /*更改文件头信息 定义临时文件头结构变量*/
41.