将32位TIFF转换为位图

时间:2018-02-11 14:15:45

标签: c# image winforms bitmap tiff

我有一个32位的.tif文件,首先在ImageJ中显示在下图中,其次是我的程序。你可以猜到,ImageJ显示图片的方式是正确的。

2 ways to display my tiff

我正在将文件转换为这样的位图:

private Bitmap TiffToBmp()
{
    Bitmap bmp;
    int width;
    int height;
    float[] scanline32Bit;
    float[] buffer;

    using (Tiff original = Tiff.Open(file, "r"))
    {
        width = original.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
        height = original.GetField(TiffTag.IMAGELENGTH)[0].ToInt();

        byte[] scanline = new byte[original.ScanlineSize()];
        scanline32Bit = new float[original.ScanlineSize() / 4];
        buffer = new float[width * height];

        for (int i = 0; i < height; i++) //loading the data into a buffer
        {
            original.ReadScanline(scanline, i);

            Buffer.BlockCopy(scanline, 0, scanline32Bit, 0, scanline.Length);

            for (int j = 0; j < width; j++)
            {
                buffer[i * width + j] = scanline32Bit[j];
            }
        }
    }

    bmp = new Bitmap(width, height);

    BitmapData data = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);

    byte[] bytes = new byte[data.Height * data.Stride];

    for (int y = 0; y < data.Height; y++) //creating Bitmap from buffer
    {
        for (int x = 0; x < data.Stride; x += 4)
        {
            bytes[y * data.Stride + x] = (byte)buffer[(y * data.Stride + x) / 4];
            bytes[y * data.Stride + x + 1] = (byte)buffer[(y * data.Stride + x) / 4];
            bytes[y * data.Stride + x + 2] = (byte)buffer[(y * data.Stride + x) / 4];
            bytes[y * data.Stride + x + 3] = 255;
        }
    }
    Marshal.Copy(bytes, 0, data.Scan0, bytes.Length);
    bmp.UnlockBits(data);
    return bmp;
}

使用RGBA位图可能看起来有点幼稚,但在程序的后续步骤中它是必需的。另外值得一提的是:XnView显示的文件类似于我的,只是负片(从白色到黑色而不是黑色到白色)。打开文件时,它注意到我将图像转换为每通道8位的RGB(我正在做同样的事情)并错误地声称.tif是16位而不是32位。

有人知道我做错了什么吗? 在我看来,错误纯粹来自某种结构的误用或它们之间的错误转换(从浮点到字节等)。
我使用the .NET version of original libtiff library

中的BitMiracle.LibTiff.Classic

编辑经过一些研究后,我发现original.ReadScanline(scanline, i)会返回看似奇怪的值,并通过Buffer.BlockCopy(...)将它们转换为图片中出现的条纹。例如,像素scanline的4个字节(从(x = 0, y = 0)读取)为0, 0, 200, 6,相应的8位像素值(从scanline32Bit读取)结果为110。像素(x = width, y = 0) 4个字节是0, 128, 111, 68,显示的8位值是958,对应190.所以现在我认为其中一个步骤有问题,但我实际上不知道是什么&# 39;继续。

1 个答案:

答案 0 :(得分:0)

假设您不介意使用现有代码,请执行以下操作:https://www.codeproject.com/Articles/8279/ImageConverter-Converts-images-to-a-specific-image

作者(不是我,BTW)提供了C#源代码和可执行文件。我使用可执行文件将TIF(使用paint.net创建)转换为BMP,因此我认为源对您有用。我能够使用VS 2017打开作者的解决方案(VS升级了解决方案和项目以在当前的VS环境中工作)。转换基于System.Drawing.Imaging.ImageFormat类