2015-02-04 16:25:24 Yokeqi 阅读数 4623
  • C#WinForm图表控件应用详解

    本课程详细介绍图表控件(Chart)在C#WinForm程序开发中的应用,包括图表的基本要素,基本图表的创建,图表的类型,核心内容是用图表展示数据库中的数据。

    2375 人正在学习 去看看 武占文

如游戏中,一张图片中包含了动画的所有帧。其实没必要做这么个控件,只需要将动画做成Gif,然后使用PictureBox加载这个Gif就可以了~囧。但是为了验证是否两者有区别,特意做了这个动画控件,直接丢弃了太可惜,记录一下吧~~以后需要可以直接用。

步骤:

1. 添加组件AnimationControl,添加一个Sytem.Windows.Timer作为帧管理器。

2. 注册Timer的Tick事件作为帧数刷新控件。

animationTimer.Tick += (sender, e) =>
{
    Invalidate();
};
3. 添加属性Interval、PictureSize分别制定刷新速率,动作图片大小。

4. 定义变量imageCount,ImageIndex分别获取图片中动作的总数、当前在第几个动作。

5. 定义变量rowCount,columnCount分别获取图片中行、列个数。

6. 重载OnPaint事件,画出当前帧动作。

protected override void OnPaint(PaintEventArgs pe)
{
    //base.OnPaint(pe);
    if (this.Image != null && rowCount > 0 && columnCount > 0)
    {
        Graphics g = pe.Graphics;
        g.Clear(this.BackColor);
        g.DrawImage(this.Image, 
            new Rectangle(0, 0, this.Width, this.Height),
            new Rectangle(
                (imageIndex % rowCount) * PictureSize.Width,
                (imageIndex / rowCount) * PictureSize.Height,
                PictureSize.Width,
                PictureSize.Height
                ), GraphicsUnit.Pixel);
        imageIndex = (imageIndex + 1) % imageCount;
    }
}
7.添加Start方法,初始化以上变量,并启动Timer开始动画显示。

8.定义Stop方法,停止Timer。

9.调用方法:设置好Interval与每个动作图片的大小,然后调用Start方法。


总代码:

public partial class AnimationControl : PictureBox
{
    private int imageCount = 0;
    private int imageIndex = 0;
    private int rowCount = 0, columnCount = 0;

    public AnimationControl()
        : this(null)
    {
    }

    public AnimationControl(IContainer container)
    {
        if (container != null)
        {
            container.Add(this);
        }

        InitializeComponent();
        animationTimer.Tick += (sender, e) =>
        {
            Invalidate();
        };
    }

    public int Interval
    {
        get
        {
            return animationTimer.Interval;
        }

        set
        {
            if (value != animationTimer.Interval)
            {
                animationTimer.Interval = value;
            }
        }
    }

    public Size PictureSize
    {
        get;
        set;
    }

    public void Start()
    {
        imageIndex = 0;
        rowCount = 0;
        columnCount = 0;
        if (this.Image != null && PictureSize.Width > 0 && PictureSize.Height > 0)
        {
            rowCount = this.Image.Width / PictureSize.Width;
            columnCount = this.Image.Height / PictureSize.Height;
            imageCount = rowCount * columnCount;
        }
        animationTimer.Start();
    }

    public void Stop()
    {
        animationTimer.Stop();
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        //base.OnPaint(pe);
        if (this.Image != null && rowCount > 0 && columnCount > 0)
        {
            Graphics g = pe.Graphics;
            g.Clear(this.BackColor);
            g.DrawImage(this.Image, 
                new Rectangle(0, 0, this.Width, this.Height),
                new Rectangle(
                    (imageIndex % rowCount) * PictureSize.Width,
                    (imageIndex / rowCount) * PictureSize.Height,
                    PictureSize.Width,
                    PictureSize.Height
                    ), GraphicsUnit.Pixel);
            imageIndex = (imageIndex + 1) % imageCount;
        }
    }
}



2013-02-26 12:33:58 leehong2005 阅读数 16956
  • C#WinForm图表控件应用详解

    本课程详细介绍图表控件(Chart)在C#WinForm程序开发中的应用,包括图表的基本要素,基本图表的创建,图表的类型,核心内容是用图表展示数据库中的数据。

    2375 人正在学习 去看看 武占文

最近没事,有网上看到一篇关于图像处理的文章,觉得很好,结合它上面的原理,自己写了一个C#图像处理的例子。这个DEMO的界面的有两个PictrueBox控件,用来显示图片,一个是源图片,一个是经过转换的目标图片,UI下面部分有一些按钮,每个按钮实现一个转换功能。这个DEMO允许用户拖一张图片到源PictureBox中,然后通过这些功能按钮实现图片的效果转换。这些功能有把图片变成黑白、底片、浮雕、锐化、柔化等效果。首先来一张运行效果图:


这个DEMO主要有以下几个机能点:
 图像处理
 PictureBox的拖拽。
 计算处理时间
 对图像进行缩放处理


1.图像处理

    首先说明一点,图像处理的算法不是我自己的想出来的,也没有必要去想,网上调查一下,很多的。所以算法是网是找的。在些声明一下。

  1.1 黑白效果

原理: 彩色图像处理成黑白效果通常有3种算法:
(1).最大值法: 使每个像素点的 R, G, B 值等于原像素点的 RGB (颜色值) 中最大的一个;
(2).平均值法: 使用每个像素点的 R,G,B值等于原像素点的RGB值的平均值;
(3).加权平均值法: 对每个像素点的 R, G, B值进行加权,R,G,B的系数分别是0.7,0.2,0.1。
    自认为第三种的效果是最好的。

  1.2 底片效果

    原理: GetPixel方法获得每一点像素的值, 然后再使用SetPixel方法将取反后的颜色值设置到对应的点。

  1.3 锐化效果

    原理:突出显示颜色值大(即形成形体边缘)的像素点。

  1.4 浮雕效果

    原理: 对图像像素点的像素值分别与相邻像素点的像素值相减后加上128, 然后将其作为新的像素点的值。

  1.5 柔化效果

    原理: 当前像素点与周围像素点的颜色差距较大时取其平均值。

 

2.PictureBox的拖拽

拖拽是写在UserControlPictureBox类中,该类继承于UserControl,里面有一个PictrueBox,相当于把图片显示,缩放,拖拽封装了。
C#的拖拽还是很简单的。主要用到DragEnter和DragDrop事件和DoDragDrop方法。
 DragEnter
在拖拽源被拖入到拖拽目标时触发,在这个事件处理函数中,要做的事情就是设置DragEventArgs 对象的Effect,这是一个DragDropEffects枚举值。具体请参见MSDN。
 DragDrop
在释放鼠标并且鼠标拖拽目标之内在时发生。这里面可以接受拖拽的数据。
 DoDragDrop
这个函数表示开始一个拖拽事件,一般是在MouseDown或者MouseMove中调用这个函数,这个函数会阻塞线程。


3.计算处理时间

这部分主要用到了QueryPerformanceCounter 和 QueryPerformanceFrequency API。这里会涉及到API与C#交互的问题。代码如下:
[DllImport("kernel32.dll")]
private static extern bool QueryPerformanceCounter(ref long lpPerformanceCount);
[DllImport("kernel32.dll")]
private static extern bool QueryPerformanceFrequency(ref long lpFrequency);


4.对图像进行缩放处理

这部分是也是写在UserControlPictureBox类中。由于用户拖入的图片尺寸可能很大,显示在PictrueBox中虽说可以进行缩放显示,但得到的Image对象还是原来图片你的尺寸,所以为了提高转换效率,就要对图片进行等比例缩放。核心代码如下:
Bitmap bitmap = new Bitmap(newWidth, newHeight, oldImage.PixelFormat);
    Graphics g = Graphics.FromImage(bitmap);
    g.Clear(Color.Transparent);
    g.DrawImage(oldImage, new RectangleF(0, 0, newWidth, newHeight));
return Image.FromHbitmap(bitmap.GetHbitmap());

其中newWidth, newHeight是新的图片的尺寸,这两个值的得到很简单。

 

5.总体说明

界面上有很多按钮,其实每个按钮的事件处理程序都是一个,我在程序中定义了一个枚举:
public enum ImageEffect
{
    GrayScale   = 0,      // 黑白
    Film        = 1,      // 底片
    Relief      = 2,      // 浮雕
    Soften      = 3,      // 柔化
    Sharpen     = 4,      // 锐化
    Canvas      = 5,      // 油画
}

在按钮处理程序中根据不同的按钮ID,给ImageEffectManager类的ChangeEffect方法传递不同的参数。ChangeEffect方法的定义如下:

public void ChangeEffect(ImageEffect effect)
{
    switch(effect)
    {
    case  ImageEffect .GrayScale :
         break;
    }
}

6. 代码

ImageEffectManager.cs类 图像效果管理

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
namespace ImageEffectSample.Classes
{
    public enum ImageEffect
    {
        GrayScale = 0,      // 黑白
        Film      = 1,      // 底片
        Relief    = 2,      // 浮雕
        Soften    = 3,      // 柔化
        Sharpen   = 4,      // 锐化
        Canvas    = 5,      // 油画
    }
    public class ImageEffectManager
    {
        private Bitmap newBitmap = null;
        private Bitmap oldBitmap = null;
        #region Properties
       
        public Bitmap ConvertedBitmap
        {
            get { return this.newBitmap; }
        }
        public Bitmap OriginalBitmap
        {
            set
            {
                DisposeBitmap();
                this.oldBitmap = value;
            }
        }
        public Size PixelSize
        {
            get
            {
                if (this.oldBitmap != null)
                {
                    GraphicsUnit unit = GraphicsUnit.Pixel;
                    RectangleF bounds = this.oldBitmap.GetBounds(ref unit);
                    return new Size(
                        (int)bounds.Width, (int)bounds.Height);
                }
                return new Size(0, 0);
            }
        }
        #endregion
        #region Methods
       
        public ImageEffectManager()
        {
        }
        public void DisposeBitmap()
        {
            if (this.newBitmap != null)
            {
                this.newBitmap.Dispose();
                this.newBitmap = null;
            }
        }
        public void ChangeEffect(ImageEffect effect)
        {
            if (null == this.oldBitmap)
            {
                return;
            }
            Size size = PixelSize;
            int width = size.Width;
            int height = size.Height;
            this.DisposeBitmap();
            this.newBitmap = new Bitmap(width, height);
            switch (effect)
            {
                case ImageEffect.GrayScale:
                    MakeGrayScale(width, height);
                    break;
                case ImageEffect.Film:
                    MakeFilmEffect(width, height);
                    break;
                case ImageEffect.Relief:
                    MakeReliefEffect(width, height);
                    break;
                case ImageEffect.Soften:
                    MakeSoftenEffect(width, height);
                    break;
                case ImageEffect.Sharpen:
                    MakeSharpenEffect(width, height);
                    break;
            }
        }
        private void MakeGrayScale(int width, int height)
        {
            Color c;
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    c = this.oldBitmap.GetPixel(x, y);
                    ///////////////////////////////////////////////////////
                    //
                    // Average
                    // int value = (c.R + c.G + c.B) / 3;
                    //
                    ///////////////////////////////////////////////////////
                    // Weighted average
                    int value = (int)(0.7 * c.R) + 
                        (int)(0.2 * c.G) + (int)(0.1 * c.B);
                    this.newBitmap.SetPixel(x, y,
                        Color.FromArgb(c.A, value, value, value));
                }
            }
        }
        private void MakeFilmEffect(int width, int height)
        {
            Color c;
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    c = this.oldBitmap.GetPixel(x, y);
                    this.newBitmap.SetPixel(x, y, 
                        Color.FromArgb(c.A, 255 - c.R, 
                            255 - c.G, 255 - c.B));
                }
            }
        }
        private void MakeReliefEffect(int width, int height)
        {
            Color c1;
            Color c2;
            int r, g, b = 0;
            for (int x = 0; x < width - 1; x++)
            {
                for (int y = 0; y < height - 1; y++)
                {
                    c1 = this.oldBitmap.GetPixel(x, y);
                    c2 = this.oldBitmap.GetPixel(x + 1, y + 1);
                    r = Math.Abs(c1.R - c2.R + 128);
                    g = Math.Abs(c1.G - c2.G + 128);
                    b = Math.Abs(c1.B - c2.B + 128);
                    r = (r > 255) ? 255 : ((r < 0) ? 0 : r);
                    g = (g > 255) ? 255 : ((g < 0) ? 0 : g);
                    b = (b > 255) ? 255 : ((b < 0) ? 0 : b);
                    this.newBitmap.SetPixel(x, y, 
                        Color.FromArgb(c1.A, r, g, b));
                }
            }
        }
        private void MakeSoftenEffect(int width, int height)
        {
            // The template of Gauss
            int[] Gauss = { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
            Color pixel;
            for (int x = 1; x < width - 1; x++)
            {
                for (int y = 1; y < height - 1; y++)
                {
                    int r = 0, g = 0, b = 0;
                    int Index = 0;
                    for (int col = -1; col <= 1; col++)
                    {
                        for (int row = -1; row <= 1; row++)
                        {
                            pixel = 
                                this.oldBitmap.GetPixel(x + row, y + col);
                            r += pixel.R * Gauss[Index];
                            g += pixel.G * Gauss[Index];
                            b += pixel.B * Gauss[Index];
                            Index++;
                        }
                    }
                    r /= 16;
                    g /= 16;
                    b /= 16;
                    //处理颜色值溢出
                    r = r > 255 ? 255 : r;
                    r = r < 0 ? 0 : r;
                    g = g > 255 ? 255 : g;
                    g = g < 0 ? 0 : g;
                    b = b > 255 ? 255 : b;
                    b = b < 0 ? 0 : b;
                    this.newBitmap.SetPixel(x - 1, y - 1, 
                        Color.FromArgb(r, g, b));
                }
            }
        }
        private void MakeSharpenEffect(int width, int height)
        {
            Color pixel;
            //拉普拉斯模板
            int[] Laplacian ={ -1, -1, -1, -1, 9, -1, -1, -1, -1 };
            for (int x = 1; x < width - 1; x++)
            {
                for (int y = 1; y < height - 1; y++)
                {
                    int r = 0, g = 0, b = 0;
                    int Index = 0;
                    for (int col = -1; col <= 1; col++)
                    {
                        for (int row = -1; row <= 1; row++)
                        {
                            pixel = this.oldBitmap.GetPixel(x + row, y + col);
                            r += pixel.R * Laplacian[Index];
                            g += pixel.G * Laplacian[Index];
                            b += pixel.B * Laplacian[Index];
                            Index++;
                        }
                    }
                    //处理颜色值溢出
                    r = r > 255 ? 255 : r;
                    r = r < 0 ? 0 : r;
                    g = g > 255 ? 255 : g;
                    g = g < 0 ? 0 : g;
                    b = b > 255 ? 255 : b;
                    b = b < 0 ? 0 : b;
                    this.newBitmap.SetPixel(x - 1, y - 1, 
                        Color.FromArgb(r, g, b));
                }
            }
        }
        private void MakeCanvasEffect(int width, int height)
        {
        }
        #endregion
    }
}

TimeCounter.cs类,用于计算处理时间

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ImageEffectSample.Classes
{
    public class TimeCounter
    {
        private static long startCount = 0;
        private static long elapsedCount = 0;
        #region Properties
        public static float Seconds
        {
            get
            {
                long freq = 0;
                float retValue = 0.0f;
                QueryPerformanceFrequency(ref freq);
                if (freq != 0)
                {
                    retValue = (float)elapsedCount / (float)freq;
                }
                return retValue;
            }
        }
        #endregion
        #region Methods
        public static void Start()
        {
            startCount = 0;
            QueryPerformanceCounter(ref startCount);
        }
        public static void Stop()
        {
            long stopCount = 0;
            QueryPerformanceCounter(ref stopCount);
            elapsedCount = (stopCount - startCount);
        }
        #endregion
        #region Import API
        [DllImport("kernel32.dll")]
        private static extern bool QueryPerformanceCounter(
            ref long lpPerformanceCount);
        [DllImport("kernel32.dll")]
        private static extern bool QueryPerformanceFrequency(
            ref long lpFrequency);
       
        #endregion
    }
}


UserControlPictureBox.cs类  封装了图像缩放,拖拽,显示等功能

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace ImageEffectSample.UserControls
{
    public partial class UserControlPictureBox : UserControl
    {
        private bool m_dragDropEnable = true;
        private bool m_isOriginalSize = false;
        #region Properties
        public PictureBox PictrueBoxObject
        {
            get { return this.pictureBox; }
        }
        public bool DragDropEnable
        {
            get { return this.m_dragDropEnable; }
            set { m_dragDropEnable = value; }
        }
        public bool IsOriginalSize
        {
            get { return this.m_isOriginalSize; }
            set { m_isOriginalSize = value; }
        }
        #endregion
        #region Methods
       
        public UserControlPictureBox()
        {
            InitializeComponent();
            this.pictureBox.AllowDrop = true;
            this.pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
            this.pictureBox.DragDrop += 
                new DragEventHandler(PictureBox_DragDrop);
            this.pictureBox.DragEnter +=
                 new DragEventHandler(PictureBox_DragEnter);
        }
        public void DisposeImage()
        {
            if (this.pictureBox.Image != null)
            {
                this.pictureBox.Image.Dispose();
                this.pictureBox.Image = null;
            }
        }
        private Image ZoomImage(Image oldImage)
        {
            if (null == oldImage)
            {
                return null;
            }
            int width = oldImage.Width;
            int height = oldImage.Height;
            int newWidth = 0;
            int newHeight = 0;
            float ratioXY = (float)width / (float)height;
            if ((width > this.pictureBox.Width) || 
                 (height > this.pictureBox.Height))
            {
                if (ratioXY >= 1.0)
                {
                    newWidth = this.pictureBox.Width;
                    newHeight = (int)((float)newWidth / ratioXY) + 1;
                }
                else
                {
                    newHeight = this.pictureBox.Height;
                    newWidth = (int)(newHeight * ratioXY);
                }
                Bitmap bitmap = new Bitmap(newWidth,
                     newHeight, oldImage.PixelFormat);
                Graphics g = Graphics.FromImage(bitmap);
                g.Clear(Color.Transparent);
                g.DrawImage(oldImage, 
                    new RectangleF(0, 0, newWidth, newHeight));
                return Image.FromHbitmap(bitmap.GetHbitmap());
            }
            return oldImage;
        }
        #endregion
        #region PictureBox drag and drop events
        private void PictureBox_DragEnter(object sender, DragEventArgs e)
        {
            bool bflag = e.Data.GetDataPresent(DataFormats.FileDrop);
            e.Effect = bflag && this.m_dragDropEnable ? e.Effect =
                DragDropEffects.Copy : DragDropEffects.None;
        }
        private void PictureBox_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                String[] strfileNames =
                    (String[])e.Data.GetData(DataFormats.FileDrop);
                Image dragImage = Image.FromFile(strfileNames[0]);
                if (dragImage != null)
                {
                    this.DisposeImage();
                    this.pictureBox.Image = 
                        m_isOriginalSize ? dragImage : ZoomImage(dragImage);
                }
            }
        }
        #endregion
    }
}
 

ImageEffectMainWindow.cs类,主窗体

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ImageEffectSample.Classes;
namespace ImageEffectSample.Windows
{
    public partial class ImageEffectMainWindow : Form
    {
        ImageEffectManager effectManager = null;
        public ImageEffectMainWindow()
        {
            InitializeComponent();
            this.effectManager = new ImageEffectManager();
            this.convertedPictureBox.DragDropEnable = false;
        }
        private void CheckBoxOriginalSize_CheckedChanged(object sender, EventArgs e)
        {
            this.originalPictureBox.IsOriginalSize = 
                this.checkBoxOriginalSize.Checked;
        }
        private void Button_Click(object sender, EventArgs e)
        {
            this.txtBoxTime.Text = "";
            Button button = sender as Button;
            if (button != null)
            {
                TimeCounter.Start();
                Image img = this.originalPictureBox.PictrueBoxObject.Image;
                if (img != null)
                {
                    effectManager.OriginalBitmap = new Bitmap(img);
                    switch (button.Name)
                    {
                        case "btnGrayScaleEffect":
                            effectManager.ChangeEffect(ImageEffect.GrayScale);
                            break;
                        case "btnFileEffect":
                            effectManager.ChangeEffect(ImageEffect.Film);
                            break;
                        case "btnReliefEffect":
                            effectManager.ChangeEffect(ImageEffect.Relief);
                            break;
                        case "btnSoftenEffect":
                            effectManager.ChangeEffect(ImageEffect.Soften);
                            break;
                        case "btnSharpenEffect":
                            effectManager.ChangeEffect(ImageEffect.Sharpen);
                            break;
                    }
                    this.convertedPictureBox.DisposeImage();
                    this.convertedPictureBox.PictrueBoxObject.Image = 
                        effectManager.ConvertedBitmap;
                    TimeCounter.Stop();
                    this.txtBoxTime.Text = 
                        String.Format("Elapsed time:  {0}  s",
                            TimeCounter.Seconds.ToString());
                }
            }
        }
        
        private void ClearImagesButton_Click(object sender, EventArgs e)
        {
            this.convertedPictureBox.DisposeImage();
            this.originalPictureBox.DisposeImage();
            this.txtBoxTime.Text = "";
        }
    }
}




2014-03-01 14:04:44 good_jobs 阅读数 866
  • C#WinForm图表控件应用详解

    本课程详细介绍图表控件(Chart)在C#WinForm程序开发中的应用,包括图表的基本要素,基本图表的创建,图表的类型,核心内容是用图表展示数据库中的数据。

    2375 人正在学习 去看看 武占文

C#开发DIY照片书软件(C#图形图像开发)


涉及的技术是C#图形图像开发、图形学算法(包括图形的缩放、旋转、移动、裁减等等)、自定义控件开发、GDI+图形渲染等等。


软件应用场景: 

DIY相册、台历、挂历、海报、贺卡、照片冲印、影楼、帆布画、手提袋等等DIY领域。应用场景非常广阔,几乎所有印刷行业、照片处理、影楼、DIY设计等等。


功能描述: 

 

1、 配套软件有3个:模版制作软件;照片处理软件;作品解密软件。 

2、 模版制作软件,可以轻松制作模版。 

3、 照片处理软件功能包括: 

【1】      打开模版或作品

【2】      导入照片库

【3】      随意拖动照片放进模版里

【4】      调整照片显示范围

【5】      添加文字,设置文字样式、字体、颜色等等

【6】      添加贴图饰物,设置贴图大小

【7】      随意拖动文字、贴图位置

【8】      可随意旋转文字、贴图

【9】      文字和贴图支持无限制复制,支持复制到其他模版,方便快捷

【10】   丰富的快捷方式支持,包括打开、保存、文字和贴图的复制、剪粘贴、删除等

【11】   导出作品 

4、作品解密软件把作品解密出高质量JPG图片。


软件截图:







2014-08-12 17:38:25 u014542704 阅读数 6943
  • C#WinForm图表控件应用详解

    本课程详细介绍图表控件(Chart)在C#WinForm程序开发中的应用,包括图表的基本要素,基本图表的创建,图表的类型,核心内容是用图表展示数据库中的数据。

    2375 人正在学习 去看看 武占文
用c#做图形图像处理的时候需要用到System.Drawing.Bitmap。在WPF中显示图像的Image控件接受的数据源是ImageSource,因此使用System.Drawing.Bitmap进行图像处理之后要把System.Drawing.Bitmap转换成ImageSource,转换方法如下:
System.Drawing.Bitmap m_Bitmap = new System.Drawing.Bitmap("c:\temp\test.jpg", false);
IntPtr ip = m_Bitmap.GetHbitmap();
BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ip, IntPtr.Zero, Int32Rect.Empty, 
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ip);
imageLarge.Source = bitmapSource;
其中DeleteObject的声明如下:
[DllImport("gdi32")]
static extern int DeleteObject(IntPtr o);
使用过System.Drawing.Bitmap后一定要用DeleteObject释放掉对象,不然内存不释放,很快系统内存就消耗光了。
2016-12-05 09:50:49 ryb666666 阅读数 1351
  • C#WinForm图表控件应用详解

    本课程详细介绍图表控件(Chart)在C#WinForm程序开发中的应用,包括图表的基本要素,基本图表的创建,图表的类型,核心内容是用图表展示数据库中的数据。

    2375 人正在学习 去看看 武占文

作者:彭军 http://pengjun.org.cn

这里之所以说“浅谈”是因为我这里只是简单的介绍如何使用Visual C#进行图像的读入、保存以及对像素的访问。而不涉及太多的算法。

一、读入图像

在Visual C#中我们可以使用一个Picture Box控件来显示图片,如下:
        private void btnOpenImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*";
            ofd.CheckFileExists = true;
            ofd.CheckPathExists = true;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                //pbxShowImage.ImageLocation = ofd.FileName;
                bmp = new Bitmap(ofd.FileName);
                if (bmp==null)
                {
                    MessageBox.Show("加载图片失败!", "错误");
                    return;
                }
                pbxShowImage.Image = bmp;
                ofd.Dispose();
            }
        }
其中bmp为类的一个对象:private Bitmap bmp=null;
在使用Bitmap类和BitmapData类之前,需要使用using System.Drawing.Imaging;
二、保存图像
        private void btnSaveImage_Click(object sender, EventArgs e)
        {
            if (bmp == null) return;

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "BMP Files(*.bmp)|*.bmp|JPG Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All Files(*.*)|*.*";
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                pbxShowImage.Image.Save(sfd.FileName);
                MessageBox.Show("保存成功!","提示");
                sfd.Dispose();
            }
        }
三、对像素的访问
我们可以来建立一个GrayBitmapData类来做相关的处理。整个类的程序如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace ImageElf
{
    class GrayBitmapData
    {
        public byte[,] Data;//保存像素矩阵
        public int Width;//图像的宽度
        public int Height;//图像的高度

        public GrayBitmapData()
        {
            this.Width = 0;
            this.Height = 0;
            this.Data = null;
        }

        public GrayBitmapData(Bitmap bmp)
        {
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            this.Width = bmpData.Width;
            this.Height = bmpData.Height;
            Data = new byte[Height, Width];
            unsafe
            {
                byte* ptr = (byte*)bmpData.Scan0.ToPointer();
                for (int i = 0; i < Height; i++)
                {
                    for (int j = 0; j < Width; j++)
                    {
    //将24位的RGB彩色图转换为灰度图
                        int temp = (int)(0.114 * (*ptr++)) + (int)(0.587 * (*ptr++))+(int)(0.299 * (*ptr++));
                        Data[i, j] = (byte)temp;
                    }
                    ptr += bmpData.Stride - Width * 3;//指针加上填充的空白空间
                }
            }
            bmp.UnlockBits(bmpData);
        }

        public GrayBitmapData(string path)
            : this(new Bitmap(path))
        {
        }

        public Bitmap ToBitmap()
        {
            Bitmap bmp=new Bitmap(Width,Height,PixelFormat.Format24bppRgb);
            BitmapData bmpData=bmp.LockBits(new Rectangle(0,0,Width,Height),ImageLockMode.WriteOnly,PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* ptr=(byte*)bmpData.Scan0.ToPointer();
                for(int i=0;i<Height;i++)
                {
                    for(int j=0;j<Width;j++)
                    {
                        *(ptr++)=Data[i,j];
                        *(ptr++)=Data[i,j];
                        *(ptr++)=Data[i,j];
                    }
                    ptr+=bmpData.Stride-Width*3;
                }
            }
            bmp.UnlockBits(bmpData);
            return bmp;
        }

        public void ShowImage(PictureBox pbx)
        {
            Bitmap b = this.ToBitmap();
            pbx.Image = b;
            //b.Dispose();
        }

        public void SaveImage(string path)
        {
            Bitmap b=ToBitmap();
            b.Save(path);
            //b.Dispose();
        }
//均值滤波
        public void AverageFilter(int windowSize)
        {
            if (windowSize % 2 == 0)
            {
                return;
            }

            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    int sum = 0;
                    for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++)
                    {
                        for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++)
                        {
                            int a = i + g, b = j + k;
                            if (a < 0) a = 0;
                            if (a > Height - 1) a = Height - 1;
                            if (b < 0) b = 0;
                            if (b > Width - 1) b = Width - 1;
                            sum += Data[a, b];
                        }
                    }
                    Data[i,j]=(byte)(sum/(windowSize*windowSize));
                }
            }
        }
//中值滤波
        public void MidFilter(int windowSize)
        {
            if (windowSize % 2 == 0)
            {
                return;
            }

            int[] temp = new int[windowSize * windowSize];
            byte[,] newdata = new byte[Height, Width];
            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    int n = 0;
                    for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++)
                    {
                        for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++)
                        {
                            int a = i + g, b = j + k;
                            if (a < 0) a = 0;
                            if (a > Height - 1) a = Height - 1;
                            if (b < 0) b = 0;
                            if (b > Width - 1) b = Width - 1;
                            temp[n++]= Data[a, b];
                        }
                    }
                    newdata[i, j] = GetMidValue(temp,windowSize*windowSize);
                }
            }

            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    Data[i, j] = newdata[i, j];
                }
            }
        }
//获得一个向量的中值
        private byte GetMidValue(int[] t, int length)
        {
            int temp = 0;
            for (int i = 0; i < length - 2; i++)
            {
                for (int j = i + 1; j < length - 1; j++)
                {
                    if (t[i] > t[j])
                    {
                        temp = t[i];
                        t[i] = t[j];
                        t[j] = temp;
                    }
                }
            }

            return (byte)t[(length - 1) / 2];
        }
//一种新的滤波方法,是亮的更亮、暗的更暗
        public void NewFilter(int windowSize)
        {
            if (windowSize % 2 == 0)
            {
                return;
            }

            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    int sum = 0;
                    for (int g = -(windowSize - 1) / 2; g <= (windowSize - 1) / 2; g++)
                    {
                        for (int k = -(windowSize - 1) / 2; k <= (windowSize - 1) / 2; k++)
                        {
                            int a = i + g, b = j + k;
                            if (a < 0) a = 0;
                            if (a > Height - 1) a = Height - 1;
                            if (b < 0) b = 0;
                            if (b > Width - 1) b = Width - 1;
                            sum += Data[a, b];
                        }
                    }
                    double avg = (sum+0.0) / (windowSize * windowSize);
                    if (avg / 255 < 0.5)
                    {
                        Data[i, j] = (byte)(2 * avg / 255 * Data[i, j]);
                    }
                    else
                    {
                        Data[i,j]=(byte)((1-2*(1-avg/255.0)*(1-Data[i,j]/255.0))*255);
                    }
                }
            }
        }
//直方图均衡
        public void HistEqual()
        {
            double[] num = new double[256] ;
            for(int i=0;i<256;i++) num[i]=0;

            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    num[Data[i, j]]++;
                }
            }

            double[] newGray = new double[256];
            double n = 0;
            for (int i = 0; i < 256; i++)
            {
                n += num[i];
                newGray[i] = n * 255 / (Height * Width);
            }

            for (int i = 0; i < Height; i++)
            {
                for (int j = 0; j < Width; j++)
                {
                    Data[i,j]=(byte)newGray[Data[i,j]];
                }
            }
        }

}
}
在GrayBitmapData类中,只要我们对一个二维数组Data进行一系列的操作就是对图片的操作处理。在窗口上,我们可以使用
一个按钮来做各种调用:
//均值滤波
        private void btnAvgFilter_Click(object sender, EventArgs e)
        {
            if (bmp == null) return;
            GrayBitmapData gbmp = new GrayBitmapData(bmp);
            gbmp.AverageFilter(3);
            gbmp.ShowImage(pbxShowImage);
        }
//转换为灰度图
        private void btnToGray_Click(object sender, EventArgs e)
        {
            if (bmp == null) return;
            GrayBitmapData gbmp = new GrayBitmapData(bmp);
            gbmp.ShowImage(pbxShowImage);
        }

 

四、总结

在Visual c#中对图像进行处理或访问,需要先建立一个Bitmap对象,然后通过其LockBits方法来获得一个BitmapData类的对象,然后通过获得其像素数据的首地址来对Bitmap对象的像素数据进行操作。当然,一种简单但是速度慢的方法是用Bitmap类的GetPixel和SetPixel方法。其中BitmapData类的Stride属性为每行像素所占的字节。

 

 

 

 

 

 

 

 

 

 

 

C# colorMatrix 对图片的处理 : 亮度调整 抓屏 翻转 随鼠标画矩形

 

1.图片亮度处理

 

        private void btn_Grap_Click(object senderEventArgs e)

        {

            //亮度百分比

            int percent = 50;

            Single v = 0.006F * percent;    

            Single[][] matrix = {         

                new Single[] { 1, 0, 0, 0, 0 },         

                new Single[] { 0, 1, 0, 0, 0 },          

                new Single[] { 0, 0, 1, 0, 0 },         

                new Single[] { 0, 0, 0, 1, 0 },         

                new Single[] { vvv, 0, 1 }     

            };    

            System.Drawing.Imaging.ColorMatrix cm = new System.Drawing.Imaging.ColorMatrix(matrix);

            System.Drawing.Imaging.ImageAttributes attr = newSystem.Drawing.Imaging.ImageAttributes();    

            attr.SetColorMatrix(cm);    

            //Image tmp 

            Image tmp = Image.FromFile("1.png");

 

            this.pictureBox_Src.Image = Image.FromFile("1.png");

 

            Graphics g = Graphics.FromImage(tmp);  

            try  

            {

                Rectangle destRect = new Rectangle(0, 0, tmp.Widthtmp.Height);        

                g.DrawImage(tmpdestRect, 0, 0, tmp.Widthtmp.HeightGraphicsUnit.Pixelattr);    

            }    

            finally    

            {        

                g.Dispose();    

            }

 

            this.pictureBox_Dest.Image = (Image)tmp.Clone();

        }

 

 

2.抓屏将生成的图片显示在pictureBox

 

        private void btn_Screen_Click(object senderEventArgs e)

        {

            Image myImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width,Screen.PrimaryScreen.Bounds.Height);

            Graphics g = Graphics.FromImage(myImage);

            g.CopyFromScreen(new Point(0, 0), new Point(0, 0), newSize(Screen.PrimaryScreen.Bounds.WidthScreen.PrimaryScreen.Bounds.Height));

            //IntPtr dc1 = g.GetHdc();      //此处这两句多余,具体看最后GetHdc()定义

            //g.ReleaseHdc(dc1);           

            g.Dispose();

            this.pictureBox_Src.SizeMode = PictureBoxSizeMode.StretchImage;

            this.pictureBox_Src.Image = myImage;

            myImage.Save("Screen"ImageFormat.Png);

     }

 

3.翻转

 

        private void btn_RotateFlip_Click(object senderEventArgs e)

        {

            this.pictureBox_Src.Image = Image.FromFile("1.png");

 

            Image tmp = Image.FromFile("1.png");

 

            tmp.RotateFlip(RotateFlipType.Rotate90FlipNone);

            this.pictureBox_Dest.Image = tmp;

        }

4.跟随鼠标在 pictureBox的图片上画矩形

        private int intStartX = 0;

        private int intStartY = 0;

        private bool isMouseDraw = false;

 

        private void pictureBox_Src_MouseDown(object senderMouseEventArgs e)

        {

            isMouseDraw = true;

 

            intStartX = e.X;

            intStartY = e.Y;

        }

 

        private void pictureBox_Src_MouseMove(object senderMouseEventArgs e)

        {

            if (isMouseDraw)

            {

                try

                {

                    //Image tmp = Image.FromFile("1.png");

                    Graphics g = this.pictureBox_Src.CreateGraphics();

                    //清空上次画下的痕迹

                    g.Clear(this.pictureBox_Src.BackColor);

                    Brush brush = new SolidBrush(Color.Red);

                    Pen pen = new Pen(brush, 1);

                    pen.DashStyle = DashStyle.Solid;

                    g.DrawRectangle(pennew Rectangle(intStartX > e.X ? e.X : intStartXintStartY > e.Ye.Y : intStartYMath.Abs(e.X - intStartX), Math.Abs(e.Y - intStartY)));

                    g.Dispose();

                    //this.pictureBox_Src.Image = tmp;

                }

                catch (Exception ex)

                {

                    ex.ToString();

                }

            }

        }

 

        private void pictureBox_Src_MouseUp(object senderMouseEventArgs e)

        {

            isMouseDraw = false;

 

            intStartX = 0;

            intStartY = 0;

        }

5.取灰度

 

        private void btn_GetGray_Click(object senderEventArgs e)

        {

            this.pictureBox_Src.Image = Image.FromFile("1.png");

            Bitmap currentBitmap = new Bitmap(this.pictureBox_Src.Image);

            Graphics g = Graphics.FromImage(currentBitmap);

            ImageAttributes ia = new ImageAttributes();

            float[][] colorMatrix =   {    

                new   float[]   {0.299f,   0.299f,   0.299f,   0,   0},

                new   float[]   {0.587f,   0.587f,   0.587f,   0,   0},

                new   float[]   {0.114f,   0.114f,   0.114f,   0,   0},

                new   float[]   {0,   0,   0,   1,   0},

                new   float[]   {0,   0,   0,   0,   1}

            };

            ColorMatrix cm = new ColorMatrix(colorMatrix);

            ia.SetColorMatrix(cmColorMatrixFlag.DefaultColorAdjustType.Bitmap);

            g.DrawImage(currentBitmapnew Rectangle(0, 0, currentBitmap.WidthcurrentBitmap.Height), 0, 0, currentBitmap.WidthcurrentBitmap.HeightGraphicsUnit.Pixelia);

            this.pictureBox_Dest.Image = (Image)(currentBitmap.Clone());

            g.Dispose();

        }

 

 

 

 

Graphics.GetHdc 方法

.NET Framework 4

获取与此 Graphics 关联的设备上下文的句柄。

命名空间:  System.Drawing
程序集:  System.Drawing(在 System.Drawing.dll 中)

语法

[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags =

SecurityPermissionFlag.UnmanagedCode)]

public IntPtr GetHdc()

返回值

类型:System.IntPtr
与此 Graphics 关联的设备上下文的句柄。

实现

IDeviceContext.GetHdc()

备注


设备上下文是一个基于 GDI 的 Windows 结构,它定义一组图形对象及其关联的特性,以及影响输出的图形模式。 此方法返回该设备上下文(字体除外)。由于未选择字体,使用 GetHdc 方法返回的句柄对 FromHdc方法进行调用将会失败。

GetHdc 方法调用和 ReleaseHdc 方法调用必须成对出现。 在 GetHdc 和 ReleaseHdc 方法对的范围内,通常仅调用 GDI 函数。 在该范围内对 Graphics(它产生 hdc 参数)的 GDI+ 方法的调用因 ObjectBusy错误而失败。 此外,GDI+ 忽略后续操作中对 hdc 参数的 Graphics 所做的所有状态更改。

示例


下面的代码示例设计为与 Windows 窗体一起使用,它需要 PaintEventArgse,即 Paint 事件处理程序的一个参数。 该示例演示如何调用 Windows GDI 函数以执行与 GDI+ Graphics 方法相同的任务。 代码执行下列操作:

  • 为 Windows DLL 文件 gdi32.dll 定义互操作性 DllImportAttribute 特性。 此 DLL 包含所需的GDI 函数。
  • 将该 DLL 中的 Rectangle 函数定义为外部函数。
  • 创建一支红色钢笔。
  • 利用该钢笔,使用 GDI+ DrawRectangle 方法将矩形绘制到屏幕。
  • 定义内部指针类型变量 hdc 并将它的值设置为窗体的设备上下文句柄。
  • 使用 GDI Rectangle 函数将矩形绘制到屏幕。

释放由 hdc 参数表示的设备上下文。

 

public class GDI

{

    [System.Runtime.InteropServices.DllImport("gdi32.dll")]

    internal static extern bool Rectangle(

       IntPtr hdc,

       int ulCornerX, int ulCornerY,

       int lrCornerX, int lrCornerY);

}

 

[System.Security.Permissions.SecurityPermission(

System.Security.Permissions.SecurityAction.LinkDemand, Flags =

System.Security.Permissions.SecurityPermissionFlag.UnmanagedCode)]           

private void GetHdcForGDI1(PaintEventArgs e)

{

    // Create pen.

    Pen redPen = new Pen(Color.Red, 1);

 

    // Draw rectangle with GDI+.

    e.Graphics.DrawRectangle(redPen, 10, 10, 100, 50);

 

    // Get handle to device context.

    IntPtr hdc = e.Graphics.GetHdc();

 

    // Draw rectangle with GDI using default pen.

    GDI.Rectangle(hdc, 10, 70, 110, 120);

 

    // Release handle to device context.

    e.Graphics.ReleaseHdc(hdc);

}

 

 

 

 

C#结合EmguCv编程

阅读数 1085

没有更多推荐了,返回首页