【发布时间】:2022-01-14 16:30:23
【问题描述】:
我在实时更改图像颜色时遇到了一些问题。我的愿景是我的主项目的用户应该能够通过调整 RGB 通道的 3 个滑块来调整颜色。
我找到了一个很好的算法,可以完美地完成这项工作,但我现在面临的问题是颜色只会在应用程序中改变一次。但是在磁盘上我可以看到颜色的变化。
另一个潜在问题是每次颜色变化时将图像保存到磁盘可能是一个性能问题(尤其是在快速拖动滑块时),所以我希望可以将转换后的图像加载到像这样的控件直接来自对象/内存的按钮。
我已经设置了一个示例应用程序用于演示目的。在应用程序中,我只通过在文本框中输入值来更改红色通道。其他通道已在代码中预定义。
非常感谢您对此提供的任何帮助,因为我已经为这项任务苦苦挣扎了将近一周。
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