如何从 pdf 中提取视口并根据视口修改注释的边界矩形?
How do I extract viewport from a pdf and modify an annotation's bounding rectangle according to the viewport?
我已经实现了使用 pdfbox 向任何 pdf 添加 link 注释的功能。它适用于大多数 pdf,但对于某些 pdf,它没有将标记放置在正确的坐标处。当我在某个 pdf 编辑器中打开该 pdf 时,它警告我该 pdf 包含一个未命名的视口,这可能会影响该 pdf 的测量。所以,我觉得视口很可能是导致问题的原因。有没有一种方法可以根据视口修改标记的坐标,以便将其放置在 pdf 中的正确位置。这是包含视口的 pdf 的 link。
根据Tilman的建议,我从viewport的measure字典中提取了C项。并尝试修改矩形的坐标,但它们没有添加到右侧 location.Below 是我尝试过的代码。此外,视口对注释没有影响,但当我尝试将某些内容绘制到 pdf 中时它会导致问题。
COSArray vps = (COSArray)page.getCOSObject().getDictionaryObject(COSName.getPDFName("VP"));
if (vps != null)
{
for (int v = 0; v < vps.size(); ++v)
{
COSDictionary vp = (COSDictionary)vps.getObject(v);
PDViewportDictionary viewportDict = new PDViewportDictionary(vp);
PDRectangle vpRect = viewportDict.getBBox();
PDMeasureDictionary measureDict = viewportDict.getMeasure();
PDRectlinearMeasureDictionary rectilinearDict = new PDRectlinearMeasureDictionary(measureDict.getCOSObject());
bool pointLieInVP = UtilityClass.RectangleContainsPoint(new PointF(leftX, bottomY), vpRect);
if (pointLieInVP)
{
COSArray xArray = (COSArray)measureDict.getCOSObject().getDictionaryObject(COSName.getPDFName("X"));
float xScale = 1;
if (xArray!=null)
{
xScale = ((COSFloat)(((COSDictionary)xArray.getObject(0)).getDictionaryObject(COSName.getPDFName("C")))).floatValue();
}
leftX /= xScale;
rightX /= xScale;
COSBase yObj = measureDict.getCOSObject().getDictionaryObject(COSName.getPDFName("Y"));
if (yObj != null)
{
COSArray yArray = (COSArray)yObj;
float yScale = ((COSFloat)(((COSDictionary)yArray.getObject(0)).getDictionaryObject(COSName.getPDFName("C")))).floatValue();
bottomY /= yScale;
topY /= yScale;
}
else
{
bottomY /= xScale;
topY /= xScale;
}
}
}
}
这是 pdf 的 link to pdf markups are added without adjusting for viewports. The 5 red colored markups are added at bottom right end of the page. But they should have been placed over the link annotations in the pdf which are placed at correct positions. And here is the link,其中标记是在使用上述代码修改坐标后放置的。标记根本没有出现。
此代码(不避免 ClassCastExceptions)将显示每个页面中的视口:
try (PDDocument doc = PDDocument.load(new File("S115-STRUCTURALHIGH ROOF FRAMING(WEST)ENLARGED PLANS.pdf")))
{
for (int p = 0; p < doc.getNumberOfPages(); ++p)
{
PDPage page = doc.getPage(p);
COSArray vps = (COSArray) page.getCOSObject().getDictionaryObject(COSName.getPDFName("VP"));
if (vps != null)
{
for (int v = 0; v < vps.size(); ++v)
{
COSDictionary vp = (COSDictionary) vps.getObject(v);
PDRectangle rect = new PDRectangle((COSArray) vp.getDictionaryObject(COSName.BBOX));
System.out.println("Viewport " + vp.getString(COSName.NAME) + ": " + rect);
}
}
}
}
如何调整注释由您决定...最有可能的是,这些应该在 bbox 内。您只需要调整注释的矩形即可。
我已经实现了使用 pdfbox 向任何 pdf 添加 link 注释的功能。它适用于大多数 pdf,但对于某些 pdf,它没有将标记放置在正确的坐标处。当我在某个 pdf 编辑器中打开该 pdf 时,它警告我该 pdf 包含一个未命名的视口,这可能会影响该 pdf 的测量。所以,我觉得视口很可能是导致问题的原因。有没有一种方法可以根据视口修改标记的坐标,以便将其放置在 pdf 中的正确位置。这是包含视口的 pdf 的 link。
根据Tilman的建议,我从viewport的measure字典中提取了C项。并尝试修改矩形的坐标,但它们没有添加到右侧 location.Below 是我尝试过的代码。此外,视口对注释没有影响,但当我尝试将某些内容绘制到 pdf 中时它会导致问题。
COSArray vps = (COSArray)page.getCOSObject().getDictionaryObject(COSName.getPDFName("VP"));
if (vps != null)
{
for (int v = 0; v < vps.size(); ++v)
{
COSDictionary vp = (COSDictionary)vps.getObject(v);
PDViewportDictionary viewportDict = new PDViewportDictionary(vp);
PDRectangle vpRect = viewportDict.getBBox();
PDMeasureDictionary measureDict = viewportDict.getMeasure();
PDRectlinearMeasureDictionary rectilinearDict = new PDRectlinearMeasureDictionary(measureDict.getCOSObject());
bool pointLieInVP = UtilityClass.RectangleContainsPoint(new PointF(leftX, bottomY), vpRect);
if (pointLieInVP)
{
COSArray xArray = (COSArray)measureDict.getCOSObject().getDictionaryObject(COSName.getPDFName("X"));
float xScale = 1;
if (xArray!=null)
{
xScale = ((COSFloat)(((COSDictionary)xArray.getObject(0)).getDictionaryObject(COSName.getPDFName("C")))).floatValue();
}
leftX /= xScale;
rightX /= xScale;
COSBase yObj = measureDict.getCOSObject().getDictionaryObject(COSName.getPDFName("Y"));
if (yObj != null)
{
COSArray yArray = (COSArray)yObj;
float yScale = ((COSFloat)(((COSDictionary)yArray.getObject(0)).getDictionaryObject(COSName.getPDFName("C")))).floatValue();
bottomY /= yScale;
topY /= yScale;
}
else
{
bottomY /= xScale;
topY /= xScale;
}
}
}
}
这是 pdf 的 link to pdf markups are added without adjusting for viewports. The 5 red colored markups are added at bottom right end of the page. But they should have been placed over the link annotations in the pdf which are placed at correct positions. And here is the link,其中标记是在使用上述代码修改坐标后放置的。标记根本没有出现。
此代码(不避免 ClassCastExceptions)将显示每个页面中的视口:
try (PDDocument doc = PDDocument.load(new File("S115-STRUCTURALHIGH ROOF FRAMING(WEST)ENLARGED PLANS.pdf")))
{
for (int p = 0; p < doc.getNumberOfPages(); ++p)
{
PDPage page = doc.getPage(p);
COSArray vps = (COSArray) page.getCOSObject().getDictionaryObject(COSName.getPDFName("VP"));
if (vps != null)
{
for (int v = 0; v < vps.size(); ++v)
{
COSDictionary vp = (COSDictionary) vps.getObject(v);
PDRectangle rect = new PDRectangle((COSArray) vp.getDictionaryObject(COSName.BBOX));
System.out.println("Viewport " + vp.getString(COSName.NAME) + ": " + rect);
}
}
}
}
如何调整注释由您决定...最有可能的是,这些应该在 bbox 内。您只需要调整注释的矩形即可。