• C#对图像像素处理的三种方式


    C#对图像像素处理的三种方式

    Posted on 2009-11-02 22:33  feisky  阅读(3046)  评论(0)  编辑  收藏

    在C#中,可以采用直接获取像素法(GetPixel)、内存拷贝法和指针法(unsafe)来获取图像像素并进行处理。

    下面以图像的灰度化为例说明具体的处理方法和速度的比较(1G内存,P4处理器测试)。

    1.GetPixel方法

    GetPixel(i,j)和SetPixel(i, j,Color)可以直接得到图像的一个像素的Color结构,但是处理速度比较慢,处理一副180*180的图像大约需要100.48ms。

    private void pixel_Click(object sender, EventArgs e)
    {
        if(curBitmap != null)
        {
            myTimer.ClearTimer();
            myTimer.Start();
            Color curColor;
            int ret;
            for (int i = 0; i < curBitmap.Width; i++)
            {
                for (int j = 0; j < curBitmap.Height ; j++)
                {
                    curColor = curBitmap.GetPixel(i,j);
                    ret = (int)(curColor.R * 0.299 + curColor.G * 0.587 + curColor.B * 0.114);
                    curBitmap.SetPixel(i, j, Color.FromArgb(ret, ret, ret));
                }
            }
            myTimer.Stop();
            timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒"; 
            Invalidate();
        }
    }
    

    2.内存拷贝法

    内存拷贝法就是采用System.Runtime.InteropServices.Marshal.Copy将图像数据拷贝到数组中,然后进行处理,这不需要直接对指针进行操作,不需采用unsafe,处理速度和指针处理相差不大,
    处理一副180*180的图像大约需要1.32ms。
    private void memory_Click(object sender, EventArgs e)
    {
        if (curBitmap != null)
        {
            myTimer.ClearTimer();
            myTimer.Start();
            Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
            System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            int bytes = curBitmap.Width * curBitmap.Height * 3;
            byte[] rgbValues = new byte[bytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);
            double colorTemp = 0;
            for (int i = 0; i < rgbValues.Length; i += 3)
            {
                colorTemp = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114;
                rgbValues[i] = rgbValues[i + 1] = rgbValues[i + 2] = (byte)colorTemp;
            }
            System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
            curBitmap.UnlockBits(bmpData);
            myTimer.Stop();
            timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒"; 
            Invalidate();
        }
    }
    

    3.指针法

    指针在c#中属于unsafe操作,需要用unsafe括起来进行处理,速度最快,处理一副180*180的图像大约需要1.16ms。
    采用byte* ptr = (byte*)(bmpData.Scan0); 获取图像数据根位置的指针,然后用bmpData.Scan0获取图像的扫描宽度,就可以进行指针操作了。
     
    private void pointer_Click(object sender, EventArgs e)
    {
        if (curBitmap != null)
        {
            myTimer.ClearTimer();
            myTimer.Start();
            Rectangle rect = new Rectangle(0, 0, curBitmap.Width, curBitmap.Height);
            System.Drawing.Imaging.BitmapData bmpData = curBitmap.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite, curBitmap.PixelFormat);
            byte temp = 0;
            unsafe
            {
                byte* ptr = (byte*)(bmpData.Scan0);
                for (int i = 0; i < bmpData.Height; i++)
                {
                    for (int j = 0; j < bmpData.Width; j++)
                    {
                        temp = (byte)(0.299 * ptr[2] + 0.587 * ptr[1] + 0.114 * ptr[0]);
                        ptr[0] = ptr[1] = ptr[2] = temp;
                        ptr += 3;
                    }
                    ptr += bmpData.Stride - bmpData.Width * 3;
                }
            }
            curBitmap.UnlockBits(bmpData);
            myTimer.Stop();
            timeBox.Text = myTimer.Duration.ToString("####.##") + " 毫秒"; 
            Invalidate();
        }
    }
  • 相关阅读:
    COGS 2104. [NOIP2015]神奇的幻方
    洛谷 P1387 最大正方形
    包和一些常用的模块
    模块
    模块的导入和使用
    函数迭代器与生成器
    函数的小知识
    函数的闭包和装饰器
    函数的进阶
    初识函数
  • 原文地址:https://www.cnblogs.com/guanshan/p/guan2020-11-26_001.html
Copyright © 2020-2023  润新知