iText:使用图像设置 table 单元格的高度

iText: Set height of table cell with image

我用 iText 5.5.13.2(最新的 iText5 版本)创建了一个 table,我用从同一台 PC 上的特定文件夹读取的文本和图像填充它:

Paragraph p = new Paragraph();
p.add(new Phrase("This is a new paragraph!"));

PdfPTable table = new PdfPTable(2);
table.setWidthPercentage(100);

for(int i=0;i<imageArr.size();i++) { //imageArr.size()%2==0!
    PdfPCell cell = new PdfPCell();
    String name = imageArr.get(i);
    String path = imgFolder + File.separator + name;
    File f = new File(path);

    if(f.isFile()) {
        Image img = Image.getInstance(path);
        //cell.setCalculatedHeight(50);
        cell.addElement(img);
    } else {
        cell.addElement(new Phrase(name));
    }

    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    cell.setHorizontalAlignment(Element.ALIGN_MIDDLE);
    //cell.setCalculatedHeight(50);
    table.addCell(cell);
}

p.add(table);
doc.add(p);

table 中的两列使用相同的宽度(这很好)并且大图像会自动调整大小以适应宽度(这也很好),唯一不起作用的是:

所有单元格都应具有一定的高度,大图像应相应调整大小(同时仍保持适当的 height/width 比例)。在将图像添加到单元格之前或之后使用 setCalculatedHeight 似乎并不重要(只做一个或另一个,请参见上面的代码),单元格始终根据图像的高度设置其高度,因此只有横向格式的文本或图像的行总是小于纵向格式的图像的行。

即使在使用 img.setScaleToFitLineWhenOverflow(false)img.setScaleToFitHeight(false) 时,小图像也会调整大小(拉伸),但即便如此高度设置不正确。

我已经尝试使用 Chunk (cell.addElement(new Chunk(img, 0, 0))),但图像很小,我的高度设置仍然被忽略。

如何设置单元格的高度并使图像相应地调整大小?

我设法找到了解决方案。涉及大量测试,即使是现在我也不能 100% 确定为什么它会像大多数时候那样运行。

首先:不要添加带有 addElement 的元素,因为一旦您使用 PdfPCell 调用它,iText 就会从“文本模式”(似乎也会影响图像)切换到“复合模式”模式”,然后忽略所有对齐方式,...该单元格的设置,包括文本的水平对齐方式 - 您可以找到原始 iText 开发人员的更详细解释 here (with examples )。相反,先用 Image 做任何您想做的事,然后才用该图像创建 PdfPCell 。之后可以编辑单元格 - 虽然使用 table.getDefaultCell() 不起作用,但对其所做的更改不会对使用以下代码创建的单元格产生任何影响。

我的工作代码:

float docWidth = doc.getPageSize().getWidth() - doc.leftMargin() - doc.rightMargin();
float docHeight = doc.getPageSize().getHeight() - doc.topMargin() - doc.bottomMargin();
float docWidthDiv2 = docWidth/2 - 10;
float docHeightDiv2 = docHeight/2 - 10;
PdfPCell cell = null;

if(f.isFile()) {
    Image img = Image.getInstance(path);
    //img.scaleAbsolute(100, 50);

    if(img.getWidth() < docWidthDiv2 && img.getHeight < docHeightDiv2) {
        cell = new PdfPCell(img, false);
    } else {
        cell = new PdfPCell(img, true);
    }
} else {
    cell = new PdfPCell(new Phrase(name));
}

cell.setFixedHeight(50); //"setCalculatedHeight" doesn't work

为什么我将图像的宽度与 docWidthDiv2 进行比较,将图像的高度与 docHeightDiv2 进行比较?

有很多设置单元格高度的组合,但 none 显示了我预期的 100% 行为:真正大的图像应该按比例缩小以适合列的宽度(对于图像更重要在横向模式下)但也尊重单元格的固定高度(对于纵向模式下的图像更重要),同时仍保持其纵横比。已经很适合单元格的小图像根本不应该缩放。

new PDfPCell(Image image, boolean fit) 的文档描述了 fit 参数:

true to fit the image to the cell

在我的例子中 true 调整图像的大小(同时仍然尊重其纵横比和单元格的高度)直到它触及单元格的两个相对侧,因此:大图像缩小尺寸,小图像缩小拉伸。

使用 false 时,图像的纵横比和单元格的高度仍然受到尊重,但是虽然小图像保持其大小,但横向模式下的大图像“渗入”相邻单元格(并且 setScaleToFitLineWhenOverflow 没有帮助)并且纵向模式下的大图像甚至可能根本不会显示(当它们对于单元格来说太高时)。

为了不拉伸小图像而减小大图像的尺寸,需要两者的结合。我只添加了 -10,因此潜在的默认填充不会弄乱它。如果你想在 table 之前或之后添加文本,那么你也必须从 docHeightDiv2 中减去它的高度。

如上所述,我还测试了其他组合,我从中获取的最重要信息:

如果在添加图像之前设置了单元格的高度,则图像将覆盖高度,无论它比单元格小(单元格高度缩小)还是大(单元格高度增加)。

在参数、设置图像大小和设置单元格高度之间有几个组合可以使用,但其中大多数图像要么保持其原始大小(例如 2000x1000 将不会完全可见在页面上)或者它们的大小会增加,直到它们触及单元格的两个相对侧(这也会增加单元格的高度)。最后只剩下一个组合仍然有用(在我看来)——一个例子:

img.scaleAbsolute(100, 50);
cell = new PdfPCell(img, false);
cell.setVerticalAlignment(Element.ALIGN_MIDDLE); //"center" doesn't work here
cell.setHorizontalAlignment(Element.ALIGN_CENTER); //"middle" doesn't work here
cell.setFixedHeight(150);

这将在 150 个单位高的单元格中心创建一个大小为 100x50(忽略原始纵横比)的图像(= 在图像上方和下方填充 50 个单位)。

关于 iText 的附加信息 table:

列平均共享 table 的可用宽度,无需更改它,即使第一个单元格包含非常小的图像而第二个单元格包含非常大的图像。在这方面,您唯一需要注意的是添加的单元格数量 - 行始终必须完全填充,因此具有 3 列的 table 每行必须包含 3 个单元格,否则该行将不会打印到 pdf 文件中(同样也不会打印空白的新页面)。可以创建空的额外单元格来填充行的其余部分:

PdfPCell extra = new PdfPCell();
extra.setFixedHeight(50);
table.addCell(extra);