【问题标题】:What is the alternative to Bitmap so that I can store double/float values in it's pixels without casting to int/byte?Bitmap 的替代方法是什么,以便我可以在它的像素中存储双精度/浮点值而不转换为 int/byte?
【发布时间】:2017-10-23 00:21:01
【问题描述】:

我正在从一个双精度数组创建一个位图(对于每个像素,我从数组中定义它的颜色)。由于 Color 类型只能存储整数值(从 0 到 255),因此我必须将数组值转换为 int 或 byte,然后再将它们存储到位图的颜色值中。但是,当然,由于转换,我会丢失信息。所以我需要一些方法来存储我的双精度值,以某种方式表示图像的颜色,而不会造成任何损失。

更新: 问题是 Bitmap 使用 Color 类型,它需要小范围内的整数。最好有可能以双值形式(如从 0 到 1)表示颜色并将其存储在图像中。但据我所知,Bitmap 不提供这个机会。

【问题讨论】:

  • 你的双打精度是多少?您可以想象乘以 10 以删除小数位并将其存储,然后在您需要信息时将其除以
  • @capncoolio,谢谢,我喜欢这个想法,现在我会记住,如果发生此类问题或类似问题,则没有此类解决方案。但是我的问题不够清楚(对不起,一开始没有想到)。通过说“我正在从一个双精度数组创建一个位图”,我的意思是对于每个像素,我都从双精度数组定义它的颜色。但是颜色的数字表示应该在 0-255 范围内。乘以 10 不会使我的双重适合颜色类型范围。所以不幸的是,这种情况对我不起作用。 - 更新我的问题
  • 双精度是 64 位(8 字节)浮点数,因此您可以使用 BitConvert 来获取 8 字节。
  • @jdweng,您的意思是 BitConverter.DoubleToInt64Bits (Double) 方法?但 Color 类型要求 Int32。
  • 浮点值乘以 255

标签: c# bitmap


【解决方案1】:

让我们看看这里:

如果您希望单个 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 位redalpha 的前 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 位的位图……当然可以存在,但为什么呢?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多