【问题标题】:C# WPF - 实时更改图像颜色的问题
【发布时间】:2022-01-14 16:30:23
【问题描述】:

我在实时更改图像颜色时遇到了一些问题。我的愿景是我的主项目的用户应该能够通过调整 RGB 通道的 3 个滑块来调整颜色。

我找到了一个很好的算法,可以完美地完成这项工作,但我现在面临的问题是颜色只会在应用程序中改变一次。但是在磁盘上我可以看到颜色的变化。

另一个潜在问题是每次颜色变化时将图像保存到磁盘可能是一个性能问题(尤其是在快速拖动滑块时),所以我希望可以将转换后的图像加载到像这样的控件直接来自对象/内存的按钮。

我已经设置了一个示例应用程序用于演示目的。在应用程序中,我只通过在文本框中输入值来更改红色通道。其他通道已在代码中预定义。

非常感谢您对此提供的任何帮助,因为我已经为这项任务苦苦挣扎了将近一周。

红色通道上第一个值为 0 的值显示正常

第二个值为 255 的值应该将图像更改为黄色,但没有

当我在“照片”应用中打开图像时,图像会更新

using System;
using System.Windows;
using Point = System.Drawing.Point;
using System.Drawing;
using System.Drawing.Imaging;
using Image = System.Drawing.Image;
using System.Windows.Media.Imaging;
using Rectangle = System.Drawing.Rectangle;
using System.Threading;

namespace ImageColorConversionTesting
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>

    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();

        }

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            byte number;

            if(System.Byte.TryParse(NumberTextBox.Text, out number))
            {

                LoadImage(number);

            }

        }

        private void LoadImage(byte redcolor)
        {
            Bitmap newImage = ConvertImageColor(255, redcolor, 255, 0, @"Images\house-64.png");
            newImage.Save("test.png");
            System.Windows.Controls.Image imgHome = new System.Windows.Controls.Image();
            imgHome.Source = BitmapFromUri(new Uri("test.png", UriKind.Relative));
           
            image3.Source = imgHome.Source;

        }

        public Bitmap ConvertImageColor(int alpha, int red, int green, int blue, string filename)
        {
            System.Drawing.Color newColor = System.Drawing.Color.FromArgb(alpha, red, green, blue);
            Image originalImage = Image.FromFile(filename);
            Bitmap newImage = ToColorTone(originalImage, newColor);

            return newImage;

        }

        private Bitmap ToColorTone(Image image, System.Drawing.Color color)
        {

            int brightness = color.A;
            float scale = brightness;

            float r = color.R / 255f * scale;
            float g = color.G / 255f * scale;
            float b = color.B / 255f * scale;

   
            ColorMatrix cm = new ColorMatrix(new float[][]
            {
                new float[] {r, 0, 0, 0, 0},
                new float[] {0, g, 0, 0, 0},
                new float[] {0, 0, b, 0, 0},
                new float[] {0, 0, 0, 1, 0},
                new float[] {0, 0, 0, 0, 1}
            });

            ImageAttributes ImAttribute = new ImageAttributes();
            ImAttribute.SetColorMatrix(cm);

          
            Point[] points =
            {
                new Point(0, 0),
                new Point(image.Width - 1, 0),
                new Point(0, image.Height - 1),
            };
            Rectangle rect = new Rectangle(0, 0, image.Width, image.Height);

            Bitmap myBitmap = new Bitmap(image.Width, image.Height);
            using(Graphics graphics = Graphics.FromImage(myBitmap))
            {
                graphics.DrawImage(image, points, rect, GraphicsUnit.Pixel, ImAttribute);
            }
            return myBitmap;
        }

        public static System.Windows.Media.ImageSource BitmapFromUri(Uri source)
        {
            var bitmap = new BitmapImage();
            bitmap.BeginInit();
            bitmap.UriSource = source;
            bitmap.CacheOption = BitmapCacheOption.OnLoad;
            bitmap.EndInit();
            return bitmap;
        }

    }
}

【问题讨论】:

  • 为什么要写入和读取图像文件,而不是直接操作内存中 BitmapSource 的颜色(像素值或调色板条目)?
  • 因为我不知道怎么做,我是一个相当新的程序员。我只是在网上搜索了解决方案,发现了一个有效的算法。
  • 这不是正确的方法。看看 BitmapSource 类,也许还有 WriteableBitmap。熟悉如何通过 BitmapSource 类的静态 Create 方法之一从现有像素缓冲区创建 BitmapSource。
  • 你确定你真的需要处理位图吗?也许您可以在 Path 元素中更改绘图的填充画笔。
  • 我将尝试使用 BitmapSource 类。谢谢! :)

标签: c# wpf image-processing image-manipulation


【解决方案1】:

我试过你提供的代码,图片不刷新的原因是BitmapImage的缓存。

BitmapImage.CreateOptions的官方文档中说:

CreateOptions 的另一个可能值是 BitmapCreateOptions.IgnoreImageCache。只有在您知道由统一资源标识符 (URI) 检索到的源图像文件有可能随时间发生变化时,才应使用 BitmapCreateOptions.IgnoreImageCache。

CreateOptions后,效果很好。

public static System.Windows.Media.ImageSource BitmapFromUri(Uri source)
{
    var bitmap = new BitmapImage();
    bitmap.BeginInit();
    bitmap.UriSource = source;
    bitmap.CacheOption = BitmapCacheOption.OnLoad;
    // NOTE: ignore the image cache
    bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
    bitmap.EndInit();
    return bitmap;
}

根据其他朋友的建议,使用BitmapSource是更好的实现方式。

【讨论】:

  • 感谢您的反馈。我已经按照 Clemens 之前的建议使用 BitmapSource 解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2018-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多