我有一个问题是:绘制一个矩形,以涵盖PDF中的所有图像。我已经知道图像可以写成图像,但它也可以写成图形矢量。
我想得到正常图像的位置(X,Y,宽度,高度)(例如保存为位图),并在它们上面绘制矩形,以不覆盖页面上的其他元素,如此图像下的文本(我不想覆盖整个页面,如果图像只覆盖它的30% )。到目前为止,我已经编写了两个获取图像的函数:
public List<Image> GetImagesFromPdf(string path)
{
List<Image> imageList = new List<Image>();
PdfReader reader = new PdfReader(path);
for (int i=1;i<reader.NumberOfPages;i++)
{
PdfDictionary pdfDict = reader.GetPageN(i);
imageList.AddRange(GetImagesFromDocument(pdfDict, reader));
}
return imageList;
}
private List<Image> GetImagesFromDocument(PdfDictionary dict, PdfReader doc)
{
List<Image> imageList = new List<Image>();
PdfDictionary resources = (PdfReader.GetPdfObject(dict.Get(PdfName.RESOURCES))) as PdfDictionary;
PdfDictionary objects = (PdfReader.GetPdfObject(resources.Get(PdfName.XOBJECT))) as PdfDictionary;
if (objects != null)
{
foreach (PdfName objKey in objects.Keys)
{
PdfObject obj = objects.Get(objKey);
if (obj.IsIndirect())
{
PdfDictionary tg = (PdfDictionary)(PdfReader.GetPdfObject(obj));
PdfName objectType = (PdfName)(PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE)));
if (
PdfName.IMAGE.Equals(objectType)
||PdfName.IMAGEB.Equals(objectType)
|| PdfName.IMAGEC.Equals(objectType)
|| PdfName.IMAGEI.Equals(objectType)
)
{
int xrefIdx = ((PRIndirectReference)obj).Number;
PdfObject pdfObj = doc.GetPdfObject(xrefIdx);
PdfStream str = (PdfStream)(pdfObj);
iTextSharp.text.pdf.parser.PdfImageObject pdfImage =
new iTextSharp.text.pdf.parser.PdfImageObject((PRStream)str);
System.Drawing.Image img = pdfImage.GetDrawingImage();
imageList.Add(img);
}
else if (PdfName.FORM.Equals(objectType) || PdfName.GROUP.Equals(objectType))
{
imageList.AddRange(GetImagesFromDocument(tg, doc));
}
}
}
}
return imageList;
}
我调用函数GetImagesFromPdf
,然后对每个页面运行function:GetImagesFromDocument
。这导致了正确数量的图像在pdf中,但我真的没有线索,如何获得位置(X,Y,宽度,高度).还有什么我可以使用的吗?或者我应该使用另一种机制呢?
任何帮助都将不胜感激。PS。我注意到一件事。我还尝试实现了IExtRenderListener
接口,并且我注意到当pdf中有图像时,就会调用函数RenderImage
。有一个函数我可以在对象renderInfo
上调用,结果是result,我得到了那个值(这个函数叫做GetImageCTM()):
当我试图覆盖以图形向量形式编写的图像时,我失败了。没有图像被覆盖,但我得到了大约15000个非常小的矩形,不幸的是看不见。我使用了以下代码:
public void ModifyPath(PathConstructionRenderInfo renderInfo)
{
if (renderInfo.Operation == PathConstructionRenderInfo.RECT)
{
float x = renderInfo.SegmentData[0];
float y = renderInfo.SegmentData[1];
float w = renderInfo.SegmentData[2];
float h = renderInfo.SegmentData[3];
Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
Vector b = new Vector(x + w, y, 1).Cross(renderInfo.Ctm);
Vector c = new Vector(x + w, y + h, 1).Cross(renderInfo.Ctm);
Vector d = new Vector(x, y + h, 1).Cross(renderInfo.Ctm);
Rectangle rect = new Rectangle(x,y,x+w, y+h); //is that correct ?
}
else
{
for (int i = 0; i < renderInfo.SegmentData.Count - 1; i += 2)
{
float x = renderInfo.SegmentData[i];
float y = renderInfo.SegmentData[i + 1];
Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
// Rectangle rect = new Rectangle(x, y, x + ..., y + ...); What to do here ?
}
}
modifyPathCounter++;
}
好的,它已经解决了,解决方案在这里:
if (renderInfo.Operation == PathConstructionRenderInfo.RECT)
{
float x = renderInfo.SegmentData[0];
float y = renderInfo.SegmentData[1];
float w = renderInfo.SegmentData[2];
float h = renderInfo.SegmentData[3];
Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
Vector b = new Vector(x + w, y, 1).Cross(renderInfo.Ctm);
Vector c = new Vector(x + w, y + h, 1).Cross(renderInfo.Ctm);
Vector d = new Vector(x, y + h, 1).Cross(renderInfo.Ctm);
Rectangle rect = new Rectangle(a[0],a[1],c[0], c[1]);
//SquaresToDraw image = new SquaresToDraw(0, rect.Left, rect.Bottom, rect.Right, rect.Top);
// squaresToDraw.Add(image);
}
else
{
if (renderInfo.SegmentData!=null)
{
for (int i = 0; i < renderInfo.SegmentData.Count - 1; i += 2)
{
float x = renderInfo.SegmentData[i];
float y = renderInfo.SegmentData[i + 1];
Vector a = new Vector(x, y, 1).Cross(renderInfo.Ctm);
Rectangle rect = new Rectangle(x, y, a[0], a[1]);
SquaresToDraw image = new SquaresToDraw(0, rect.Left, rect.Bottom, rect.Right, rect.Top);
squaresToDraw.Add(image);
// Rectangle rect = new Rectangle(x, y, x + ..., y + ...); What to do here ?
}
}
}
发布于 2018-12-15 17:54:10
您的两个方法为您提供了与页面相关的资源(直接或间接),但仅此而已,它们不能告诉您页面上使用了此类资源的位置(或根本不能)。所以这不会产生任何结果。
但是你的IExtRenderListener
方法确实是你要走的路。你的观察是正确的,ImageCtm
是表示应用于原始图像的仿射变换的矩阵,而不是原点的1x1正方形。
只需将该转换应用于1x1单元正方形角点,即可获得页面上图像的角点。
https://stackoverflow.com/questions/53783701
复制相似问题