使用 C# 从图片框中的图像中添加或减去颜色 [英] Adding or subtracting color from an image in a pictureBox using C#

查看:38
本文介绍了使用 C# 从图片框中的图像中添加或减去颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想学习如何在 Visual Studio 中编写一些非常基本的图像编辑代码.我正在使用 openFileDialog 将图片加载到图片框中.我在互联网上发现了一些循环,它们旨在逐个像素地转换颜色,但由于各种原因(每个代码示例不同)都不起作用.添加(或减去)红色值以更改图片框中图像色调的正确方法是什么?我正在使用 C#.

I'd like to learn how to code some very basic image editing in Visual Studio. I'm using the openFileDialog to load a picture into a pictureBox. I've found some loops on the internet that are designed to convert color on a pixel by pixel basis, but for various reasons (that differ with each code sample) none work. What is the correct way to add to (or subtract from), for example, the red value, to change the tint of an image in a pictureBox? I'm using C#.

谢谢

这里有一个至少是一个起点的例子:

        Bitmap bmp = (Bitmap)Bitmap.FromFile(pictureBox1.ImageLocation);

        for (int x = 0; x < bmp.Width; x++)
        {
            for (int y = 0; y < bmp.Height; y++)
            {
                bmp.GetPixel(x, y);
                bmp.SetPixel(x, y, Color.FromArgb(128, 0, 128));
            }
        }

        pictureBox1.Image = bmp;
        MessageBox.Show("Done"); 

这允许我逐个像素地获取图像,并将颜色更改为紫色,在这种情况下.当然,这不是我想做的.我想要做的是获取每个像素的原始RGB值,并增加或减少这些值.换句话说,执行一些非常基本的色彩校正.

This allows me to get the image pixel by pixel, and change the color, in this case, to purple. Of course, that's not what I want to do. What I want to do, is get the original RGB value of each pixel, and increase or decrease the values. In other words, perform some very basic color correction.

如何获取每个像素的当前RGB,并设置新像素的RGB?

How do I get the current RGB of each pixel, and set the RGB of the new pixel?

我也看过这个帖子作为例子.问题是,我不知道如何使用 ModifyHue:

I have also seen this posted as an example. The problem is, I don't see how to use ModifyHue:

        var bmp = new Bitmap(pictureBox1.ImageLocation);
        for (int x = 0; x < bmp.Width; x++)
        {
            for (int y = 0; y < bmp.Height; y++)
            {
                Color oldColor = bmp.GetPixel(x, y);
                Color newColor = ModifyHue(oldColor);
                bmp.SetPixel(x, y, newColor);
            }
        }  

        pictureBox1.Image = bmp;

我意识到我应该第一次发布代码示例.谢谢

I realize I should have posted code samples the first time around. Thank you

推荐答案

这是一个使用 GetpixelSetPixel 的例子.

This is an example of using Getpixel and SetPixel.

对于(快得多)更快的过滤结果,请查看 Lockbits 以及使用 ColorMatrix

For (much much) faster filter results look into Lockbits and also into using a ColorMatrix

private void button2_Click(object sender, EventArgs e)
{
    // we pull the bitmap from the image
    Bitmap bmp = (Bitmap) pictureBox1.Image;

    // we change some picels
    for (int y = 100; y < bmp.Height; y++) 
    for (int x = 100; x < bmp.Width; x++)
    {
        Color c = bmp.GetPixel(x, y);
        bmp.SetPixel(x, y, Color.FromArgb(255, 255, c.G, c.B));
    }
    // we need to re-assign the changed bitmap
    pictureBox1.Image = (Bitmap) bmp;
}

更新:

上面的代码是一个非常简单的介绍.它很简单,但也很慢,而且不是很灵活.

The code above is a very simple introduction. It is simple but also very slow and it is not very flexible.

这是一个既快速又灵活的版本:

Here is a version that is both very fast and and much more flexible:

private void button3_Click(object sender, EventArgs e)
{
    // pick one of our filter methods
    ModifyHue hueChanger = new ModifyHue(MaxChannel);

    // we pull the bitmap from the image
    Bitmap bmp = (Bitmap)pictureBox1.Image;
    Size s = bmp.Size;
    PixelFormat fmt = bmp.PixelFormat;
    // we need the bit depth and we assume either 32bppArgb or 24bppRgb !
    byte bpp = (byte)(fmt == PixelFormat.Format32bppArgb ? 4 : 3);
    // lock the bits and prepare the loop
    Rectangle rect = new Rectangle(Point.Empty, s);
    BitmapData bmpData = bmp.LockBits(rect, ImageLockMode.ReadOnly, fmt);
    int size1 = bmpData.Stride * bmpData.Height;
    byte[] data = new byte[size1];
    System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, data, 0, size1);
    // loops
    for (int y = 0; y < s.Height; y++)
    {
        for (int x = 0; x < s.Width; x++)
        {
            // calculate the index
            int index = y * bmpData.Stride + x * bpp;
            // get the color
            Color c = Color.FromArgb( bpp == 4 ?data[index + 3]: 255 , 
                                      data[index + 2], data[index + 1], data[index]);
            // process it
            c = hueChanger(c, 2); 
            // set the channels from the new color
            data[index + 0] = c.B;
            data[index + 1] = c.G;
            data[index + 2] = c.R;
            if (bpp == 4) data[index + 3] = c.A;
        }
    }

    System.Runtime.InteropServices.Marshal.Copy(data, 0, bmpData.Scan0, data.Length);
    bmp.UnlockBits(bmpData);

   // we need to re-assign the changed bitmap
    pictureBox1.Image = (Bitmap)bmp;
}

上面的代码调用了一个delegate:

The above code calls a delegate:

public delegate Color ModifyHue(Color c, int ch);

并且 delegate 设置为调用一个简单的过滤器函数:

And the delegate is set to call a simple filter function:

public Color MaxChannel(Color c, int channel)
{
    if (channel == 1) return Color.FromArgb(255, 255, c.G, c.B);
    if (channel == 2) return Color.FromArgb(255, c.R, 255, c.B);
    if (channel == 3) return Color.FromArgb(255, c.R, c.G, 255);
    else return c;
}

这是另一种将 Color 更改为灰色

And here is another one that changes a Color to grey

public Color ToGreyscale(Color c, int dummy)
{
    byte val = (byte) ( (c.R * 0.299f + c.G * 0.587f + c.B *0.114f)  ) ;
    return Color.FromArgb(255, val, val,val);
}

请注意,我们要通过 delegate 调用的所有方法都需要具有相同的 signature.因此 ToGreyscale 也将 integer 作为第二个参数,即使它不使用它..

Note that all methods we want to call via a delegate need to have the same signature. Therefore ToGreyscale also takes an integer as second parameter, even though it doesn't use it..

另请注意,您可以像之前的简单示例一样限制 LockBits 循环开始和结束值以获得第二个屏幕截图..

Also note that you can limit the LockBits loop start and end values just like in the simple example before to get the second screenshot..

这篇关于使用 C# 从图片框中的图像中添加或减去颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆