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();

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

原文地址:https://www.cnblogs.com/fightfuture/p/4161443.html