pdfHTML 目前确实不支持 EXIF 数据中的旋转标志(拉取请求welcome https://github.com/itext/i7n-pdfhtml).
作为解决方法,您可以自定义标签工作工厂以插入您自己的实现中以进行处理<img>
标签。您可以在那里插入自己的实现来执行图像旋转。我要做的是使用 EXIF 读取旋转标志元数据提取器 https://github.com/drewnoakes/metadata-extractor-dotnet库并应用附加属性,即Image#setRotationAngle()
。另一种选择可能是只读取图像和旋转标志,然后旋转图像并替换图像内容(这样我们就可以用其精确副本替换原始图像,除非不使用旋转标志,即如果需要则旋转图像)在删除标志之前),例如通过将 Base64 编码的值放入src
属性。
这里我们创建一个自定义标签工人工厂:
private static class CustomTagWorkerFactory extends DefaultTagWorkerFactory {
@Override
public ITagWorker getCustomTagWorker(IElementNode tag, ProcessorContext context) {
if ("img".equals(tag.name())) {
return new RotationAwareImgTagWorker(tag, context);
}
return super.getCustomTagWorker(tag, context);
}
}
接下来是最重要的部分 - 解析图像并将我们的属性应用到自定义标记工作器中:
private static class RotationAwareImgTagWorker extends ImgTagWorker {
private int rotation = 0;
public RotationAwareImgTagWorker(IElementNode element,
ProcessorContext context) {
super(element, context);
}
@Override
public void processEnd(IElementNode element, ProcessorContext context) {
super.processEnd(element, context);
String src = element.getAttribute(AttributeConstants.SRC);
PdfXObject imageXObject = context.getResourceResolver().retrieveImageExtended(src);
if (imageXObject instanceof PdfImageXObject && ((PdfImageXObject) imageXObject).identifyImageType() == ImageType.JPEG) {
Metadata metadata = null;
try {
metadata = ImageMetadataReader
.readMetadata(new ByteArrayInputStream(((PdfImageXObject) imageXObject).getImageBytes()));
ExifIFD0Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
if (directory.containsTag(ExifSubIFDDirectory.TAG_ORIENTATION)) {
int orientation = directory.getInt(ExifSubIFDDirectory.TAG_ORIENTATION);
if (orientation != 0) {
switch (orientation) {
case 1:
break;
case 6:
this.rotation = 270;
break;
default:
throw new UnsupportedOperationException(); // TODO
}
}
}
} catch (Exception e) {
e.printStackTrace(); // TODO
}
}
}
@Override
public IPropertyContainer getElementResult() {
IPropertyContainer baseResult = super.getElementResult();
if (baseResult instanceof Image) {
((Image) baseResult).setRotationAngle(Math.PI * rotation / 180);
}
return baseResult;
}
}
为了把它们放在一起,我们需要利用ConverterProperties
:
ConverterProperties properties = new ConverterProperties();
properties.setTagWorkerFactory(new CustomTagWorkerFactory());
HtmlConverter.convertToPdf(new File(sourceHtml), new File(outPdf), properties);
这是视觉结果:
如果您想使用 PowerShell,那么您可能应该围绕 iText 构建自己的小型自定义库并调用该库,而不是在 PowerShell 中实现上述选项。请注意,答案是用 Java 编写的,但移植到 .NET 应该是大写一些字母名称等的小问题,并且metadata-extractor
与 iText 类似,该库可在 Java 和 .NET 上使用。