iText:仅当位置为空时才在PDF上显示图像 [英] iText : image on PDF only if the position is blank
问题描述
需要在特定位置的每个页面上绘制图像。限制是我们应该只在特定位置为空(不包含任何文本/图像/表等)时粘贴图像。有没有办法做到这一点?
Have an image that need to be painted on each page at a specific location. The constraint is we should paste the image only if the specific location is blank (not containing any text/images/tables, etc). Is there a way to do this?
推荐答案
是的,有。
-
使用
IEventListener
来解析pdf中的特定页面。
您将收到有关解析器在页面上处理的每个事件的通知。有3种。PathRenderInfo
,TextRenderInfo
,ImageRenderInfo
。
Use
IEventListener
to parse a specific page in the pdf. You'll get notified about every event that the parser handles on the page. There are 3 kinds.PathRenderInfo
,TextRenderInfo
,ImageRenderInfo
.
可以查询所有这些事件的内容坐标,以及在渲染之前应用的变换矩阵。
All of these events can be queried for the coordinates of their content, as well as the transformation matrix that is applied before rendering them.
这允许您计算在某个页面上呈现的内容占用的 Rectangle
。
This allows you to calculate the Rectangle
that is occupied by the content that was rendered on a certain page.
现在您已拥有此矩形集合,您可以轻松检查给定矩形是否与这些矩形中的任何一个相交。 java.awt.Rectangle
有一个名为的方法相交
Now that you have this collection of Rectangles, you can easily check whether a given rectangle intersects with any of these rectangles. java.awt.Rectangle
has a method for this called intersects
然后使用一些示例代码将图像定位在绝对位置。
Then use some of the example code to position an image at an absolute position.
这是星期五,对每个人来说都是美好的一天。所以这是代码;
It's Friday, which is a wonderful day for everyone. So here's the code;
class FreeSpaceFinder implements IEventListener
{
private Collection<Rectangle> areas = new HashSet<>();
public FreeSpaceFinder(PdfPage page)
{
areas.clear();
PdfCanvasProcessor processor = new PdfCanvasProcessor(this);
processor.processPageContent(page);
}
public Collection<Rectangle> getOccupiedAreas()
{
return areas;
}
@Override
public void eventOccurred(IEventData iEventData, EventType eventType) {
if(eventType == EventType.RENDER_TEXT)
processText((TextRenderInfo) iEventData);
else if(eventType == EventType.RENDER_PATH)
processPath((PathRenderInfo) iEventData);
else if(eventType == EventType.RENDER_IMAGE)
processImage((ImageRenderInfo) iEventData);
}
private void processText(TextRenderInfo info)
{
for(TextRenderInfo characterRenderInfo : info.getCharacterRenderInfos())
{
com.itextpdf.kernel.geom.Rectangle charBoundingBox = new CharacterRenderInfo(characterRenderInfo).getBoundingBox();
areas.add(new Rectangle( (int) charBoundingBox.getX(),
(int) charBoundingBox.getY(),
(int) charBoundingBox.getWidth(),
(int) charBoundingBox.getHeight()));
}
}
private void processPath(PathRenderInfo info)
{
for(Subpath subpath : info.getPath().getSubpaths())
{
for(IShape segment : subpath.getSegments())
{
if(segment instanceof Line)
{
processLine(info, (Line) segment);
}
}
}
}
private float[] applyMtx(Matrix m, float[] point)
{
Matrix m2 = m.multiply(new Matrix(point[0], point[1]));
return new float[]{m2.get(Matrix.I31), m2.get(Matrix.I32)};
}
private void processLine(PathRenderInfo info, Line shape)
{
float[] p0 = applyMtx(info.getCtm(), new float[]{(float) shape.getBasePoints().get(0).getX(), (float) shape.getBasePoints().get(0).getY()});
int x0 = (int) p0[0];
int y0 = (int) p0[1];
float[] p1 = applyMtx(info.getCtm(), new float[]{(float) shape.getBasePoints().get(1).getX(), (float) shape.getBasePoints().get(1).getY()});
int x1 = (int) p1[0];
int y1 = (int) p1[1];
int w = java.lang.Math.abs(x0 - x1);
int h = java.lang.Math.abs(y0 - y1);
areas.add(new Rectangle(java.lang.Math.min(x0,x1), java.lang.Math.min(y0,y1), java.lang.Math.max(w, 1), java.lang.Math.max(h, 1)));
}
private void processImage(ImageRenderInfo info)
{
// #TODO
}
@Override
public Set<EventType> getSupportedEvents() {
return null;
}
}
这篇关于iText:仅当位置为空时才在PDF上显示图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!