我确信有很多最佳方法可以做到这一点。
正如@Groo 在评论部分完美指出的那样,可以使用例如LockBits方法在实例中写入和读取像素颜色Bitmap
。更进一步,可以使用计算机的图形卡进行实际计算。
此外,Color ToGrayscaleColor(Color color)
将颜色转换为其灰度版本的方法在光学上是不正确的。有一组实际需要应用于颜色分量强度的比率。我只是使用了 1、1、1 的比率。这对我来说是可以接受的,但对于艺术家或科学家来说可能是可怕的。
在评论部分,@plinth 非常高兴地指出了这个问题,如果您想进行解剖学上正确的转换:Converting RGB to grayscale/intensity
只是想分享这个非常容易理解和实施的解决方案:
首先是一个小帮手把颜色变成它的灰度版本:
public static Color ToGrayscaleColor(Color color) {
var level = (byte)((color.R + color.G + color.B) / 3);
var result = Color.FromArgb(level, level, level);
return result;
}
然后对于彩色位图到灰度位图的转换:
public static Bitmap ToGrayscale(Bitmap bitmap) {
var result = new Bitmap(bitmap.Width, bitmap.Height);
for (int x = 0; x < bitmap.Width; x++)
for (int y = 0; y < bitmap.Height; y++) {
var grayColor = ToGrayscaleColor(bitmap.GetPixel(x, y));
result.SetPixel(x, y, grayColor);
}
return result;
}
双打部分很简单。该Bitmap
对象是您可以在各种操作中使用的实际图像的内存表示。颜色深度和图像格式的细节只是加载和保存实例Bitmap
到流或文件的问题。我们现在不需要关心那些:
public static double[,] FromGrayscaleToDoubles(Bitmap bitmap) {
var result = new double[bitmap.Width, bitmap.Height];
for (int x = 0; x < bitmap.Width; x++)
for (int y = 0; y < bitmap.Height; y++)
result[x, y] = (double)bitmap.GetPixel(x, y).R / 255;
return result;
}
并将双数组转换回灰度图像:
public static Bitmap FromDoublesToGrayscal(double[,] doubles) {
var result = new Bitmap(doubles.GetLength(0), doubles.GetLength(1));
for (int x = 0; x < result.Width; x++)
for (int y = 0; y < result.Height; y++) {
int level = (int)Math.Round(doubles[x, y] * 255);
if (level > 255) level = 255; // just to be sure
if (level < 0) level = 0; // just to be sure
result.SetPixel(x, y, Color.FromArgb(level, level, level));
}
return result;
}
以下几行:
if (level > 255) level = 255; // just to be sure
level < 0) level = 0; // just to be sure
如果您在双打上进行操作并且想要为小错误留出空间,那么真的在那里。