BitMiracle LibTIFF.NET不能解压缩以前自己创建的TIFF

本文关键字:自己 创建 TIFF LibTIFF NET 不能 解压缩 BitMiracle | 更新日期: 2023-09-27 18:07:13

我实现了一个类,它读取Microsoft.Reporting.WinForms.ReportViewer生成的每像素24位的TIFF,将其转换为每像素1位的TIFF,并将结果存储到一个文件中。

这部分工作得很好-我能够在TIFF查看器中打开生成的TIFF并查看内容。

对于压缩,我使用以下编解码器:
    outImage.SetField(TiffTag.COMPRESSION, Compression.CCITT_T6);

现在我正试图读取相同的每像素1位TIFF并解压缩它。我编写了以下方法:

public static void DecompressTiff(byte[] inputTiffBytes)
{
    using (var tiffStream = new MemoryStream(inputTiffBytes))
    using (var inImage = Tiff.ClientOpen("in-memory", "r", tiffStream, new TiffStream()))
    {
        if (inImage == null)
            return null;
        int totalPages = inImage.NumberOfDirectories();
        for (var i = 0; i < totalPages; )
        {
            if (!inImage.SetDirectory((short) i))
                return null;
            var decompressedTiff = DecompressTiff(inImage);
...
}
private static byte[] DecompressTiff(Tiff image)
{
    // Read in the possibly multiple strips 
    var stripSize = image.StripSize();
    var stripMax = image.NumberOfStrips();
    var imageOffset = 0;
    int row = 0;
    var bufferSize = image.NumberOfStrips() * stripSize;
    var buffer = new byte[bufferSize];
    int height = 0;
    var result = image.GetField(TiffTag.IMAGELENGTH);
    if (result != null)
        height = result[0].ToInt();
    int rowsperstrip = 0;
    result = image.GetField(TiffTag.ROWSPERSTRIP);
    if (result != null)
        rowsperstrip = result[0].ToInt();
    if (rowsperstrip > height && rowsperstrip != -1)
        rowsperstrip = height;
    for (var stripCount = 0; stripCount < stripMax; stripCount++)
    {
        int countToRead = (row + rowsperstrip > height) ? image.VStripSize(height - row) : stripSize;
        var readBytesCount = image.ReadEncodedStrip(stripCount, buffer, imageOffset, countToRead); // Returns -1 for the last strip of the very first page
        if (readBytesCount == -1)
            return null;
        imageOffset += readBytesCount;
        row += rowsperstrip;
    }
    return buffer;
}

问题是,当对第一页的最后一个条带调用ReadEncodedStrip()时,它返回-1,表明存在错误。即使在调试LibTIFF之后,我也无法找出问题所在。. NET解码器代码。这是EOL TIFF标记在不期望的地方发现的东西。

由于某种原因,LibTIFF。NET不能读取自己生成的TIFF,或者很可能我错过了什么。这就是TIFF的问题。

谁能帮忙找出根本原因?

BitMiracle LibTIFF.NET不能解压缩以前自己创建的TIFF

经过半天多的调查,我终于找到了这个奇怪问题的原因。

为了将24位/像素的TIFF转换为1位/像素,我将原始libtiff附带的两个工具中的算法从C移植到c#: tiff2bw和tiffdither。

tiffdither有一个错误,它不包括最后一个图像行在输出图像,即,如果你给它2200行高度的图像,你得到2199行高度的图像作为输出。

我在移植的一开始就注意到这个bug,并试图修复,但是,最终证明,不完全,移植的算法实际上没有通过WriteScanline()方法将最后一行写入输出TIFF。这就是LibTIFF的原因。. NET无法读取图像的最后一行,这取决于我使用的读取方法。

让我惊讶的是LibTIFF。NET允许在写入过程中写入这种实际损坏的TIFF而不会出现任何错误。例如,当通过TiffTag.IMAGELENGTH设置的图像高度与实际写入的行数不同时,WriteDirectory()方法在这种情况下返回true。但是,后来它无法读取这样的图像,并且在读取时抛出错误。