MNT-24205 Tiff to pdf page size regression (#965)

* MNT-24205 Fix Tiff to PDF regression

* MNT-24205 add test files

* MNT-24205 remove redundant code
This commit is contained in:
Sara 2024-06-14 11:01:49 +01:00 committed by GitHub
parent dc6000af0c
commit 8c3fa87a25
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 116 additions and 6 deletions

View File

@ -52,6 +52,13 @@
<version>${dependency.pdfbox.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-imaging -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>${dependency.imaging.version}</version>
</dependency>
<!-- OOXMLThumbnailContentTransformer -->
<dependency>
<groupId>org.apache.poi</groupId>

View File

@ -2,7 +2,7 @@
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
@ -30,6 +30,8 @@ import static org.alfresco.transform.common.RequestParamMap.END_PAGE;
import static org.alfresco.transform.common.RequestParamMap.PDF_FORMAT;
import static org.alfresco.transform.common.RequestParamMap.PDF_ORIENTATION;
import static org.alfresco.transform.common.RequestParamMap.START_PAGE;
import static org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants.TIFF_TAG_XRESOLUTION;
import static org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants.TIFF_TAG_YRESOLUTION;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
@ -45,6 +47,12 @@ import java.util.stream.Stream;
import org.alfresco.transform.base.TransformManager;
import org.alfresco.transform.base.util.CustomTransformerFileAdaptor;
import org.apache.commons.imaging.Imaging;
import org.apache.commons.imaging.ImagingException;
import org.apache.commons.imaging.common.ImageMetadata;
import org.apache.commons.imaging.formats.tiff.TiffField;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
@ -75,8 +83,9 @@ public class ImageToPdfTransformer implements CustomTransformerFileAdaptor
private static final String START_PAGE_GREATER_THAN_END_PAGE_ERROR_MESSAGE = "Start page number cannot be greater than end page.";
private static final String INVALID_OPTION_ERROR_MESSAGE = "Parameter '%s' is invalid: \"%s\" - it must be an integer.";
private static final String INVALID_IMAGE_ERROR_MESSAGE = "Image file (%s) format (%s) not supported by ImageIO.";
private static final String DEFAULT_PDF_FORMAT_STRING = "DEFAULT";
private static final String DEFAULT_PDF_FORMAT_STRING = "DEFAULT"; // pdf format to use when no pdf format specified
private static final String DEFAULT_PDF_ORIENTATION_STRING = "DEFAULT";
private static final float PDFBOX_POINTS_PER_INCH = 72.0F;
@Override
public String getTransformerName()
@ -99,6 +108,7 @@ public class ImageToPdfTransformer implements CustomTransformerFileAdaptor
final String pdfOrientation = parseOptionIfPresent(transformOptions, PDF_ORIENTATION, String.class).orElse(DEFAULT_PDF_ORIENTATION_STRING);
verifyOptions(startPage, endPage);
final Map<String, Integer> resolution = determineImageResolution(imageFile);
final ImageReader imageReader = findImageReader(imageInputStream, imageFile.getName(), sourceMimetype);
for (int i = 0; i < imageReader.getNumImages(true); i++)
{
@ -111,7 +121,7 @@ public class ImageToPdfTransformer implements CustomTransformerFileAdaptor
break;
}
scaleAndDrawImage(pdfDocument, imageReader.read(i), pdfFormat, pdfOrientation);
scaleAndDrawImage(pdfDocument, imageReader.read(i), pdfFormat, pdfOrientation, resolution);
}
pdfDocument.save(pdfFile);
@ -131,11 +141,22 @@ public class ImageToPdfTransformer implements CustomTransformerFileAdaptor
return imageReader;
}
private void scaleAndDrawImage(final PDDocument pdfDocument, final BufferedImage bufferedImage, final String pdfFormat, final String pdfOrientation)
private void scaleAndDrawImage(final PDDocument pdfDocument, final BufferedImage bufferedImage, final String pdfFormat, final String pdfOrientation, final Map<String, Integer> resolution)
throws IOException
{
final PDImageXObject image = LosslessFactory.createFromImage(pdfDocument, bufferedImage);
final PDPage pdfPage = new PDPage(resolvePdfFormat(pdfFormat, pdfOrientation, image.getWidth(), image.getHeight()));
int imageWidth = image.getWidth();
int imageHeight = image.getHeight();
// if the image has a resolution which differs from pdfbox then adjust size in pixels according to pdfbox ppi
if (resolution.get("X") > 0 && resolution.get("X") != PDFBOX_POINTS_PER_INCH &&
resolution.get("Y") > 0 && resolution.get("Y") != PDFBOX_POINTS_PER_INCH)
{
imageWidth = (int)(((float)imageWidth / resolution.get("X")) * PDFBOX_POINTS_PER_INCH);
imageHeight = (int)(((float)imageHeight / resolution.get("Y")) * PDFBOX_POINTS_PER_INCH);
}
final PDPage pdfPage = new PDPage(resolvePdfFormat(pdfFormat, pdfOrientation, imageWidth, imageHeight));
pdfDocument.addPage(pdfPage);
try (PDPageContentStream pdfPageContent = new PDPageContentStream(pdfDocument, pdfPage))
{
@ -257,4 +278,44 @@ public class ImageToPdfTransformer implements CustomTransformerFileAdaptor
throw new IllegalArgumentException(START_PAGE_GREATER_THAN_END_PAGE_ERROR_MESSAGE);
}
}
private static Map<String, Integer> determineImageResolution(File imageFile)
{
int xResolution = 0;
int yResolution = 0;
try
{
final ImageMetadata metadata = Imaging.getMetadata(imageFile);
if (metadata instanceof TiffImageMetadata)
{
final TiffImageMetadata tiffImageMetadata = (TiffImageMetadata) metadata;
xResolution = findMetadataField(tiffImageMetadata, TIFF_TAG_XRESOLUTION);
yResolution = findMetadataField(tiffImageMetadata, TIFF_TAG_YRESOLUTION);
}
}
catch (IOException e)
{
// treat as though no resolution exists
}
return Map.of("X", xResolution, "Y", yResolution);
}
static private int findMetadataField(TiffImageMetadata tiffImageMetadata, TagInfo tagInfo)
{
int value = 0;
try
{
TiffField field = tiffImageMetadata.findField(tagInfo);
if (field != null)
{
value = field.getIntValue();
}
}
catch (ImagingException e)
{
// treat as though field not found
}
return value;
}
}

View File

@ -2,7 +2,7 @@
* #%L
* Alfresco Transform Core
* %%
* Copyright (C) 2005 - 2022 Alfresco Software Limited
* Copyright (C) 2005 - 2024 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* -
@ -290,6 +290,41 @@ class ImageToPdfTransformerTest
}
}
static Stream<Arguments> imageFilesOfVariousSizeAndResolution()
{
return Stream.of(
Arguments.of(ImageFile.of("MNT-24205.tiff", MIMETYPE_IMAGE_TIFF), 612.0f, 792.0f),
Arguments.of(ImageFile.of("459x594-50.tif", MIMETYPE_IMAGE_TIFF), 660.0f, 855.0f),
Arguments.of(ImageFile.of("459x594-72.tif", MIMETYPE_IMAGE_TIFF), 459.0f, 594.0f),
Arguments.of(ImageFile.of("459x594-300.tif", MIMETYPE_IMAGE_TIFF), 110.0f, 142.0f),
Arguments.of(ImageFile.of("612x792-50.tif", MIMETYPE_IMAGE_TIFF), 881.0f, 1140.0f),
Arguments.of(ImageFile.of("612x792-72.tif", MIMETYPE_IMAGE_TIFF), 612.0f, 792.0f),
Arguments.of(ImageFile.of("612x792-300.tif", MIMETYPE_IMAGE_TIFF), 146.0f, 190.0f),
Arguments.of(ImageFile.of("765x990-50.tif", MIMETYPE_IMAGE_TIFF), 1101.0f, 1425.0f),
Arguments.of(ImageFile.of("765x990-72.tif", MIMETYPE_IMAGE_TIFF), 765.0f, 990.0f),
Arguments.of(ImageFile.of("765x990-300.tif", MIMETYPE_IMAGE_TIFF), 183.0f, 237.0f)
);
}
@ParameterizedTest
@MethodSource("imageFilesOfVariousSizeAndResolution")
void testTransformTiffToPDF_withVariousImageSizes(ImageFile imageFile, float expectedWidth, float expectedHeight) throws Exception
{
TransformOptions transformOptions = TransformOptions.of("DEFAULT");
File source = loadFile(imageFile.fileName);
// when
transformer.transform(imageFile.mimetype, MIMETYPE_PDF, transformOptions.toMap(), source, targetFile, transformManager);
try (PDDocument actualPdfDocument = PDDocument.load(targetFile))
{
assertNotNull(actualPdfDocument);
assertEquals(expectedWidth, actualPdfDocument.getPage(0).getMediaBox().getWidth(),"Pdf width");
assertEquals(expectedHeight,actualPdfDocument.getPage(0).getMediaBox().getHeight(),"Pdf height");
}
}
//----------------------------------------------- Helper methods and classes -----------------------------------------------
private static BiFunction<Float, Float, PDRectangle> unchangedRectangle()

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -27,6 +27,7 @@
<dependency.jackson.version>2.16.1</dependency.jackson.version>
<dependency.tika.version>2.9.2</dependency.tika.version>
<dependency.poi.version>5.2.5</dependency.poi.version>
<dependency.imaging.version>1.0.0-alpha5</dependency.imaging.version>
<dependency.snakeyaml.version>2.2</dependency.snakeyaml.version>
<!--The override can be removed when transitive (from tika) bouncycastle dependency is free of vulnerabilities-->
<dependency.bouncycastle.version.override>1.78.1</dependency.bouncycastle.version.override>
@ -160,6 +161,12 @@
<artifactId>pdfbox-tools</artifactId>
<version>${dependency.pdfbox.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-imaging -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-imaging</artifactId>
<version>${dependency.imaging.version}</version>
</dependency>
<!-- Jackson -->
<dependency>
<groupId>com.fasterxml.jackson</groupId>