让我们看看这里:
如果您希望单个 double 表示像素的 RGB(以及可选的 A)字段,则必须分离出相应的位范围。
首先,让我们创建一个doubles 数组来表示我们的像素(我们有一个名为_rand 的静态RNG):
double[,] vals = new double[500,500];
for (int i = 0; i < 500; i++)
for (int j = 0; j < 500; j++)
vals[i, j] = _rand.NextDouble();
接下来,让我们创建我们的位图:
Bitmap bit = new Bitmap(500,500);
现在我们要做的是将这些双精度中的每一个乘以int.MaxValue,并将低 8 位分开为blue,将中间右 8 位分开为green,中间左 8 位red 和 alpha 的前 8 位。 (我们暂时不会使用 alpha)
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < 500; j++)
{
var val = (int) (vals[i, j] * int.MaxValue);
var b = (val & 0x000000FF);
var g = (val & 0x0000FF00) >> 8;
var r = (val & 0x00FF0000) >> 16;
//var a = (val & 0xFF000000) >> 24; (this would get you the alpha)
//Set the pixel at [i, j] to (r, g, b)
bit.SetPixel(i, j, Color.FromArgb(r, g, b));
}
}
这与 32 位位图的精确度差不多。每个像素由一个 32 位数字表示;不是每个像素的每种颜色。
将产生样本(随机)输出的完整程序如下(我删除了我们在double[,] 中创建和存储值的部分并直接进行了计算:
using System;
using System.Drawing;
namespace BitmapTest
{
class Program
{
private static Random _rand = new Random();
private static void Main(string[] args)
{
Bitmap bit = new Bitmap(500, 500);
for (int i = 0; i < 500; i++)
{
for (int j = 0; j < 500; j++)
{
var val = (int)(_rand.NextDouble() * int.MaxValue);
var b = (val & 0x000000FF);
var g = (val & 0x0000FF00) >> 8;
var r = (val & 0x00FF0000) >> 16;
//var a = (val & 0xFF000000) >> 24; (this would get you the alpha)
bit.SetPixel(i, j, Color.FromArgb(r, g, b));
}
}
bit.Save(@"C:\Temp\img.bmp");
bit.Dispose();
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
}
}
}
据我所知,不幸的是,这里没有办法避免精度损失,因为位图像素值必须包含 32 位内的所有信息(显然是 32 位位图),double 是已经比那个大了。如果您想将 ARGB 存储为 4 个不同的 64 位 doubles,您需要一个 256 位的位图……当然可以存在,但为什么呢?