• C#作业总结(2)


    先来说一下MiniPhoto部分。

    一。核心 滤镜算法(当然网上也有,我自己不过是修改其中的错误和优化)

    二。UI界面  这是仿写的,不过写的一般

    先给出程序的运行图片 

    开始一步步分析

    1.在C++里面图片的访问都是使用指针,C#里面也是可以用指针的,不过不建议使用,这里我也是上网补了一下C#里面图片的访问,代码如下

            private int width;            //图片的宽度
            private int height;
            private int step;             //步长
            private BitmapData srcBitData; //图像数据
            private BitmapData dstBitData;
            private Bitmap srcBit;       //具体的图片
            private Bitmap dstBit;
            private byte[] srcValues;    //C#里面就是将所有的图片数据放到数组里面然后访问
            private byte[] dstValues;
            private System.IntPtr srcPtr;  //指针
            private System.IntPtr dstPtr;
    
            public BasicFilter(Bitmap src)
            {
                srcBit = src;
                width = src.Width;
                height = src.Height;
                Init();
            }
            private void Init()
            {
                Rectangle rect = new Rectangle(0, 0, width, height);
                dstBit = new Bitmap(width, height);    //实例化
                srcBitData = srcBit.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);  //锁定内存  获取数据(c++里面会获得内存的头指针)
                step = srcBitData.Stride;
                srcValues = new byte[step * height];  //分配数组内存
                dstValues = new byte[step * height];
                srcBit.UnlockBits(srcBitData); //解锁 否则其他程序无法访问
            }
            private void InitFilter()
            {
                Rectangle rect = new Rectangle(0, 0, width, height);    
                srcBitData = srcBit.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                dstBitData = dstBit.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
                srcPtr = srcBitData.Scan0; //获取相关指针
                dstPtr = dstBitData.Scan0;
                System.Runtime.InteropServices.Marshal.Copy(srcPtr, srcValues, 0, srcValues.Length);  //内存的复制   将数据复制到数组里面 
                System.Runtime.InteropServices.Marshal.Copy(dstPtr, dstValues, 0, dstValues.Length);
            }

    然后所有的操作就如同操作数组一样,不过最后必须加上下面的代码

    System.Runtime.InteropServices.Marshal.Copy(dstValues, 0, dstPtr, dstValues.Length);  //数组复制到指针内存区
    srcBit.UnlockBits(srcBitData); //解锁
    dstBit.UnlockBits(dstBitData);

    2.好了,下面就是改代码,从C++到C#,这里我就不放代码了,直接给出下载的链接(C#版本的,当然C++我也有,需要的在下面留言)

    http://download.csdn.net/detail/zhoupeng39/8255507

    3.下面就是UI部分了

    刚开始做的时候遇到了一个很简单的问题,就是透明图片的问题,当时我以为需要自己写一个透明Panel,然后就是搜代码,改写,后来发现C#里面会自动对有透明通道的图片进行合成,这可比MFC方便多了,省去我自己重绘控件,其实透明的原理也相当简单,我就不说了。

    (1)选项卡的切换

    其实是不存在选项卡的,下面的选项都是Label控件,我增加了鼠标移入移出和点击的效果,然后对应显示图片,就OK了

    (2)图片的切换

    这里由于滤镜写的不多,没有用到滚动条,这块也就简单了,直接上十个PictureBox控件,对应的加载图片,切换的时候去掉不需要显示的控件就可以了

    (3)参数调节窗口

    本来这块是准备写在主界面上的,后来觉得里面的控件太丑,自己去重绘控件时间不够,于是加了额外的窗口,而且使用原始的控件。

    这里提一下子窗口和父窗口的交互问题,网上很多,我搜了一个比较简单的(MFC里面直接传递消息就OK了)

    父窗口

    ColorTone Base1 = new ColorTone(255, 0, 0, 20);
    Base1.ShowDialog(this);   //显示  制定当前窗口是父窗口
    
    //子窗口里面调用  
    public void ColorToneChange(byte r,byte g,byte b,int satu)
    {
         Bitmap dst = m_BaseFilter.ColorToneFilter(r, g, b, satu);
         picture_Photo.Image = dst;
    }

     子窗口

     m_mainForm = (Form1)this.Owner;   //获取父窗口
     m_mainForm.ColorToneChange(m_R, m_G, m_B, m_satu);  //交互

    可以看出是通过一个Public方法来交互的,是不是很简单,当然还有很多其他方法。

    (4)菜单部分

      菜单的移入和移出不是很难,几个定时器足以完成,这部分我在历史图片处犯了很多错误,就是撤销按钮和还原按钮

      给出示例代码

    private void InsertBitmap(Bitmap src)
     {
         if (m_CurrentIndex<10)
           {
               m_HistoryBitmap[m_CurrentIndex++] = src.Clone(new Rectangle(0, 0, src.Width, src.Height), src.PixelFormat);  //注意  直接 = 是引用操作  历史图片不会保存 必须使用复制的方法 
           }
          else
           {
                for (int i = 0; i < 9; i++)
                   m_HistoryBitmap[i] = m_HistoryBitmap[i + 1]; //引用操作
                m_HistoryBitmap[9] = src.Clone(new Rectangle(0, 0, src.Width, src.Height), src.PixelFormat); //复制
             }
     }

    给引用操作搞了很长时间,必须复制

    (5)图片的放大缩小

    为了保证滤镜的速度,我先是缩小图片,保存的时候再放大图片,使用GDI插值缩小放大

    代码如下

                Bitmap src = new Bitmap(path);
                m_SrcWidth = src.Width;
                m_SrcHeight = src.Height;        //记住原始的宽度高度
                double scale;
                int w, h;
                if (m_SrcWidth >= m_SrcHeight)
                {
                    scale = m_SrcHeight / (double)m_SrcWidth;        //记住缩放的比例
                    w = 300;
                    h = (int)(300 * scale);
                }
                else
                {
                    scale = m_SrcWidth / (double)m_SrcHeight;
                    w = (int)(300 * scale);
                    h = 300;
                }
                m_ProcessImage = new Bitmap(w, h);      
                Graphics g = Graphics.FromImage(m_ProcessImage);                        //使用GDI+ 绘制
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;  //高质量插值
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;  
                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                g.SmoothingMode |= System.Drawing.Drawing2D.SmoothingMode.AntiAlias;  //抗锯齿
                g.DrawImage(src, new Rectangle(0, 0, w, h), new Rectangle(0, 0, m_SrcWidth, m_SrcHeight), GraphicsUnit.Pixel);    //缩小
                picture_Photo.Size = new Size(w, h);  
                picture_Photo.Image = m_ProcessImage;
                g.Dispose(); //释放资源
                src.Dispose();

    好了基本的东西就这些,不是很多,毕竟花的时间很短,得去复习了,蛋疼的考试..

  • 相关阅读:
    oracle中rownum和rowid的区别和用法
    jsp中,对window对象的简单总结
    下拉列表框实现二级联动
    window.showModalDialog()的简单用法
    javascript中的正则表达式
    java实现树型结构样式
    几个数据库的驱动、连接
    Java桌面程序中设置一个软件的系统托盘
    【动态规划】求两字符串连续最大公共子串长度
    大整数相乘
  • 原文地址:https://www.cnblogs.com/fightfuture/p/4161443.html
Copyright © 2020-2023  润新知