如何将 OCR 文本数据复制到新的 pdf Itext 7 C#
How to copy OCR text data to a new pdf Itext 7 C#
我有一份扫描件。在这份文件中,上面有文字和图像的透明层。有没有办法将文本原样(没有任何变化,因此它保持透明并在同一位置)复制到我创建的另一个 .pdf 文件(没有图像)?我在 google 中搜索它,但没有找到任何解决方案。我知道我可以将页面中的文本复制到字符串中,然后将其添加到我的新文档中并包含一个新段落。但它会破坏识别字母的透明度和位置。我真正想做的是更改 OCR 文本下方的图像。首先,我们的想法是从 .pdf 中删除所有图像并添加新图像。然后我明白这不是一个好主意,也不是很容易做到,因为有很多不同的图像类型。(但我是这样做的,看看解决方案)
添加示例:
我的示例文档是我进行了 OCR 扫描的文档。
我的真实代码示例在这里:
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 提供的代码部分,我能够构建解决方案。
- 我使用 Apitron 从每个页面的带水印的 pdf 生成图像(查找代码示例)。
- 我使用 mkl 提供的代码删除了我原始 pdf 文档中的所有图像。
- 我使用 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 按预期工作。
我有一份扫描件。在这份文件中,上面有文字和图像的透明层。有没有办法将文本原样(没有任何变化,因此它保持透明并在同一位置)复制到我创建的另一个 .pdf 文件(没有图像)?我在 google 中搜索它,但没有找到任何解决方案。我知道我可以将页面中的文本复制到字符串中,然后将其添加到我的新文档中并包含一个新段落。但它会破坏识别字母的透明度和位置。我真正想做的是更改 OCR 文本下方的图像。首先,我们的想法是从 .pdf 中删除所有图像并添加新图像。然后我明白这不是一个好主意,也不是很容易做到,因为有很多不同的图像类型。(但我是这样做的,看看解决方案)
添加示例:
我的示例文档是我进行了 OCR 扫描的文档。
我的真实代码示例在这里:
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 提供的代码部分,我能够构建解决方案。
- 我使用 Apitron 从每个页面的带水印的 pdf 生成图像(查找代码示例)。
- 我使用 mkl 提供的代码删除了我原始 pdf 文档中的所有图像。
- 我使用 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 按预期工作。