【问题标题】:Methods for deleting blank (or nearly blank) pages from TIFF files从 TIFF 文件中删除空白(或几乎空白)页面的方法
【发布时间】:2015-06-04 16:22:08
【问题描述】:

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

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

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

编辑添加:这些图像是旧扫描件,因此“脏”,所以这不是一门精确的科学。需要设置阈值以避免误报。

【问题讨论】:

    标签: language-agnostic tiff


    【解决方案1】:

    你可能应该:

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

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

    附:我假设所有图像都可以成功加载到System.Drawing.Bitmap

    【讨论】:

    【解决方案2】:

    您可以使用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 包。

    【讨论】:

      【解决方案3】:

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

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

      IFD:

      标签数量(2字节)

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

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

      只需将“下一个 IFD 偏移量”修补为 0x00000000 值即可“取消链接”当前页面之外的页面。

      【讨论】:

        猜你喜欢
        • 2021-03-14
        • 2017-12-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-29
        • 2017-06-21
        • 2022-09-29
        相关资源
        最近更新 更多