ImageFromLanguageStandardLibraryTest.java
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2025 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itextpdf.kernel.pdf.xobject;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfStream;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.utils.CompareTool;
import com.itextpdf.test.ExtendedITextTest;
import com.itextpdf.test.TestUtil;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledInNativeImage;
@Tag("IntegrationTest")
// Android-Conversion-Skip-File (java.awt library isn't available on Android)
public class ImageFromLanguageStandardLibraryTest extends ExtendedITextTest {
public static final String destinationFolder = TestUtil.getOutputPath() + "/kernel/pdf/xobject/ImageFromLanguageStandardLibraryTest/";
public static final String sourceFolder = "./src/test/resources/com/itextpdf/kernel/pdf/xobject/ImageFromLanguageStandardLibraryTest/";
@BeforeAll
public static void beforeClass() {
createDestinationFolder(destinationFolder);
}
@AfterAll
public static void afterClass() {
CompareTool.cleanup(destinationFolder);
}
@DisabledInNativeImage // java.awt is not compatible with graalvm
@Test
// See http://stackoverflow.com/questions/39119776/itext-binary-transparency-bug
public void imageBinaryTransparencySameColorTest() throws java.io.IOException {
String outFile = destinationFolder + "imageBinaryTransparencySameColorTest.pdf";
String cmpFile = sourceFolder + "cmp_imageBinaryTransparencySameColorTest.pdf";
ImageData bkgnd = ImageDataFactory.create(sourceFolder + "itext.jpg");
PdfImageXObject image = new PdfImageXObject(bkgnd);
PdfDocument pdfDocument = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
PdfCanvas canvas = new PdfCanvas(pdfDocument.addNewPage());
PdfPage firstPage = pdfDocument.getFirstPage();
canvas.addXObjectFittedIntoRectangle(image, firstPage.getPageSize());
canvas
.beginText()
.setTextMatrix(36, 790)
.setFontAndSize(PdfFontFactory.createFont(), 12)
.showText("Invisible image (both opaque and non opaque pixels have the same color)")
.endText();
canvas.addXObjectAt(new PdfImageXObject(
ImageDataFactory.create(createBinaryTransparentAWTImage(null), null)), 36, 580);
PdfDocument cmpDoc = new PdfDocument(new PdfReader(cmpFile));
// In general case this code will probably will fail, however in this particular case we know the structure of the pdf
PdfStream outStream = firstPage.getResources().getResource(PdfName.XObject).getAsStream(new PdfName("Im1"));
PdfStream cmpStream = cmpDoc.getFirstPage().getResources().getResource(PdfName.XObject).getAsStream(new PdfName("Im1"));
Assertions.assertNull(new CompareTool().compareStreamsStructure(outStream, cmpStream));
cmpDoc.close();
pdfDocument.close();
ExtendedITextTest.printOutputPdfNameAndDir(outFile);
}
@DisabledInNativeImage // java.awt is not compatible with graalvm
@Test
// See http://stackoverflow.com/questions/39119776/itext-binary-transparency-bug
public void imageBinaryTransparencyDifferentColorsTest() throws java.io.IOException {
String outFile = destinationFolder + "imageBinaryTransparencyDifferentColorsTest.pdf";
String cmpFile = sourceFolder + "cmp_imageBinaryTransparencyDifferentColorsTest.pdf";
ImageData bkgnd = ImageDataFactory.create(sourceFolder + "itext.jpg");
PdfImageXObject image = new PdfImageXObject(bkgnd);
PdfDocument pdfDocument = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
PdfCanvas canvas = new PdfCanvas(pdfDocument.addNewPage());
PdfPage firstPage = pdfDocument.getFirstPage();
canvas.addXObjectFittedIntoRectangle(image, firstPage.getPageSize());
canvas
.beginText()
.setTextMatrix(36, 790)
.setFontAndSize(PdfFontFactory.createFont(), 12)
.showText("Invisible image (both opaque and non opaque pixels have different colors)")
.endText();
canvas.addXObjectAt(new PdfImageXObject(
ImageDataFactory.create(createBinaryTransparentAWTImage(java.awt.Color.red), null)), 36, 580);
PdfDocument cmpDoc = new PdfDocument(new PdfReader(cmpFile));
// In general case this code will probably will fail, however in this particular case we know the structure of the pdf
PdfStream outStream = firstPage.getResources().getResource(PdfName.XObject).getAsStream(new PdfName("Im1"));
PdfStream cmpStream = cmpDoc.getFirstPage().getResources().getResource(PdfName.XObject).getAsStream(new PdfName("Im1"));
Assertions.assertNull(new CompareTool().compareStreamsStructure(outStream, cmpStream));
cmpDoc.close();
pdfDocument.close();
ExtendedITextTest.printOutputPdfNameAndDir(outFile);
}
// Create an ARGB AWT Image that has only 100% transparent and 0% transparent pixels.
// All transparent pixels have the Color "backgroundColor"
private static java.awt.image.BufferedImage createBinaryTransparentAWTImage(java.awt.Color backgroundColor) {
java.awt.Dimension size = new java.awt.Dimension(200, 200);
java.awt.image.BufferedImage awtImg = new java.awt.image.BufferedImage(size.width, size.height, java.awt.image.BufferedImage.TYPE_INT_ARGB);
java.awt.Graphics2D g2d = awtImg.createGraphics();
if (backgroundColor != null) {
//Usually it doesn't make much sense to set the color of transparent pixels...
//but in this case it changes the behavior of com.itextpdf.text.Image.getInstance fundamentally!
g2d.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC, 0f));
g2d.setColor(backgroundColor);
g2d.fillRect(0, 0, size.width, size.height);
}
g2d.setComposite(java.awt.AlphaComposite.getInstance(java.awt.AlphaComposite.SRC_OVER, 1f));
g2d.setColor(java.awt.Color.black);
java.awt.BasicStroke bs = new java.awt.BasicStroke(2);
g2d.setStroke(bs);
for (int i = 0; i < 5; i++) {
g2d.drawLine((size.width + 2) / 4 * i, 0, (size.width + 2) / 4 * i, size.height - 1);
g2d.drawLine(0, (size.height + 2) / 4 * i, size.width - 1, (size.height + 2) / 4 * i);
}
return awtImg;
}
}