I have a problem which is: draw a rectangle to cover all images in PDF. I already know that image can be written as an image, but it can be also written as graphical vectors.
I want to get locations (X,Y,Width,Height) of normal images (saved for example as bitmap), and draw rectangle over them, to dont cover other elements on page such as text under this image (i dont want to cover entire page, if an image is covering only 30% of it). So far i have written two functions for getting images :
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;
}
Im calling function GetImagesFromPdf
, and then for each Page i run function: GetImagesFromDocument
. This results in right quantity of images in pdf, but i dont really have a clue, how to get locations (X,Y,Width,Height) ....
Is anything additional i can use ? Or i should use another mechanism for that ?
Any help will be appreciated.
PS. i have noticed something...
I also tried to implement IExtRenderListener
interface, and i have noticed that when there is an image in pdf, the function RenderImage
is being called.
There is one function which im able to call on object renderInfo
, and the result is instresting, i get that values (The function is called GetImageCTM()):
When i was trying to cover images written as graphical vectors, i have failed. None image was covered, but i got like 15 000 very small rectangles, unfortunatelly none was visible. I used this code:
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++;
}
OK its already solved, solution is here:
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 ?
}
}
}