【CSharp】将ushort数组保存为1通道位深16bit的Tiff图片

Source

【CSharp】将ushort数组保存为1通道位深16bit的Tiff图片

1.背景

System.Drawing.Common 是一个用于图像处理和图形操作的库,它是 System.Drawing 命名空间的一部分。由于 .NET Core 和 .NET 5+ 的跨平台特性,许多以前内置于 .NET Framework 中的库被移到了独立的NuGet包中,以便更好地管理和跨平台使用。

System.Drawing.Common 提供了处理图像的基础设施,包括创建、修改和保存图像的功能。
在使用与图像相关的类(如 Bitmap 和 Graphics)时,需要引用这个包。

通过 NuGet 包管理器安装:System.Drawing.Common
如下图所示:
在这里插入图片描述
安装完成后,将在项目下的packages目录下生成System.Drawing.Common.8.0.5文件夹,如下图:
在这里插入图片描述

使用如下代码创建16位深的Tiff图:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;

namespace Raw2Tiff
{
    
      
    class jn10010537
    {
    
      
        static void Main()
        {
    
      
            // 示例 ushort 数组
            int width = 100;
            int height = 100;
            ushort[] ushortArray = new ushort[width * height];
            Random random = new Random();
            for (int i = 0; i < ushortArray.Length; i++)
            {
    
      
                ushortArray[i] = (ushort)random.Next(0, 65536);
            }

            // 将 ushort 数组转换为 byte 数组
            byte[] byteArray = new byte[ushortArray.Length * 2];
            Buffer.BlockCopy(ushortArray, 0, byteArray, 0, byteArray.Length);

            // 创建 Bitmap 对象
            Bitmap bitmap = new Bitmap(width, height, PixelFormat.Format16bppGrayScale);

            // 获取 BitmapData 对象
            // 使用LockBits方法可以更快地设置像素,该方法允许您将托管数据快速封送到非托管位图字节。
            BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat);

            // 将 byte 数组拷贝到 BitmapData 对象
            Marshal.Copy(byteArray, 0, bitmapData.Scan0, byteArray.Length);

            // 解锁 BitmapData 对象
            bitmap.UnlockBits(bitmapData);

            // 保存为 TIFF 图片
            bitmap.Save("output.tiff", ImageFormat.Tiff);

            Console.WriteLine("图片已保存为 output.tiff");
        }

    }
}

运行如下:
在这里插入图片描述

原因:请注意,GDI+似乎不支持16bpp灰度,这意味着。net无法将16bpp灰度位图保存到文件或流中。

2.接口

在Windows上使用System.Drawing.Common处理16位灰度图像保存为TIFF时,目前(2024-05-27)会遇到问题!
因为默认情况下System.Drawing库不直接支持16位灰度图像的处理。

本博客采用的替代解决方案是使用BitMiracle.LibTiff.NET库,这是一个强大的库,专门用于处理TIFF图像格式。

通过 NuGet 包管理器安装: BitMiracle.LibTiff.NET 包,
如下图:
在这里插入图片描述
安装日志:

正在尝试收集与目标为“.NETFramework,Version=v4.7.2”的项目“Raw2Tiff”有关的包“BitMiracle.LibTiff.NET.2.4.649”的依赖项信息
收集依赖项信息花费时间 665 ms
正在尝试解析程序包“BitMiracle.LibTiff.NET.2.4.649”的依赖项,DependencyBehavior 为“Lowest”
解析依赖项信息花费时间 0 ms
正在解析操作以安装程序包“BitMiracle.LibTiff.NET.2.4.649”
已解析操作以安装程序包“BitMiracle.LibTiff.NET.2.4.649”
  GET https://api.nuget.org/v3-flatcontainer/bitmiracle.libtiff.net/2.4.649/bitmiracle.libtiff.net.2.4.649.nupkg
  OK https://api.nuget.org/v3-flatcontainer/bitmiracle.libtiff.net/2.4.649/bitmiracle.libtiff.net.2.4.649.nupkg 172 毫秒
已通过内容哈希 XCEdfCphKo0UAvSg1h/OzOFWtjkIGnPMAziYkNqV7NVrqb/tZJTBxJhxIEX7gpvQwg8GIRYt133SUncfkKfjLA== 从 https://api.nuget.org/v3/index.json 安装 BitMiracle.LibTiff.NET 2.4.649 。
正在将包“BitMiracle.LibTiff.NET.2.4.649”添加到文件夹“C:\Users\Administrator\Desktop\IRay_CSahep\Raw2Tiff\packages”
已将包“BitMiracle.LibTiff.NET.2.4.649”添加到文件夹“C:\Users\Administrator\Desktop\IRay_CSahep\Raw2Tiff\packages”
已将包“BitMiracle.LibTiff.NET.2.4.649”添加到“packages.config”
已将“BitMiracle.LibTiff.NET 2.4.649”成功安装到 Raw2Tiff
执行 nuget 操作花费时间 2.52 sec
已用时间: 00:00:03.3026348
========== 已完成 ==========

安装完成将在项目文件目录下生成"BitMiracle.LibTiff.NET.2.4.649"文件夹,如下图:
在这里插入图片描述

以下是使用BitMiracle.LibTiff.NET保存16位灰度TIFF图像的示例代码:

using System;
using BitMiracle.LibTiff.Classic;

namespace Raw2Tiff
{
    
      
    class jn10010537
    {
    
      
        static void Main()
        {
    
      
            // 示例 ushort 数组
            int width = 300;
            int height = 500;
            ushort[] ushortArray = new ushort[width * height];
            
            Random random = new Random();
            for (int i = 0; i < ushortArray.Length; i++)
            {
    
      
                ushortArray[i] = (ushort)random.Next(0, 65536);
            }

            // 保存为 TIFF 图片
            Save16BitGrayscaleTiff("jn10010537.tiff", ushortArray, width, height);

            Console.WriteLine("图片已保存成功!");
            Console.ReadKey();
        }

        private static void Save16BitGrayscaleTiff(string fileName, ushort[] imageData, int width, int height)
        {
    
      
            using (Tiff output = Tiff.Open(fileName, "w"))
            {
    
      
                output.SetField(TiffTag.IMAGEWIDTH, width);
                output.SetField(TiffTag.IMAGELENGTH, height);
                output.SetField(TiffTag.SAMPLESPERPIXEL, 1);
                output.SetField(TiffTag.BITSPERSAMPLE, 16);
                output.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);
                output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
                output.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
                output.SetField(TiffTag.ROWSPERSTRIP, height);

                int stride = width * sizeof(ushort);
                byte[] strip = new byte[stride];

                for (int row = 0; row < height; row++)
                {
    
      
                    Buffer.BlockCopy(imageData, row * stride, strip, 0, stride);
                    output.WriteScanline(strip, row);
                }
            }
        }
    }
}

程序运行后将生成tiff文件,打开Tiff图片的详细信息如下图所示:
在这里插入图片描述