65.9K
CodeProject 正在变化。 阅读更多。
Home

一个用于颜色操作的 VB.NET 类

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.45/5 (4投票s)

2003年7月8日

LGPL3

3分钟阅读

viewsIcon

165263

downloadIcon

710

一个用于高级色度图像处理和操作的 VB.NET 类

引言

尽管 Windows 似乎内置了一些颜色管理,但在任何 .NET 类中都找不到这些(至少据我所知)。类似地,GDI 和 GDI+ 几乎不包含任何颜色操作或色度图像处理的规定(有一个颜色矩阵,但没有卷积或任何更高级的图像处理。而且很难操作线性光 RGB 值而不是伽马校正的 R*G*B* 值)。似乎 Microsoft 并不关心图像处理和色度的基本原理和基础,而是采用了一种简单的实用方法,“看,我可以调整亮度或色调”……这没什么错,但我们对 .NET 这样一个综合框架有更高的期望(也许我们确实应该看看 Java 和 Java 高级成像,或 JAI,它似乎建立在更深入研究的基础上)。最终结果(呵呵)是,对于我的色度成像研究,我需要编写一个支持库,最初是用 VB6 编写的。这个库现在已经转换为 VB.NET。

背景

对颜色进行介绍很有用,查看 Charles Poynton 页面,仅举一例。

使用代码

该库主要由共享函数和子程序组成,并非为了速度而编写,相反,我希望它清晰易读。它大量使用重载,并且需要另一个名为 Algebra 的类才能运行,该类包含在下载中。它的主要用途是从一个颜色空间移动到另一个颜色空间,并使用颜色三元组数组应用伽马校正,但它还包含一些例程,用于支持使用非托管指针的图像处理和 GDI+。支持的颜色空间是(符号中的 * 表示非线性光颜色空间,例如在伽马校正之后)

  • 通用 RGB 和 R*G*B*。用户必须提供转换为其他颜色空间的转换,因为实际上有数百种 RGB 颜色空间!
  • ITU Rec 709 sRGB 和 sR*G*B*。网络、显示器和打印机上使用的标准 RGB 颜色空间。
  • CIE XYZ。一种基于人类视觉的三刺激值颜色空间,包含所有可见颜色。
  • CIE L*a*b*。一个感知上均匀的颜色空间。在这个空间中,欧几里德度量与人类观察者感知到的颜色差异成正比,尽管是在相当有限的一组观看条件下。

该库还定义了几个白点

  • CIE D65:中午日光模拟,色温为 6500 K
  • CIE D55:日光模拟,色温为 5500 K
  • CIE A:钨丝灯照明,色温为 3800 K
  • CIE C:荧光灯照明,相关色温约为 5200 K
  • CIE D93:色温为 9300 K,类似于某些计算机显示器
  • HDTVD65:高清电视白点,色温为 6500 K

支持颜色空间之间的几种类型的多项式变换,从 3x3 线性变换到高度非线性的 20 项变换。该类还提供了一种计算此变换的方法,给定输入颜色空间中的一组颜色及其在输出颜色空间中的所需映射(基于代数类提供的奇异值分解解决方案。请注意,此例程是从“C 数值食谱”转换而来,这是一组众所周知的数值例程)。该类还允许在使用多项式变换之前使用查找表或 LUT。

最简单的方法是查看下载中的代码

使用该类的示例代码

这是一段 C# 代码,它遍历图像并使用给定的多项式变换和查找表转换每个像素。此代码还演示了 C# 中非托管指针的使用,与使用带有 GetPixel SetPixel 的托管 GDI+ 类相比,这大大提高了速度。这在 VB.NET 中是不可能的!假设已正确导入 *Color.vb* 类。

public static unsafe void PolynomialTransform(Bitmap objBitmap, 
    float[,]Transform, float[,] LUT )
{
//Do LUT and polynomial transform on whole image ... 
//Use unmanaged pointers to go FAST. In Memory RGB values 
//are stored in the order B-G-R!!!!!! 

int x, y, iPtrPixel0; 

Rectangle rect = new Rectangle(0,0,objBitmap.Width,objBitmap.Height);
System.Drawing.Imaging.BitmapData bitmapData = objBitmap.LockBits(rect, 
System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);

iPtrPixel0 = bitmapData.Scan0.ToInt32();

//Byte pointer and corresponding managed array type 
byte * byPixel;
byte[] bySafePixel = new byte[3];

for (y = 0; y < bitmapData.Height; y ++)
  {
  byPixel = (byte *)(iPtrPixel0 + y * bitmapData.Stride);
  for (x = 0; x < bitmapData.Width; x ++)
    {
    bySafePixel[2] = *byPixel;
    bySafePixel[1] = *(byPixel + 1);
    bySafePixel[0] = *(byPixel + 2);

    Color.GammaRGBToGammasRGB(bySafePixel, Transform, LUT);
    *byPixel = bySafePixel[2];
    byPixel ++;
    *byPixel = bySafePixel[1];
    byPixel ++;
    *byPixel = bySafePixel[0];
    byPixel ++;
    }
  }
objBitmap.UnlockBits(bitmapData);
}

关注点

没有特别的兴趣点,除了即使使用非托管指针,.NET 中的图像处理仍然非常慢!

© . All rights reserved.