• 第三章 图像的几何变换


    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 };
    View Code

    二、建立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 }
    View Code

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

    四、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 }
    View Code

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

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

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

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

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

  • 相关阅读:
    Easy UI form表单提交 IE浏览器不执行success ,以及 datagrid 展示过慢
    JS批量获取参数构建JSON参数对象
    Easy UI datebox控件无法正常赋值
    EasyUI控件combobox重复请求后台,dialog窗口数据异常
    后台Post/Get 请求接口 方式
    WebForm 页面ajax 请求后台页面 方法
    实现输入框小数多 自动进位展示,编辑时实际值不变
    页面获取Web控件ID不能正常获取,它惹得祸
    线性表的链式存储——单链表
    线性表
  • 原文地址:https://www.cnblogs.com/studylyn/p/7353902.html
Copyright © 2020-2023  润新知