首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >BitMiracle LibTIFF.NET无法解压缩先前由自己创建的TIFF

BitMiracle LibTIFF.NET无法解压缩先前由自己创建的TIFF
EN

Stack Overflow用户
提问于 2015-08-10 12:42:33
回答 1查看 867关注 0票数 1

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

这个部分工作得很好--我可以在TIFF查看器中打开结果TIFF并查看内容。

对于压缩,我使用以下编解码器:

代码语言:javascript
复制
    outImage.SetField(TiffTag.COMPRESSION, Compression.CCITT_T6);

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

代码语言:javascript
复制
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的问题。

有谁能帮忙找出根本原因吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-08-10 20:11:02

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

为了从每像素24位的TIFF转换为每像素1位,我将算法从C移植到C#,这两个工具附带了原始的libtiff:tiff2bw蒂夫抖动

tiffdither有一个错误,它不包括输出映像中的最后一个图像行,也就是说,如果您向它提供一个高度为2200行的图像,您将得到高度为2199行的图像作为输出。

我在移植的一开始就注意到了这个bug,并试图修复它,但是最终它没有完全修复,而且移植的算法实际上并没有通过WriteScanline()方法将最后一行写入输出TIFF。这就是为什么LibTIFF.NET不能根据我使用的读取方法读取图像的最后一条\行的原因。

令我惊讶的是,LibTIFF.NET允许在编写过程中没有任何错误地编写这样的实际损坏的TIFF。例如,当通过WriteDirectory()设置的图像高度与写入它的实际行数不同时,true方法将返回true。但是,稍后它无法读取这样的图像,并且在读取时会抛出错误。

不过,这种行为可能是从最初的libtiff继承下来的。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31919888

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档