这看起来与 8 位图像有关。 8 位图像的优点是您只需要一个包含您的值的一维字节数组,and you can pretty much load that straight into an image, using LockBits and Marshal.Copy.
嗯,几乎是直的。 8 位图像上的像素值实际上并不是您的颜色。它们是对调色板的引用,实际上包含您的颜色。但是如果您希望图像上的值 0 到 255 指代颜色 (0,0,0) 到 (255,255,255),那么您需要做的就是生成一个包含您想要的 256 种灰色颜色的调色板,可以处理在一个简单的for-loop 中。
但首先是 CSV。如果这真的只是简单的“数字、逗号、数字”信息,您可以简单地使用 String.Split,但对于任何更高级/可靠的 CSV 解析,可以处理包含引号和/或拆分字符的引用块的特殊情况,你需要TextFieldParser。有关这方面的更多信息,请参阅 here,尽管我认为为此我们可以选择 String.Split 解决方案。
为方便起见,我在此处设置了 startColumn 变量,但在您的情况下,它当然是“3”。
public static Bitmap GrayImageFromCsv(String[] lines, Int32 startColumn, Int32 maxValue)
{
// maxValue cannot exceed 255
maxValue = Math.Min(maxValue, 255);
// Read lines; this gives us the data, and the height.
//String[] lines = File.ReadAllLines(path);
if (lines == null || lines.Length == 0)
return null;
Int32 bottom = lines.Length;
// Trim any empty lines from the start and end.
while (bottom > 0 && lines[bottom - 1].Trim().Length == 0)
bottom--;
if (bottom == 0)
return null;
Int32 top = 0;
while (top < bottom && lines[top].Trim().Length == 0)
top++;
Int32 height = bottom - top;
// This removes the top-bottom stuff; the new array is compact.
String[][] values = new String[height][];
for (Int32 i = top; i < bottom; i++)
values[i - top] = lines[i].Split(',');
// Find width: maximum csv line length minus the amount of columns to skip.
Int32 width = values.Max(line => line.Length) - startColumn;
if (width <= 0)
return null;
// Create the array. Since it's 8-bit, this is one byte per pixel.
Byte[] imageArray = new Byte[width*height];
// Parse all values into the array
// Y = lines, X = csv values
for (Int32 y = 0; y < height; y++)
{
Int32 offset = y*width;
// Skip indices before "startColumn". Target offset starts from the start of the line anyway.
for (Int32 x = startColumn; x < values[y].Length; x++)
{
Int32 val;
// Don't know if Trim is needed here. Depends on the file.
if (Int32.TryParse(values[y][x].Trim(), out val))
imageArray[offset] = (Byte) Math.Max(0, Math.Min(val, maxValue));
offset++;
}
}
// generate gray palette for the given range, by calculating the factor to multiply by.
Double mulFactor = 255d / maxValue;
Color[] palette = new Color[maxValue + 1];
for (Int32 i = 0; i <= maxValue; i++)
{
// Away from zero rounding: 2.4 => 2 ; 2.5 => 3
Byte g = (Byte)Math.Round(i * mulFactor, MidpointRounding.AwayFromZero);
palette[i] = Color.FromArgb(g, g, g);
}
// Since the palette is incomplete, give the color fill arg as Color.White
return BuildImage(imageArray, width, height, width, PixelFormat.Format8bppIndexed, palette, Color.White);
}
称为:
String[] lines = File.ReadAllLines(path);
using (Bitmap img = GrayImageFromCsv(lines, 3, 15))
{
// null = conversion failed. Could log/show warning.
if (img != null)
img.Save("fromcsv.png", ImageFormat.Png);
}
在主处理结束时调用的 BuildImage 函数执行上述“将字节数组加载到图像中”操作。 It can be found here. 请注意,“步幅”是图像一行上的字节数。虽然这与 8 位图像的宽度相同,但由于每个字节是一个像素,因此对于其他格式会有所不同。