【问题标题】:32bit float image format getpixel?32位浮点图像格式getpixel?
【发布时间】:2017-05-02 16:56:47
【问题描述】:

如何在 C# 中使用 32 位浮点图像?

我更喜欢使用 openExr 但是,tiff 或类似的也可以,基本上我只想从磁盘加载一个 32 位浮点 (每像素/通道 32 位) 图像并获取像素单个通道的值并将其放入数组中,最好是尽可能简单的解决方案。

这是我制作的一个使用 png 的简单测试示例:

Download visual studio project

代码:C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.Diagnostics;
using System.IO;

namespace ImgToVxlForm
{
    public partial class Form1 : Form
    {
        Bitmap myBitmap;
        Byte[] byteArr;

        public Form1()
        {
            InitializeComponent();
        }

        private void browseBtn_Click(object sender, EventArgs e)
        {
            using (OpenFileDialog dlg = new OpenFileDialog())
            {
                dlg.Title = "Open Image";
                dlg.Filter = "png files (*.png)|*.png";
                if (dlg.ShowDialog() == DialogResult.OK)
                {
                    myBitmap = new Bitmap(dlg.FileName);
                    pictureBox1.Image = myBitmap;
                }
            }
        }

        private void runBtn_Click(object sender, EventArgs e)
        {
            byteArr = (ImageToArr(myBitmap));
            for (int i = 0; i < byteArr.Length; i++)
            {
                // Debug.WriteLine(byteArr[i]);
            }
            lb_debug.Text = byteArr.Length.ToString();
        }

        public static byte[] ImageToArr(Bitmap inBitmap)
        {
            int w = inBitmap.Width;
            int h = inBitmap.Height;
            Byte[] tmpByteArr = new byte[w * h];
            int count = 0;
            for (int y = 0; y < h; y++)
            {
                for (int x = 0; x < w; x++)
                {
                    Color pixelColor = inBitmap.GetPixel(x, y);
                    tmpByteArr[count] = pixelColor.R;
                    count++;
                }
            }
            return tmpByteArr;
        }
    }
}

Download 16 and 32bit test tiff image: (19KB)

【问题讨论】:

  • 那么你包含的代码是什么?不行吗?
  • 我的代码适用于 8 位图像(当前为 png),但我想使用 32 位浮点图像,如 tiff 或 openExr
  • 查找 DICOM 的代码示例。例如JPEG2000等图片支持HDR 12 bit+灰度
  • 另外,"...获取单个通道的像素值..." - 我认为您不了解高动态范围 (HDR) “32 位浮点” 图像。你不只是得到一个像素颜色。单个文件代表多种曝光,因此获取像素颜色将是您的 窗口级别 的一项功能。你不能只是inBitmap.GetPixel(x,y)
  • 嗯,认为你是不了解 HDR 32 位浮动图像的人......如果你用摄影制作 HDR 图像,你会合并多次曝光,32 位浮动图像只是每个通道的 32 位浮动值,一个 8 位 0-255 将是 0.0-1.0 浮点数,你可以有负数和远远超出的值,问题是我已经用 MaxScript .Net 编写了应用程序,它支持 getPixels(x,y) 32bit开箱即用浮动 OpenEXR,我只是想将该应用程序转换为独立的 C# 应用程序。

标签: c# .net image winforms hdr


【解决方案1】:

您正在使用基于 GDI+ Win32 API 的 System.Drawing 包。根据 ImageCodecInfo 类文档,您会看到它内置了对多种类型的支持:

图像编码器内置在 GDI+ 中,用于 BMP、JPEG、GIF、TIFF 和 PNG 格式。

理论上,使用 TIFF 图像应该可以正常工作。如果您需要添加对其他解码器的支持,您可以找到专门执行此操作的包,然后使用包的本机类型或编写生成 Bitmap 对象供您使用的包装器,或者您可以使用更具扩展性的 API,例如Windows 映像组件。

当您处于 .NET 领域时,有一个非常好的 DirectX(以及相关技术,包括 WIC)包装器,称为 SharpDX。这是一个GitHub sample,它展示了如何做到这一点。这里需要注意的是,它是 System.Drawing 的较低级别的 API,需要更多样板代码才能上线,以及直接向您公开 COM;好处是可以使用系统上可用的任何 WIC 兼容编解码器,并且您可以使用相同的 API 来枚举支持的格式。

【讨论】:

  • 目前它也适用于 16 位 tif(只需在浏览时更改过滤器),但如果我尝试,32 位 tif 不会出错。 16 位和 32 位 tiff 测试图像:patan77.com/download/16_32bit_tiff_test.zip
  • 可能会研究如何使用 WIC,考虑到它看起来有点像我想做的事情,发现 freeimage.sourceforge.net/download.html 所以我也想看看,我只是想要一个现在简单快速而肮脏的解决方案,因为将来仍然需要更换它。
  • TIFF 图像由 System.Drawing 原生支持。 OpenEXR 不是,SharpEXR 可以添加到您的代码中,然后在您的代码中使用。或者您可以添加一些 OpenEXR 编解码器并使用 Windows Imaging。无论哪种方式似乎都排除了简单快速和肮脏
  • 为了快速和肮脏,您可以尝试直接使用 TIFF 库;有一个 .NET 标准包形式的 .NET LibTiff 实现:nuget.org/packages/BitMiracle.LibTiff.NET
  • 解码 HDR 图像是一回事,显示是另一回事,您不会真正进入,这就是您遇到重大技术问题的地方。遗憾的是,仅使用 DirectX 也不会显示 HDR 图像。 TIFF 库的选择无关紧要
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 2011-01-27
相关资源
最近更新 更多