如何将 OCR 文本数据复制到新的 pdf Itext 7 C#

How to copy OCR text data to a new pdf Itext 7 C#

我有一份扫描件。在这份文件中,上面有文字和图像的透明层。有没有办法将文本原样(没有任何变化,因此它保持透明并在同一位置)复制到我创建的另一个 .pdf 文件(没有图像)?我在 google 中搜索它,但没有找到任何解决方案。我知道我可以将页面中的文本复制到字符串中,然后将其添加到我的新文档中并包含一个新段落。但它会破坏识别字母的透明度和位置。我真正想做的是更改 OCR 文本下方的图像。首先,我们的想法是从 .pdf 中删除所有图像并添加新图像。然后我明白这不是一个好主意,也不是很容易做到,因为有很多不同的图像类型。(但我是这样做的,看看解决方案)

添加示例:

我的示例文档是我进行了 OCR 扫描的文档。

Sample document

我的真实代码示例在这里:

                    String dest = "C:\ImagePaged.pdf";
                    PdfWriter writer = new PdfWriter(dest);
                   
                    // Creating a PdfDocument  
                    pdfDoc = new PdfDocument(writer);
                    

                    // Creating a Document   Document 
                    iText.Layout.Document document2 = new iText.Layout.Document(pdfDoc);
                    document2.SetMargins(0, 0, 0, 0);

                    //////////////////////

                    List<int> rotatedPages = new List<int>();
                    using (FileStream fs = new FileStream(@"C:\source.pdf", FileMode.Open))
                 
                    using (Document document = new Document(fs)) // this object represents a PDF document
                    
                    {

                
                        // process and save pages one by one
                        for (int i = 0; i < document.Pages.Count; i++)
                        {
                     

       
                            Page currentPage = document.Pages[i];
                            
                            // we use original page's width and height for image as well as default rendering settings
                            using (Bitmap bitmap = currentPage.Render((int)currentPage.Width*3, (int)currentPage.Height*3, new RenderingSettings()))
                          
                            {
                                if (bitmap.Width>bitmap.Height)
                                {
                                    rotatedPages.Add(i+1);

                                    bitmap.RotateFlip(RotateFlipType.Rotate90FlipNone);

                                }
                                

 bitmap.Save($"C:\ImagePage{i}.png", ImageFormat.Png);

iText.IO.Image.ImageData imageData = iText.IO.Image.ImageDataFactory.Create($"C:\ImagePage{i}.png");

 Image image = new Image(imageData);
                             
imageData = null;
             
                                
   document2.Add(image);
                                
     image = null;
     File.Delete($"C:\ImagePage{i}.png");


                                


                            }
                            GC.Collect();
                        }
                        document.Dispose();
                        document2.Close();
                        GC.Collect();

更新:解决方案

感谢 mkl 提供的代码部分,我能够构建解决方案。

  1. 我使用 Apitron 从每个页面的带水印的 pdf 生成图像(查找代码示例)。
  2. 我使用 mkl 提供的代码删除了我原始 pdf 文档中的所有图像。
  3. 我使用 Itext 将 Apitron 创建的图像添加到第 2 条中创建的 pdf 文件中。

我不会在此处 post 我的整个解决方案,但在执行此操作时要记住的重要事项是:

一个。像这样在目标文档中设置页边距:

document2.SetMargins(0, 0, 0, 0);

b。在添加之前旋转您的图像。

 int rotations=  pdfDoc.GetPage(i+1).GetRotation();
                            
                                if (rotations>0)
                                {
                                   

                                    if (rotations == 270)
                                    {
                                        bitmap.RotateFlip(RotateFlipType.Rotate270FlipXY);
                                    } else
                                          if (rotations == 90)
                                    {
                                        bitmap.RotateFlip(RotateFlipType.Rotate90FlipXY);
                                    }
                                    if (rotations == 180)
                                    {
                                        bitmap.RotateFlip(RotateFlipType.Rotate180FlipXY);
                                    }

c。创建添加页码的图像。

image = new Image(imageData).SetFixedPosition(i + 1, 0, 0).SetAutoScale(true);   (the first argument i, is the page number)

在评论中,我提议用 形式的 Xobject 替换图像 XObjects,没有任何说明。 你试图为此使用普通的 PdfDictionary,但那也是清楚的。而是尝试使用空 PdfFormXObject 下方的 PDF 对象作为 replacement:

的方法
void replaceImages(PdfResources pdfResources, PdfObject replacement)
{
    PdfDictionary xobjects = pdfResources.GetPdfObject().GetAsDictionary(PdfName.XObject);
    if (xobjects == null)
        return;
    ISet<PdfName> toReplace = new HashSet<PdfName>();
    foreach (KeyValuePair<PdfName, PdfObject> entry in xobjects.EntrySet())
    {
        PdfObject pdfObject = entry.Value;
        if (pdfObject is PdfIndirectReference reference)
            pdfObject = reference.GetRefersTo();
        if (pdfObject is PdfStream pdfStream && PdfName.Image.Equals(pdfStream.GetAsName(PdfName.Subtype)))
        {
            toReplace.Add(entry.Key);
        }
    }
    foreach (PdfName name in toReplace)
    {
        xobjects.Put(name, replacement);
    }
}

(ReplaceImageWithEmptyObject辅助方法)

注意,这会更改实际资源而不更新 PdfResources 实例的内部缓存。因此,它的状态可能会变得不一致,您不应将该实例用于其他操作。

您可以像这样将它应用于 PdfDocument pdfDocument

PdfFormXObject replacement = new PdfFormXObject(new Rectangle(1, 1));
for (int pageNr = 1; pageNr <= pdfDocument.GetNumberOfPages(); pageNr++)
{
    PdfPage pdfPage = pdfDocument.GetPage(pageNr);
    PdfResources pdfResources = pdfPage.GetResources();
    replaceImages(pdfResources, replacement.GetPdfObject());
}

(ReplaceImageWithEmptyObject 测试 testReplaceForVZ)

您的示例 PDF 按预期工作。