第三章 图像的几何变换

VC++图像处理程序设计(第1版)    杨淑莹 编著     边奠英 主审

第二章 图像的几何变换

Joanna-In-Hdu&Hust 手工打,印象更深刻

使用工具 VS2010 mfc

声明:这一章开始的代码都是本人实际演示过的,按照本人的操作可以运行。程序并没有很强的健壮性,只能对正确的操作做出符合预期的响应。

整本书的代码文件、测试图片和程序运行exe请在这里下载https://github.com/CaptainLYN/VCPictureProcessing

这一章中如之前一样,会有很对的错误,比如循环里面的边界有时候会少一多一等,大部分修改的部分都在代码后面说明了,喜欢的同学可以直接拷下来运行试试效果,或者直接前往上面的链接下载源文件。代码都是以类的形式建立的。

一、建立JHBHDib.h头文件,建立类,声明好我们需要实现的函数:

 1 #pragma once
 2 class CDib;
 3 class JHBHDib:public CObject
 4 {
 5 protected:
 6     CDib *dib;
 7 public:
 8     void GetDib(CDib* cdib);
 9     JHBHDib();
10     ~JHBHDib();
11     void PingYi(int m_Xmove,int m_Ymove);
12     void JingXiang(bool fangshi);
13
14     //内存一定要在主程序申请,否则程序结束就收回了
15     LPBYTE FangDa(LPBYTE temp,int xzoom,int yzoom,long width,long height,int newwidth,int newheight);//横和纵的放大倍数,这里降低一下要求,是int
16     void SuoXiao(float xzoom,float yzoom);
17     LPBYTE ZhuanZhi();
18     LPBYTE XuanZhuan(double RotateAngle);
19     double RADIAN(double RotateAngle);
20
21 };

二、建立JHBHDib.cpp,用于实现类中的方法,也就是书中的所有功能函数,有一些函数我可能根据现实需要把参数修改了,嘿嘿嘿,不太记得了哈。另外,我觉得我写代码的一个有点就是注释丰富,同时,不得不说,这也是我的一个缺点,但是没有办法,我不会的地方实在太多了,另一方面,更是为了以后不要看不懂啊(。^▽^):

  1 #include"stdafx.h"
  2 #include"JHBHDib.h"
  3 #include"CDib.h"
  4 #include<WindowsX.h>
  5 #define _USE_MATH_DEFINES
  6 #include<cmath>
  7 JHBHDib::JHBHDib()
  8 {}
  9 JHBHDib::~JHBHDib()
 10 {}
 11 void JHBHDib::GetDib(CDib *cdib)
 12 {
 13     dib=cdib;
 14 }
 15 void JHBHDib::PingYi(int m_Xmove,int m_Ymove)//图像平移
 16 {
 17     LPBYTE lpSrc;//指向原图像像素的指针
 18     LPBYTE p_data;//指向原图像数据
 19
 20     LPBYTE lpDst;//指向要像素的指针
 21     LPBYTE temp;//指向复制图像数据的指针
 22     LONG i;//循环变量
 23     LONG wide,height;//图像的高和宽
 24     LONG lLineBytes;//图像每行的字节数
 25     p_data=dib->GetData();
 26     wide=dib->GetWidth();
 27     height=dib->GetHeight();
 28     lLineBytes=((wide*8)+31)/32*4;//计算图像每行的字节数:!!!!4字节对齐,不足补零
 29     temp=new BYTE[lLineBytes*height];//暂时分配内存,以保存新图像
 30     lpDst=(LPBYTE)temp;
 31     memset(lpDst,(BYTE)0,lLineBytes*height);//初始化新分配的内存,初始值为255
 32     for(i=0;i<wide;i++)//一竖列一竖列的复制
 33     {
 34         for(int j=0;j<height;j++)
 35         {
 36             lpSrc=(LPBYTE)p_data+lLineBytes*(height-1-j)+i;//计算该像素在原dib中的坐标
 37             int i0,j0;
 38             i0=i+m_Xmove;//计算该像素在新dib中的坐标
 39             j0=j+m_Ymove;
 40             if(i0>=0&&i0<wide&&j0>=0&&j0<height)//判断是否在新图范围内
 41             {
 42                 lpDst=(LPBYTE)temp+lLineBytes*(height-1-j0)+i0;
 43                 *lpDst=*lpSrc;//复制像素
 44             }
 45             else
 46             {
 47                 //lpDst=(LPBYTE)temp+lLineBytes*(height-1+j)+i;
 48                 //下面这个完全多余
 49                 //*((unsigned char*)lpDst)=255;//对于原图中没有的像素直接赋值为255
 50             }
 51         }
 52     }
 53     memcpy(p_data,temp,lLineBytes*height);//赋值平移后的图像:将temp指向的数据复制到p_data
 54     delete []temp;//释放内存
 55 }
 56 void JHBHDib::JingXiang(bool fangshi)//镜像变换,true是水平镜像,false是垂直镜像
 57 {
 58     LPBYTE lpSrc;
 59     LPBYTE p_data;
 60     LPBYTE lpDst;
 61     LPBYTE temp;
 62     LONG i,j;
 63     long height=dib->GetHeight();
 64     long width=dib->GetWidth();
 65     p_data=dib->GetData();
 66     temp=new BYTE[width*height];
 67     if(fangshi)
 68     {
 69         for(j=0;j<height;j++)
 70         {
 71             for(i=0;i<width;i++)
 72             {
 73                 lpSrc=(LPBYTE)p_data+width*j+i;
 74                 lpDst=(LPBYTE)temp+width*(j+1)-i-1;//一定要减一
 75                 *lpDst=*lpSrc;
 76             }
 77         }
 78     }
 79     else{
 80         for(i=0;i<width;i++)
 81             for(j=0;j<height;j++)
 82             {
 83                 lpSrc=(LPBYTE)p_data+j*width+i;
 84                 lpDst=(LPBYTE)temp+width*(height-j-1)+i;
 85                 *lpDst=*lpSrc;
 86             }
 87     }
 88     memcpy(p_data,temp,width*height);
 89     delete []temp;
 90 }
 91
 92 LPBYTE JHBHDib::FangDa(LPBYTE temp,int xzoom,int yzoom,long width,long height,int newwidth,int newheight)//图像的放大,这里改了xzoom和yzoom,因为程序下面要用的也是int,不如直接给int
 93 {
 94     LPBYTE p_data;//指向原图像
 95     p_data=dib->GetData();
 96     LPBYTE lpSrc;//指向原像素
 97     LPBYTE lpDst;
 98     long i,j,i0,j0;//,height,width;
 99     int srclinebyte=((width*8+31)/32)*4;
100     int dstlinebyte=((newwidth*8+31)/32)*4;
101     for(j=0;j<height;j++)
102         for(i=0;i<width;i++)
103         {
104             lpSrc=(LPBYTE)p_data+srclinebyte*j+i;
105             for(j0=0;j0<yzoom;j0++)
106                 for(i0=0;i0<xzoom;i0++)
107                 {
108                     lpDst=(LPBYTE)temp+dstlinebyte*(j*yzoom+j0)+i*xzoom+i0;
109                     //                          行数           新点坐标
110                     *lpDst=*lpSrc;
111                 }
112         }
113         return temp;
114 }
115
116 void JHBHDib::SuoXiao(float xzoom,float yzoom)
117 {
118     long width,height,newwidth,newheight,i,j,i0,j0;
119     LPBYTE p_data,temp,lpSrc,lpDst;
120
121     temp=dib->GetData();
122     p_data=temp;
123     width=dib->GetWidth();
124     height=dib->GetHeight();
125     newwidth=(long)(width*xzoom+0.5);
126     newheight=(long)(height*yzoom+0.5);
127     int newlinebytes,linebytes;
128
129     if(dib->GetInfo()->bmiHeader.biBitCount==8)//现在就针对灰度图进行运算
130     {
131         linebytes=((width*8+31)/32)*4;
132         newlinebytes=((newwidth*8+31)/32)*4;
133         temp=new BYTE[newlinebytes*newheight];
134         for(j=0;j<newheight;j++)
135             for(i=0;i<newwidth;i++)
136             {
137                 lpDst=(LPBYTE)temp+newlinebytes*j+i;
138                 //计算该点在原图中的位置
139                 j0=(LONG)(j/yzoom+0.5);
140                 i0=(LONG)(i/xzoom+0.5);
141                 if((i0>=0&&i0<width)&&(j0>=0&&j0<height))//虽然这里加了判断,但是感觉理论上是不可能不在原图的
142                 {
143                     lpSrc=(LPBYTE)p_data+j0*linebytes+i0;
144                     *lpDst=*lpSrc;
145                 }
146                 else
147                 {
148                     *lpDst=255;
149                 }
150             }
151
152             for(j=0;j<height;j++)
153                 for(i=0;i<width;i++)
154                 {
155                     if(j<newheight&&i<newwidth)
156                     {
157                     lpDst=(LPBYTE)temp+newlinebytes*j+i;
158                     *p_data=*lpDst;
159                     }
160                     else *p_data=0;
161                     p_data++;
162                 }
163                 delete[]temp;
164         //这里的处理方式和放大是不一样的
165
166     }
167 }
168 LPBYTE JHBHDib::ZhuanZhi()
169 {
170     long width=dib->GetWidth();
171     long height=dib->GetHeight();
172     int linebytes=((width*8+31)/32)*4;
173     int newlinebytes=(height*8+31)/32*4;
174     int i,j;
175     LPBYTE lpSrc,lpDst,temp,p_data;
176     temp=new BYTE[newlinebytes*width];
177     memset(temp,(BYTE)0,newlinebytes*width);
178     p_data=dib->GetData();
179     for(j=0;j<height;j++)
180         for(i=0;i<width;i++)
181         {
182             lpSrc=(LPBYTE)p_data+linebytes*j+i;
183             lpDst=(LPBYTE)temp+newlinebytes*i+j;
184             *lpDst=*lpSrc;
185         }
186         //不用下面这些书因为,图像转置后由于有四字节对齐,所以大小可能会变大,所以,dib类里面销毁的时候大小不对,会出现错误
187         dib->GetInfo()->bmiHeader.biHeight=width;
188         dib->GetInfo()->bmiHeader.biWidth=height;
189         dib->GetInfo()->bmiHeader.biSizeImage=newlinebytes*width;
190         //memcpy(p_data,temp,height*width);//这里这样写linebytes*newlinebytes,否则4字节对齐数据不全会出现边缘彩色
191         //delete(temp);
192         return temp;
193 }
194 double JHBHDib::RADIAN(double RotateAngle)
195 {
196     return RotateAngle*M_PI/180;//要有最上面那个define才行
197 }
198
199 LPBYTE JHBHDib::XuanZhuan(double RotateAngle)//原理看懂了,以后不懂的话看pdf版的就可以了
200 {
201     DWORD DstBufSize;
202     LPBYTE lpTempPtr,lpPtr,lpSrc,lpTemp;
203     double SrcX1,SrcY1,SrcX2,SrcY2,SrcX3,SrcY3,SrcX4,SrcY4;
204     double DstX1,DstY1,DstX2,DstY2,DstX3,DstY3,DstX4,DstY4;
205     DWORD Wold,Hold,Wnew,Hnew;
206     DWORD x0,y0,x1,y1;
207     double cosa,sina;//cos(a),sin(a)
208     double num1,num2;
209
210     //角度到弧度的变化
211     RotateAngle=(double)RADIAN(RotateAngle);
212     cosa=(double)cos((double)RotateAngle);
213     sina=(double)sin((double)RotateAngle);
214
215     //CString s;
216     //s.Format(_T("%lf"),RotateAngle);//将RotateAngle转化为字符串
217     //MessageBox(NULL,s,_T("提示"),MB_OK);//用来测试对不对
218
219     lpSrc=dib->GetData();
220     Wold=dib->GetWidth();
221     Hold=dib->GetHeight();
222     //原图的4个角的坐标
223     SrcX1=(double)(-0.5*Wold);
224     SrcY1=(double)(0.5*Hold);
225     SrcX2=(double)(0.5*Wold);
226     SrcY2=(double)(0.5*Hold);
227     SrcX3=(double)(-0.5*Wold);
228     SrcY3=(double)(-0.5*Hold);
229     SrcX4=(double)(0.5*Wold);
230     SrcY4=(double)(-0.5*Hold);
231     //新图的四个角坐标
232     DstX1=cosa*SrcX1+sina*SrcY1;
233     DstY1=-sina*SrcX1+cosa*SrcY1;
234     DstX2=cosa*SrcX2+sina*SrcY2;
235     DstY2=-sina*SrcX2+cosa*SrcY2;
236     DstX3=cosa*SrcX3+sina*SrcY3;
237     DstY3=-sina*SrcX3+cosa*SrcY3;
238     DstX4=cosa*SrcX4+sina*SrcY4;
239     DstY4=-sina*SrcX4+cosa*SrcY4;
240     //新图的宽度和高度
241     Wnew=(DWORD)(max(fabs(DstX4-DstX1),fabs(DstX3-DstX2))+0.5);
242     Hnew=(DWORD)(max(fabs(DstY4-DstY1),fabs(DstY3-DstY2))+0.5);
243     //计算矩阵中的两个常数,这样不用每次都算
244     num1=(double)(-0.5*Wnew*cosa-0.5*Hnew*sina+0.5*Wold);
245     num2=(double)(0.5*Wnew*sina-0.5*Hnew*cosa+0.5*Hold);
246
247     //这里我选择linebytes,书上不是
248     int newlinebytes=((Wnew*8+31)/32)*4;
249     int linebytes=((Wold*8+31)/32)*4;
250
251     DstBufSize=newlinebytes*Hnew;
252     //DstBufSize=Wnew*Hnew;
253     //原书填入的是白色,虽然我认为要填黑色,但是为了显示效果,还是先暂且选择白色
254     //关于缓冲区,有时候书上是linebytes,有时候又是简单的高和宽的乘积??
255     lpTempPtr=new BYTE[DstBufSize];
256     memset(lpTempPtr,(BYTE)255,DstBufSize);
257     lpTemp=lpTempPtr;//保存住总入口
258     for(y1=0;y1<Hnew;y1++)
259     {
260         for(x1=0;x1<Wnew;x1++)
261         {
262             //x0,y0是该点在原图上的坐标
263             x0=(DWORD)(x1*cosa+y1*sina+num1);
264             y0=(DWORD)(-1.0f*x1*sina+y1*cosa+num2);
265             if(x0>=0&&x0<Wold&&y0>=0&&y0<Hold)//在原图范围内
266             {
267                 lpPtr=lpSrc+y0*linebytes+x0;
268                 //lpPtr=lpSrc+y0*Wold+x0;//像原书这样是不对的
269                 lpTempPtr=lpTemp+y1*newlinebytes+x1;
270                 //lpTempPtr=lpTemp+y1*Wnew+x1;
271                 *lpTempPtr=*lpPtr;
272
273                 //lpTempPtr=lpTemp;
274
275             }
276         }
277     }
278     dib->GetInfo()->bmiHeader.biHeight=Hnew;
279     dib->GetInfo()->bmiHeader.biWidth=Wnew;
280     dib->GetInfo()->bmiHeader.biSizeImage=newlinebytes*Hnew;
281
282     return lpTemp;
283 }

三、在菜单栏添加函数,并添加相应的事件处理程序:

四、MfcPictureProcessingDlg.cpp中的事件处理程序,即我们辛苦编写的调用函数:

  1 void CMfcPictureProcessingDlg::On32789()//图像平移
  2 {
  3     CDib dib;
  4     if(filePath.Compare(_T(""))!=0)
  5     {
  6         dib.LoadFile(filePath);
  7         if(dib.m_valid)
  8         {
  9             CDC* pDC=GetDC();
 10             JHBHDib jdib;
 11             jdib.GetDib(&dib);
 12             PingYiTiShi p;
 13             p.DoModal();
 14             if(p.ifok==1)//如果点击了确认键而不是点击退出的叉
 15             {
 16                 jdib.PingYi(p.GetX(),p.GetY());//核心就在这里
 17                 CViewImage imageview;
 18                 imageview.GetDib(&dib);
 19                 imageview.OnDraw2(pDC,dib.GetWidth()+5,0);
 20             }
 21         }
 22     }
 23     else{
 24         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
 25     }
 26 }
 27
 28
 29 void CMfcPictureProcessingDlg::On32790()//水平镜像
 30 {
 31     CDib dib;
 32     if(filePath.Compare(_T(""))!=0)
 33     {
 34         dib.LoadFile(filePath);
 35         if(dib.m_valid)
 36         {
 37             CDC* pDC=GetDC();
 38             JHBHDib jdib;
 39             jdib.GetDib(&dib);
 40             jdib.JingXiang(true);
 41             CViewImage imageview;
 42             imageview.GetDib(&dib);
 43             imageview.OnDraw2(pDC,dib.GetWidth()+5,0);
 44         }
 45     }
 46     else{
 47         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
 48     }
 49 }
 50
 51
 52 void CMfcPictureProcessingDlg::On32791()//垂直镜像
 53 {
 54     CDib dib;
 55     if(filePath.Compare(_T(""))!=0)
 56     {
 57         dib.LoadFile(filePath);
 58         if(dib.m_valid)
 59         {
 60             CDC* pDC=GetDC();
 61             JHBHDib jdib;
 62             jdib.GetDib(&dib);
 63             jdib.JingXiang(false);
 64             CViewImage imageview;
 65             imageview.GetDib(&dib);
 66             imageview.OnDraw2(pDC,dib.GetWidth()+5,0);
 67             DWORD a=dib.bitmapFileHeader.bfSize;
 68         }
 69     }
 70     else{
 71         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
 72     }
 73 }
 74
 75
 76
 77 void CMfcPictureProcessingDlg::On32793()//图像放大
 78 {
 79     CDib dib;
 80     if(filePath.Compare(_T(""))!=0)
 81     {
 82         dib.LoadFile(filePath);
 83         if(dib.m_valid)
 84         {
 85             CDC *pDC=GetDC();
 86             JHBHDib jdib;
 87             jdib.GetDib(&dib);
 88
 89             int newwidth,newheight,width,height;
 90             float xzoom,yzoom;//先暂且设为int
 91             FangDaTiShi p;
 92             p.DoModal();
 93             if(p.ifok==1)
 94             {
 95                 xzoom=p.Getx();
 96                 yzoom=p.Gety();
 97                 width=dib.GetWidth();
 98                 height=dib.GetHeight();
 99                 newwidth=(int)(width*xzoom+0.5);//四舍五入的时候是直接截取小数部分的
100                 newheight=(int)(height*yzoom+0.5);
101
102                 //图像的width并不一定是真正的,实际图像中是4字节对齐存储的
103                 int linebyte=((newwidth*8+31)/32)*4;
104                 LPBYTE temp;
105                 temp=new BYTE[linebyte*newheight];//这里其实平移那个函数已经有提醒了;这样写就是承认一个像素是8位,否认了单色图和真彩色
106                 memset(temp,(BYTE)0,linebyte*newheight);
107                 LPBYTE b;
108                 b=jdib.FangDa(temp,xzoom,yzoom,width,height,newwidth,newheight);
109                 BITMAPINFO* p=dib.GetInfo();
110                 p->bmiHeader.biWidth=newwidth;
111                 p->bmiHeader.biHeight=newheight;
112
113                 p->bmiHeader.biSizeImage=linebyte*height;
114                 CViewImage imageview;
115                 imageview.GetDib(&dib);
116                 imageview.OnDraw3(pDC,b,width+5,0);
117                 delete[]b;
118             }
119         }
120     }
121     else{
122         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
123     }
124 }
125
126
127
128
129
130 void CMfcPictureProcessingDlg::OnBnClickedButton1()//退出按钮
131 {
132     CDialogEx::OnOK();
133
134 }
135
136
137 void CMfcPictureProcessingDlg::On32794()//图像缩小
138 {
139     if(filePath.Compare(_T(""))!=0)
140     {
141         CDib dib;
142         dib.LoadFile(filePath);
143         if(dib.m_valid)
144         {
145             CDC *pDC=GetDC();
146             JHBHDib jdib;
147             jdib.GetDib(&dib);
148             FangDaTiShi p;
149             //p.SetDlgItemTextW(IDD_Big,_T("缩小"));//设置窗口的标题,不行,有中断
150             p.DoModal();
151             if(p.ifok==1)
152             {
153                 float xzoom=p.Getx();
154                 float yzoom=p.Gety();
155                 int width=dib.GetWidth();
156                 int height=dib.GetHeight();
157                 long newwidth=(long)(width*xzoom+0.5);
158                 long newheight=(long)(height*yzoom+0.5);
159                 jdib.SuoXiao(xzoom,yzoom);
160                 //这里按照书上的,给出了和放大不一样的解决方案,不用改info,直接在显示的时候将显示的大小划定为新大小,其他的废数据不用管
161                 //::StretchDIBits(pDC->GetSafeHdc(),width+5,0,newwidth,newheight,0,0,newwidth,newheight,dib.GetData(),dib.GetInfo(),DIB_RGB_COLORS,SRCCOPY);
162                 CViewImage imageview;
163                 imageview.GetDib(&dib);
164                 imageview.OnDraw4(pDC,width+5,0,newwidth,newheight);
165             }
166         }
167     }
168     else{
169         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
170     }
171 }
172
173
174 void CMfcPictureProcessingDlg::On32795()//图像转置
175 {
176     if(filePath.Compare(_T(""))!=0)
177     {
178         CDib dib;
179         dib.LoadFile(filePath);
180         if(dib.m_valid)
181         {
182             CDC *pDC=GetDC();
183             JHBHDib jdib;
184             jdib.GetDib(&dib);
185             int width=dib.GetWidth();
186             LPBYTE temp=jdib.ZhuanZhi();
187             CViewImage imageview;
188             imageview.GetDib(&dib);
189             imageview.OnDraw3(pDC,temp,width+5,0);
190             //::StretchDIBits(pDC->GetSafeHdc(),width+5,0,dib.GetWidth(),dib.GetHeight(),0,0,dib.GetWidth(),dib.GetHeight(),temp,dib.GetInfo(),DIB_RGB_COLORS,SRCCOPY);
191             delete[]temp;
192         }
193     }
194     else{
195         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
196     }
197
198 }
199
200
201 void CMfcPictureProcessingDlg::On32796()//旋转按钮
202 {
203     if(filePath.Compare(_T(""))!=0)
204     {
205         CDib dib;
206         dib.LoadFile(filePath);
207         if(dib.m_valid)
208         {
209             CDC *pDC=GetDC();
210             JHBHDib jdib;
211             int width=dib.GetWidth();
212             XuanZhuanDlg d;
213             d.DoModal();
214             if(d.ifok)
215             {
216                 jdib.GetDib(&dib);
217                 LPBYTE t=jdib.XuanZhuan(d.GetAngle());//旋转30度
218
219                 //发现一个问题,我这里没有实现调色板,也可以实现画图
220                 //::StretchDIBits(pDC->GetSafeHdc(),width+5,0,dib.GetWidth(),dib.GetHeight(),0,0,dib.GetWidth(),dib.GetHeight(),t,dib.GetInfo(),DIB_RGB_COLORS,SRCCOPY);
221                 CViewImage imageview;
222                 imageview.GetDib(&dib);
223                 imageview.OnDraw3(pDC,t,width+5,0);
224                 delete[]t;
225             }
226         }
227     }
228     else{
229         MessageBox(_T("请先选择文件!"),_T("提示"),MB_OK);
230     }
231 }

程序中我写了很多个用于输入参数的Dlg,代码这里没有填,有遇到的话请到本页一开始的GitHub中下载相应源码(? ω ?)。

五、运行代码看效果,我写的都是很简单的,没有什么健壮性:

打开过程跟之前的一样,详见:http://www.cnblogs.com/studylyn/p/7349819.html

比如说,这是垂直镜像的效果:

六、结束了(? ω ?),有问题欢迎留言讨论!

时间: 2024-10-07 03:36:17

第三章 图像的几何变换的相关文章

C#数字图像处理算法学习笔记(三)--图像几何变换

C#数字图像处理算法学习笔记(三)--图像几何变换 几何图像处理包括 图像的平移变换,镜像变换,旋转变换,伸缩变换,在这里仅以水平镜像为例,通过代码来理解其基本操作方式: 翻转前: 翻转后: //后台代码: public partial class Form1 : Form { private string _curFileName; private Bitmap _srcBitmap; private Bitmap _dstBitmap; public Form1() { Initialize

[看书][CSS精粹(第2版)]第三章 CSS和图像 & HTML网页布局

本章主要讲述作为背景图像方面的技巧. 1.边框(添加边框样式.去除边框): 2.为页面设置背景图像,位置设定,固定背景图像: 3.为任意元素设置背景图像: 4.文字放在图像的上面(作为背景图像): 5.为文档添加多个背景图像(本例利用html和body元素产生多重背景图像的效果): 6.在页面中使用透明效果(使用PNG格式图像). 利用网络搜索补充学习了padding的4个方向顺序(上右下左 顺时针),流式布局(看网上的解释结合书里的描述,大概是指页内布局元素采用百分数指定位置和大小). [个人

Python下opencv使用笔记(三)(图像的几何变换)

写在之前 二维与三维图像的几何变换在计算机图形学上有重要的应用,包括现在的许多图像界面的切换.二维与三维游戏画面控制等等都涉及到图像几何变换,就比如说在三维游戏中,控制角色三维移动的时候,画面是要跟着移动的,那么怎么移动,怎么让上一时刻的画面移动到这一时刻,这都是根据了你的移动量,然后找到三维坐标之间的对应关系,用这一时刻的坐标替换到上一时刻的坐标像素值实现图像的切换. 图像的几何变换主要包括:平移.扩大与缩小.旋转.仿射.透视等等.图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对

OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)

在OpenCV2:图像的几何变换,平移.镜像.缩放.旋转(1)主要介绍了图像变换中的向前映射.向后映射.处理变换过程中浮点坐标像素值的插值算法,并且基于OpenCV2实现了两个简单的几何变换:平移和镜像变换.本文主要稍微复杂点的两个几何变换:缩放和旋转. 1.图像缩放 图像的缩放主要用于改变图像的大小,缩放后图像的图像的宽度和高度会发生变化.水平缩放系数,控制图像宽度的缩放,其值为1,则图像的宽度不变:垂直缩放系数控制图像高度的缩放,其值为1,则图像的高度不变.如果水平缩放系数和垂直缩放系数不相

OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(1)

图像的几何变换是在不改变图像内容的前提下对图像像素的进行空间几何变换,主要包括了图像的平移变换.镜像变换.缩放和旋转等.本文首先介绍了图像几何变换的一些基本概念,然后再OpenCV2下实现了图像的平移变换.镜像变换.缩放以及旋转,最后介绍几何的组合变换(平移+缩放+旋转). 1.几何变换的基本概念 1.1 坐标映射关系 图像的几何变换改变了像素的空间位置,建立一种原图像像素与变换后图像像素之间的映射关系,通过这种映射关系能够实现下面两种计算: 原图像任意像素计算该像素在变换后图像的坐标位置 变换

【OPENGL】第三章 着色器基础(一)

在这一章,我们会学习什么是着色器(Shader),什么是着色器语言(OpenGL Shading Language-GLSL),以及着色器怎么和OpenGL程序交互. 首先我们先来看看什么叫着色器. Shader(着色器)是用来实现图像渲染的,用来替代固定渲染管线的可编程程序. 着色器替代了传统的固定渲染管线,可以实现3D图形学计算中的相关计算,由于其可编程性,可以实现各种各样的图像效果而不用受显卡的固定渲染管线限制.这极大的提高了图像的画质. 在上一篇文章( http://www.cnblog

Pro ASP.NET Core MVC 6th 第三章

第三章 MVC 模式,项目和约定 在深入了解ASP.NET Core MVC的细节之前,我想确保您熟悉MVC设计模式背后的思路以及将其转换为ASP.NET Core MVC项目的方式. 您可能已经了解本章中讨论的一些想法和约定,特别是如果您已经完成了高级ASP.NET或C#开发. 如果没有,我鼓励你仔细阅读 - 深入地理解隐藏在MVC背后的东西可以帮助你在通读本书时更好地与MVC框架的功能联系起来. MVC的历史 模型视图控制器模式起源于20世纪70年代后期,来自施乐PARC的Smalltalk

第三章 Matlab的选择结构

第三章 Matlab的选择结构 3.1 程序编写的一般步骤 3.2 关系运算符 1) 0表示假,非0表示真: 2) ~=:不等于: 3) sin(pi) ~= 0:为1,比较a.b两个数是否相等方法:abs(a - b)<1.0e-14 3.3 逻辑运算 1) 先与&后或| 3.4 逻辑函数与短路运算 1) 短路运算:&&.||:非短路运算:&.| 2) ischar(x).isempty(x).isinf(x).isnan(x):是否不是数.isnumeric(x)

Android 渗透测试学习手册 第三章 Android 应用的逆向和审计

第三章 Android 应用的逆向和审计 作者:Aditya Gupta 译者:飞龙 协议:CC BY-NC-SA 4.0 在本章中,我们将查看 Android 应用程序或.apk文件,并了解其不同的组件. 我们还将使用工具(如 Apktool,dex2jar 和 jd-gui)来逆向应用程序. 我们将进一步学习如何通过逆向和分析源代码来寻找 Android 应用程序中的各种漏洞. 我们还将使用一些静态分析工具和脚本来查找漏洞并利用它们. 3.1 Android 应用程序拆解 Android 应