从TIFF文件中删除空白(或接近空白)页面的方法

时间:2011-04-19 13:04:52

标签: language-agnostic tiff

我有4千万个TIFF文档,都是1位单页双工。在大约40%的情况下,这些TIFF的背面图像是“空白”,我想在加载到CMS之前删除它们以减少空间需求。

有没有一种简单的方法可以查看每个页面的数据内容,如果它低于预设的阈值就删除它,比如2%'黑色'?

我在这方面与技术无关,但C#解决方案可能是最容易支持的。问题是,我没有图像处理经验所以不知道从哪里开始。

编辑添加:图片是旧扫描,所以“脏”,所以预计这不是一门精确的科学。需要设置阈值以避免误报的可能性。

3 个答案:

答案 0 :(得分:3)

你可能应该:

  • 打开每张图片
  • 遍历其页面(使用Bitmap.GetFrameCount / Bitmap.SelectActiveFrame方法)
  • 访问每个页面的位(使用Bitmap.LockBits方法)
  • 分析每个页面的内容(简单循环)
  • 如果内容值得,则将数据复制到另一个图像(Bitmap.LockBits和循环)

此任务并不是特别复杂,但需要编写一些代码。此站点包含一些您可以使用方法名称作为关键字搜索的样本。

P.S。我假设所有图像都可以成功加载到System.Drawing.Bitmap

答案 1 :(得分:1)

您可以使用DotImage执行类似的操作(免责声明,我为Atalasoft工作并编写了您将使用的大多数基础类)。执行此操作的代码如下所示:

public void RemoveBlankPages(Stream source stm)
{
    List<int> blanks = new List<int>();
    if (GetBlankPages(stm, blanks)) {
        // all pages blank - delete file?  Skip?  Your choice.
    }
    else {
        // memory stream is convenient - maybe a temp file instead?
        using (MemoryStream ostm = new MemoryStream()) {
            // pulls out all the blanks and writes to the temp stream
            stm.Seek(0, SeekOrigin.Begin);
            RemoveBlanks(blanks, stm, ostm);
            CopyStream(ostm, stm); // copies first stm to second, truncating at end
        }
    }
}

private bool GetBlankPages(Stream stm, List<int> blanks)
{
    TiffDecoder decoder = new TiffDecoder();
    ImageInfo info = decoder.GetImageInfo(stm);
    for (int i=0; i < info.FrameCount; i++) {
        try {
            stm.Seek(0, SeekOrigin.Begin);
            using (AtalaImage image = decoder.Read(stm, i, null)) {
                if (IsBlankPage(image)) blanks.Add(i);
            }
        }
        catch {
            // bad file - skip? could also try to remove the bad page:
            blanks.Add(i);
        }
    }
    return blanks.Count == info.FrameCount;
}

private bool IsBlankPage(AtalaImage image)
{
    // you might want to configure the command to do noise removal and black border
    // removal (or not) first.
    BlankPageDetectionCommand command = new BlankPageDetectionCommand();
    BlankPageDetectionResults results = command.Apply(image) as BlankPageDetectionResults;
    return results.IsImageBlank;
}

private void RemoveBlanks(List<int> blanks, Stream source, Stream dest)
{
    // blanks needs to be sorted low to high, which it will be if generated from
    // above
    TiffDocument doc = new TiffDocument(source);
    int totalRemoved = 0;
    foreach (int page in blanks) {
        doc.Pages.RemoveAt(page - totalRemoved);
        totalRemoved++;
    }
    doc.Save(dest);
}

你应该注意到空白页检测并不像“所有像素都是白色(-ish)?”那么简单。因为扫描引入了各种有趣的文物。要获取BlankPageDetectionCommand,您需要Document Imaging包。

答案 2 :(得分:0)

您是否有兴趣收缩文件或只是想避免人们浪费时间查看空白页?您只需将第二个IFD修补为0x00000000即可对文件进行快速而脏的编辑,以消除已知的空白页。这就是我的意思 - 如果你只是浏览页面,TIFF文件的布局很简单:

TIFF标头(4个字节) 第一个IFD偏移量(4个字节 - 通常指向0x00000008)

IFD:

标签数量(2字节)

{个别TIFF标签}(每个12字节)

下一个IFD偏移量(4个字节)

只需将“下一个IFD偏移量”修补为值0x00000000,即可“删除”超出当前页面的页面。