首页 > 代码库 > C#作业总结(2)

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 = http://www.mamicode.com/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 = http://www.mamicode.com/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();

 

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

 

C#作业总结(2)