【问题标题】:How to change value of red/green/blue/alpha values from pixels如何从像素更改红/绿/蓝/alpha 值
【发布时间】:2019-06-18 17:22:40
【问题描述】:

我正在开发一个处理图像的软件,现在我想改变白平衡并在我的照片上添加一些饱和度,所以我必须处理每个像素值。 我试图将我的 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;     

    }

【问题讨论】:

  • 您使用 WinForms Bitmap 类有什么特别的原因吗? WPF BitmapSource(BitmapImage 和 WriteableBitmap 的基类)具有 CopyPixels 方法来检索其原始像素缓冲区。您可以操作该缓冲区并从中创建一个新的 BitmapSource。或者您直接操作 WriteableBitmap 的像素。除此之外,几乎没有必要将 WriteableBitmap 转换为 BitmapImage,因为您通常可以使用一个代替另一个,例如作为 Image 元素的 Source 属性的值。
  • 不,没有。我只是初学者,并试图在本周末之前完成这个应用程序,并且我正在尝试我找到的所有内容。我正在尝试获取我的像素并修改它们。目前我想让我的所有像素都变成-30红色和-30绿色。这就是我暂时想要的。我可以处理我的位图,而不是副本。

标签: c# wpf image-processing


【解决方案1】:

假设您在 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 属性。它是“就地”改变的。

【讨论】:

  • 伙计,非常感谢。你真的拯救了我和我的项目。非常感谢您的帮助,从第一次尝试就成功了。
  • 不客气。您可能还想看看如何直接访问 WriteableBitmap 的 BackBuffer:docs.microsoft.com/en-us/dotnet/api/…
猜你喜欢
  • 2010-12-02
  • 2016-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-19
  • 2013-07-17
  • 1970-01-01
相关资源
最近更新 更多