ImageMagic - WPF 图像颜色空间






3.80/5 (3投票s)
关于使用 WPF 显示和处理流行颜色空间中的图像数据的文章

引言
有没有想过如何仅使用 WPF 从 JPEG 中提取数据并对其进行操作?或者 WPF 在中等大小的图像(10 MB)上的表现如何?ImageMagic
程序提供了答案。该程序打开一个包含的 2592 x 3872 JPEG,提取其数据,并使用 RGB、CMYK 和 HSL 色彩空间通道重新显示它。提供了文件打开和保存功能。用户可以欣赏自己的图像,或将当前显示保存为 JPEG。这是一个熟悉流行色彩空间的绝佳方法。提供了将 RGB 数据数组转换为 CMYK 或 HSL 的方法,以及反向操作。
色彩空间背景
程序员通常熟悉 RGB 色彩空间。但对 CMYK、HSL 和黑白则不太熟悉。这些色彩空间各有其众所周知的用途。在 RGB 中难以操作的图像数据,在其他色彩空间中可能变得轻而易举。这里不提供每个色彩空间属性的详细描述。但是,这里有一些需要记住的事情。
- 设备依赖性 色彩空间不像人眼所见或设备所显示的那样定义颜色。例如,两个颜色在色彩空间中可能相距甚远,但人眼可能觉得它们相似。为了帮助解决这个定义问题,可以为图像提供设备配置文件。
- 色域缩小 CMYK 和黑白通常无法描述 RGB 中定义的每种颜色。换句话说,将图像从 RGB 转换为其他色彩空间时可能会丢失信息。
- 转换回 RGB 的问题 CMYK 以百分比(0-100)表示。色相以度数定义。为了确保准确地转换回 RGB,此处将 CMYK 和 HSL 定义为浮点数(0.0-1.0)。
- 缺乏公认标准 此程序中使用的色彩空间是根据教科书定义定义的。在商业世界中,这些定义的应用更为宽松。期望在此程序和 Photoshop 等软件渲染的图像之间看到差异。
CMYK 广泛用于商业印刷图像。它是一种基于油墨工作原理的减色模型。油墨会吸收一部分环境光的频率范围,并反射其余部分。CMYK 也是如此。例如,青色吸收红色。可以通过在每个像素中添加或删除青色的量来对图像的红色进行色彩平衡。类似地,使用品红色控制绿色,使用黄色控制蓝色。理论上,3 个通道(CMY)足以指定任何颜色。但是,当混合所有油墨时,会出现类似泥巴的颜色,而不是理论上的黑色。为了解决这个问题,使用了第四个通道 K,它添加了黑色。关于 CMYK 中使用的黑色量没有普遍共识。这里的算法会取出最大值。黑色油墨便宜。
HSL 用于方便的图像处理。想要更改图像的饱和度或亮度?只需将 S 或 L 通道乘以一个常数。类似地,H 通道可用于选择颜色范围或偏移颜色。也用于取色器或计算互补色。
黑白 有许多方法可以将彩色图像转换为黑白。每种方法都会产生不同的结果。这里提供了几种。尝试 Gray、Desaturated、K 和 L 按钮。通常,根据需要进行操作以产生所需的图像。Gray 算法相当流行。
代码工作原理
在显示的 WPF Image 对象内部,Source
属性包含一个 BitmapSource
对象。BitmapSource
决定了 WPF 显示的图像。它具有标识要显示的图像的像素尺寸、格式、每英寸点数等的属性。BitmapSource
对象还有一个名为 CopyPixels
的方法,可用于检索与图像相关的原始 RGB 数据。检索后,可以操作 RGB 数据并用于创建新的 BitmapSource
对象。通过将新 BitmapSource
更新到已显示图像的 Source
属性,即可显示经过处理的数据。
ImageMagic
显示一个由 Window1.xaml 文件创建的名为 rgbImage
的单个命名图像。rgbImage
从包含的文件 DSC_4394copy.jpg 加载。您可以替换此文件为您自己的 JPEG,如果您想改变 ImageMagic
的启动方式。命名 XAML 图像可以被程序逻辑访问,这意味着 rgbImage
的 Source
属性可以被读取或更新。因此,XAML 启动了一切。但是,程序必须提供一种方法来提取 RGB 数据并创建新的 BitmapSources
。
RGB 数据的提取和新 BitmapSources
的创建由 static BmsEngine
类处理。为了创建与原始图像兼容的新 BitmapSources
,必须初始化 BmsEngine
。当 RGB 按钮加载时,将使用以下代码执行此操作:
void OnLoad(object sender, RoutedEventArgs e)
{
tb1.Text = "Image Inited.\n"; //signal operator
rgbBms = (BitmapSource)this.rgbImage.Source; //save the original BitmapSource
BmsEngine.Init(rgbBms); //Init the BmsEngine
rgbValues = BmsEngine.GetRgbData(); //save the original rgb data
} // OnLoad()
以下代码显示了当单击 Yellow 按钮时如何使用 BmsEngine
创建新的 BitmapSource
。这是一个昂贵的操作。
private void Yellow_Click(object sender, RoutedEventArgs e)
{
tb1.Text += "Yellow clicked\n"; //signal operator
if (yellowBms == null) //Has the BitmapSource for yellow been previously created?
{
byte[] newJpegBytes = BmsEngine.GetRgbData(); //Get the original rgb data
for (int i = 0; i < BmsEngine.dataLength; i += 4) //4 = 3 bytes for rgb + 1
//for transparency (not used)
{
newJpegBytes[i+(int)RGB.Blue] = 0; //zap blue channel to get Yellow=R+G;
}
yellowBms = BmsEngine.CloneBms(newJpegBytes); //Create a new BitmapSource
//from modified data and save it
}
this.rgbImage.Source = yellowBms; //display new BitmapSource
}
Using the Code
程序开始时,包含的图像以 RGB 格式显示。屏幕左侧有 20 个按钮,用于执行简单任务。鼓励操作员使用自己的图像。CMYK 或 HSL 通道的显示通常令人惊讶。这非常依赖于使用的图像。作为转换有效的检查,请单击按钮将色彩空间转换回 RGB。您应该会看到原始 RGB 图像。
代码很简单。如果您希望重用转换逻辑,请查看 CmykSpace.cs 和 HslSpace.cs 中的类。
关注点
WPF 性能以及色彩空间算法 取决于图像大小。本程序提供的图像反映了当今典型 DSLR 的输出。它比专业相机生成的图像小几倍。随着像素数量的增长速度超过计算机速度的趋势,必须采用新的方法来处理图像数据。
为减小下载大小,我对 JPEG 应用了增强压缩。压缩后的图像在 RGB 中看起来还可以,但在 HSL 通道中的退化非常明显。
历史
- 2009 年 6 月 16 日:初始发布