替换PDF文件中的重复图像
我试图用PDF文件中的可用图像替换重复图像,但结果已损坏。替换PDF文件中的重复图像,pdf,itext,Pdf,Itext,我试图用PDF文件中的可用图像替换重复图像,但结果已损坏。 PdfReader.KillIndirect将重复的图像置空,但writer.adddirectimagessimple不会将其替换为以前可用图像的引用。这里有什么问题 代码如下: using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Security.Cryptography; using System.Tex
PdfReader.KillIndirect
将重复的图像置空,但writer.adddirectimagessimple
不会将其替换为以前可用图像的引用。这里有什么问题
代码如下:
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using iTextSharp.text;
using iTextSharp.text.pdf;
namespace ReplaceDuplicateImages
{
class Program
{
/// <summary>
/// Adding one image, 2 times.
/// </summary>
private static void createSampleFile()
{
using (var pdfDoc = new Document(PageSize.A4))
{
var pdfWriter = PdfWriter.GetInstance(pdfDoc, new FileStream("Test.pdf", FileMode.Create));
pdfDoc.Open();
var table = new PdfPTable(new float[] { 1, 2 });
table.AddCell(Image.GetInstance("01.png"));
table.AddCell(Image.GetInstance("01.png"));
pdfDoc.Add(table);
}
}
private static void RemoveDuplicateImagesFromPdfFile(string inFile, string outFile)
{
var pdfReader = new PdfReader(inFile);
var pdfStamper = new PdfStamper(pdfReader, new FileStream(outFile, FileMode.Create));
var writer = pdfStamper.Writer;
var md5Service = new MD5CryptoServiceProvider();
var enc = new UTF8Encoding();
var imagesDictionary = new Dictionary<string, PRIndirectReference>();
int pageNum = pdfReader.NumberOfPages;
for (int i = 1; i <= pageNum; i++)
{
var page = pdfReader.GetPageN(i);
var resources = PdfReader.GetPdfObject(page.Get(PdfName.RESOURCES)) as PdfDictionary;
if (resources == null) continue;
var xObject = PdfReader.GetPdfObject(resources.Get(PdfName.XOBJECT)) as PdfDictionary;
if (xObject == null) continue;
foreach (var name in xObject.Keys)
{
var pdfObject = xObject.Get(name);
if (!pdfObject.IsIndirect()) continue;
var imgObject = PdfReader.GetPdfObject(pdfObject) as PdfDictionary;
if (imgObject == null) continue;
var subType = PdfReader.GetPdfObject(imgObject.Get(PdfName.SUBTYPE)) as PdfName;
if (subType == null) continue;
if (!PdfName.IMAGE.Equals(subType)) continue;
var imageBytes = PdfReader.GetStreamBytesRaw((PRStream)imgObject);
var md5 = enc.GetString(md5Service.ComputeHash(imageBytes));
if (!imagesDictionary.ContainsKey(md5)) // is it duplicate?
{
imagesDictionary.Add(md5, (PRIndirectReference)pdfObject);
}
else
{
PdfReader.KillIndirect(pdfObject); // nulls the duplicate image
// trying to replace it with the reference of the available image
var imageRef = imagesDictionary[md5];
var image = Image.GetInstance(imageRef);
Image maskImage = image.ImageMask; // it's always null here.
if (maskImage != null)
writer.AddDirectImageSimple(maskImage);
writer.AddDirectImageSimple(image, (PRIndirectReference)pdfObject);
}
}
}
pdfReader.RemoveUnusedObjects();
pdfReader.Close();
pdfStamper.Close();
}
static void Main(string[] args)
{
createSampleFile();
RemoveDuplicateImagesFromPdfFile("test.pdf", "Optimized.pdf");
Process.Start("Optimized.pdf");
}
}
}
使用System.Collections.Generic;
使用系统诊断;
使用System.IO;
使用System.Security.Cryptography;
使用系统文本;
使用iTextSharp.text;
使用iTextSharp.text.pdf;
命名空间替换重复映像
{
班级计划
{
///
///添加一个图像,2次。
///
私有静态void createSampleFile()
{
使用(var pdfDoc=新文档(PageSize.A4))
{
var pdfWriter=pdfWriter.GetInstance(pdfDoc,newfilestream(“Test.pdf”,FileMode.Create));
pdfDoc.Open();
var table=新PdfPTable(新浮点[]{1,2});
table.AddCell(Image.GetInstance(“01.png”);
table.AddCell(Image.GetInstance(“01.png”);
pdfDoc.Add(表);
}
}
从PDF文件移除的私有静态无效复制图像(字符串填充、字符串输出文件)
{
var pdfReader=新pdfReader(填充);
var pdfStamper=newpdfstamper(pdfReader,newfilestream(outFile,FileMode.Create));
var writer=pdfStamper.writer;
var md5Service=new MD5CryptoServiceProvider();
var enc=新的UTF8Encoding();
var imagesDictionary=新字典();
int pageNum=pdfReader.NumberOfPages;
对于(int i=1;i如果您想删除冗余信息(重复图像、重复XObject、重复字体等),请不要尝试使用iTextSharp的低级功能来重新发明轮子。改用PdfSmartCopy,它将为您完成所有困难的工作
代码的主要问题是删除了重复的图像,但从未更新对这些图像的引用。这样做会破坏PDF
假设您的PDF包含两个相同(字节)且冗余存储的图像(相同的字节在PDF中有两次)。假设对象具有以下引用:10 0R
(第一个图像)和20 0R
(第二个图像)
在每个页面的图像xObject上循环,会遇到10 0r
。保留该图像,并存储其MD5哈希:
imagesDictionary.Add(md5, (PRIndirectReference)pdfObject);
然后您遇到20 0 R
。您发现此图像与10 0 R
相同,因为两个图像的md5散列都对应。您删除该图像20 0 R
:
PdfReader.KillIndirect(pdfObject);
writer.AddDirectImageSimple(image, (PRIndirectReference)pdfObject);
然后你做了一件非常奇怪的事情。你没有把对复制图像(20 0r
)的引用改为对图像第一个实例(10 0r
)的引用,而是得到第一个实例(image
),然后用原始引用(10 0r
)重新添加它:
换句话说:您尝试将第二个对象编号为10的对象添加到PDF中,这是非法的(每个对象编号都是唯一的)。iText将忽略该行;它将只返回用于图像的原始PdfName
最终,您将得到一个PDF,其中包含一个正确引用10 0 R
的图像和一个引用20 0 R
的图像,该图像指向一个不再存在的对象,因为您删除了对象编号为20的图像
这就解释了您遇到的问题,您描述为:
“结果已损坏”。第一个图像正常,但第二个图像已完全消除,Adobe reader显示有关此损坏文件的错误消息
如果您想删除冗余信息(重复的图像、重复的XObject、重复的字体等),请不要尝试使用iTextSharp的低级功能来重新设计轮子。请改用PdfSmartCopy,它将为您完成所有困难的工作
代码的主要问题是删除了重复的图像,但从未更新对这些图像的引用。这样做会破坏PDF
假设您的PDF包含两个相同(字节)且冗余存储的图像(相同的字节在PDF中有两次)。假设对象具有以下引用:10 0R
(第一个图像)和20 0R
(第二个图像)
在每个页面的图像xObject上循环,会遇到10 0r
。保留该图像,并存储其MD5哈希:
imagesDictionary.Add(md5, (PRIndirectReference)pdfObject);
然后您遇到20 0 R
。您发现此图像与10 0 R
相同,因为两个图像的md5散列都对应。您删除该图像20 0 R
:
PdfReader.KillIndirect(pdfObject);
writer.AddDirectImageSimple(image, (PRIndirectReference)pdfObject);
然后你做了一件非常奇怪的事情。你没有把对复制图像(20 0r
)的引用改为对图像第一个实例(10 0r
)的引用,而是得到第一个实例(image
),然后用原始引用(10 0r
)重新添加它:
换句话说:您尝试将第二个对象编号为10的对象添加到PDF中,这是非法的(每个对象编号都是唯一的)。iText将忽略该行;它将只返回用于图像的原始PdfName
最终,您将得到一个PDF,其中包含一个正确引用10 0 R
的图像和一个引用20 0 R
的图像,该图像指向一个不再存在的对象,因为您删除了对象编号为20的图像
这就解释了您遇到的问题,您描述为:
“结果已损坏”。第一个图像正常,但第二个图像已完全消除,Adobe将重新生成