如何从像素更改红色/绿色/蓝色/ alpha值的值

时间:2019-06-18 06:45:30

标签: c# wpf image-processing

我正在处理图像软件,现在我想更改白平衡并在照片上添加一些饱和度,所以我必须处理每个像素值。 我试图将我的BitmapImage转换为WritableBitmap,然后尝试了这段代码。但是,如果我运行它,我的图像会变成绿色。 我想从该图像中获取像素,然后将其设置为新值。 我搜索了许多解决方案,但没有找到任何解决方案,因此也许有人可以帮助我编写代码。谢谢。

    public static WriteableBitmap Colors(Bitmap Image)
    {
        int width = Image.Width;
        int height = Image.Width;
        byte[,,] pixels = new byte[height, width, 4];
        WriteableBitmap wbitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgra32, null);

        var target = new Bitmap(Image.Width, Image.Height);

        for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                pixels[i, j, 1] -= 30;
                pixels[i, j, 3] -= 30;
            }

        }
        byte[] pixels1d = new byte[height * width * 4];
        int index = 0;
        for (int row = 0; row < height; row++)
        {
            for (int col = 0; col < width; col++)
            {
                for (int i = 0; i < 4; i++)
                    pixels1d[index++] = pixels[row, col, i];
            }
        }
        Int32Rect rect = new Int32Rect(0, 0, width, height);
        int stride = 4 * width;
        wbitmap.WritePixels(rect, pixels1d, stride, 0);
        return wbitmap;
    }

然后我像这样运行它:

    private void run_OnClick(object sender, RoutedEventArgs e)
    {            
       // Contrastt(BitmapImage2Bitmap(bitmap), 10);
       // MedianFilter(BitmapImage2Bitmap(bitmap),5);

        WriteableBitmap writeableBitmap = new WriteableBitmap(imageX);
        BitmapImage colored = ConvertWriteableBitmapToBitmapImage(Colors((BitmapImage2Bitmap(bitmap))));
        ImageBrush brush = new ImageBrush();
        brush.ImageSource = imageX ;
        CanvasProcessedImage.Background = brush;     

    }

1 个答案:

答案 0 :(得分:0)

假设您已经有一个source变量的BitmapSource(或类似BitmapImage的派生类的实例),则首先要创建一个具有已知像素格式的BitmapSource,然后根据该像素创建一个WritabelBitmap:

// source is a BitmapSource with whatever PixelFormat
var format = PixelFormats.Bgra32;
var temp = new FormatConvertedBitmap(source, format, null, 0); // force BGRA
var bitmap = new WriteableBitmap(temp);

现在,您可以直接在WriteableBitmap的BackBuffer属性中操作数据,或者首先更简单一些,然后按如下所示创建缓冲区的副本:

var width = bitmap.PixelWidth;
var height = bitmap.PixelHeight;
var stride = bitmap.BackBufferStride;
var buffer = new byte[stride * height];
bitmap.CopyPixels(buffer, stride, 0);

然后操作缓冲区并将其写回到WriteableBitmap。既然已经指定了PixelFormat,就知道每个4字节像素值中的哪个字节分别是B,G,R和A。

for (int i = 0; i < buffer.Length; i += 4)
{
    // Blue
    //buffer[i + 0] = ...

    // Green
    buffer[i + 1] = (byte)Math.Max(buffer[i + 1] - 30, 0);

    // Red
    buffer[i + 2] = (byte)Math.Max(buffer[i + 2] - 30, 0);

    // Alpha
    //buffer[i + 3] = ...
}

bitmap.WritePixels(new Int32Rect(0, 0, width, height), buffer, stride, 0);

在将WriteableBitmap分配给Image元素的Source属性或ImageBrush的ImageSource属性后,您可以稍后再调用WritePixels(并根据需要多次调用)无需将其重新分配给Source / ImageSource属性。更改为“就地”。