diff --git a/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/Image.java b/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/Image.java index b583af20a..4e534db31 100644 --- a/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/Image.java +++ b/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/Image.java @@ -753,12 +753,30 @@ public abstract class Image extends Rectangle { } else if (transparency == null) { if (alpha == 0) { transparentPixel = pixels[j] & 0xffffff; + // Added by Michael Klink + // Check whether this value for transparent pixels + // has already been used for a non-transparent one + // before this position + for (int prevPixel = 0; prevPixel < j; prevPixel++) { + if ((pixels[prevPixel] & 0xffffff) == transparentPixel) { + // found a prior use of the transparentPixel color + // and, therefore, cannot make use of this color + // for transparency; we could still use an image + // mask but for simplicity let's use a soft mask + // which already is implemented here + // stackOverFlow:https://stackoverflow.com/questions/39119776/itext-binary-transparency-bug + shades = true; + break; + } + } transparency = new int[6]; transparency[0] = transparency[1] = (transparentPixel >> 16) & 0xff; transparency[2] = transparency[3] = (transparentPixel >> 8) & 0xff; transparency[4] = transparency[5] = transparentPixel & 0xff; } - } else if ((pixels[j] & 0xffffff) != transparentPixel) { + } else if (((pixels[j] & 0xffffff) != transparentPixel) && (alpha == 0)) { + shades = true; + } else if (((pixels[j] & 0xffffff) == transparentPixel) && (alpha != 0)) { shades = true; } } diff --git a/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/pdf/ByteBuffer.java b/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/pdf/ByteBuffer.java index e48934ef0..e71127490 100644 --- a/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/pdf/ByteBuffer.java +++ b/fine-itext-old/src/main/java/com/fr/third/com/lowagie/text/pdf/ByteBuffer.java @@ -82,6 +82,7 @@ public class ByteBuffer extends OutputStream { */ public static boolean HIGH_PRECISION = false; private static final DecimalFormatSymbols dfs = new DecimalFormatSymbols(Locale.US); + private static final int HALF_INTEGER = Integer.MAX_VALUE >> 1; /** Creates new ByteBuffer with capacity 128 */ public ByteBuffer() { @@ -188,8 +189,11 @@ public class ByteBuffer extends OutputStream { */ public ByteBuffer append_i(int b) { int newcount = count + 1; + if (newcount < 0) { + throw new OutOfMemoryError(); + } if (newcount > buf.length) { - byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)]; + byte newbuf[] = new byte[Math.max(Math.min(buf.length, HALF_INTEGER) << 1, newcount)]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } @@ -211,8 +215,11 @@ public class ByteBuffer extends OutputStream { ((off + len) > b.length) || ((off + len) < 0) || len == 0) return this; int newcount = count + len; + if (newcount < 0) { + throw new OutOfMemoryError(); + } if (newcount > buf.length) { - byte newbuf[] = new byte[Math.max(buf.length << 1, newcount)]; + byte newbuf[] = new byte[Math.max(Math.min(buf.length, HALF_INTEGER) << 1, newcount)]; System.arraycopy(buf, 0, newbuf, 0, count); buf = newbuf; } diff --git a/fine-itext-old/test/com/fr/third/com/lowagie/text/ImageTest.java b/fine-itext-old/test/com/fr/third/com/lowagie/text/ImageTest.java new file mode 100644 index 000000000..699d98d92 --- /dev/null +++ b/fine-itext-old/test/com/fr/third/com/lowagie/text/ImageTest.java @@ -0,0 +1,108 @@ +import com.fr.third.com.lowagie.text.Document; +import com.fr.third.com.lowagie.text.RectangleReadOnly; +import com.fr.third.com.lowagie.text.pdf.PdfContentByte; +import com.fr.third.com.lowagie.text.pdf.PdfGraphics2D; +import com.fr.third.com.lowagie.text.pdf.PdfTemplate; +import com.fr.third.com.lowagie.text.pdf.PdfWriter; +import org.junit.Test; +import org.junit.Assert; + +import javax.imageio.ImageIO; +import java.awt.Color; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.util.Arrays; + + + +/** + * Image单元测试类 + * 不在打包范围内,只是留个凭证,需要自己添加junit 依赖才能跑 + * + * @author obo + * @since 11.0 + * Created on 2023/9/6 + */ +public class ITextDrawPdfImageTest { + + @Test + public void testDrawOpaqueAndTransparentImage() throws Exception { + // 创建文档对象 + Document document = new Document(new RectangleReadOnly(90,90)); + // 创建PdfWriter以将文档写入文件 + PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("actual.pdf")); + BufferedImage image = ImageIO.read(new File("transparent_image.png")); + + Assert.assertTrue(checkImageValid(image)); + + // 打开文档 + document.open(); + + // 获取PdfContentByte用于在PDF页面上绘制内容 + PdfContentByte contentByte = writer.getDirectContent(); + + // 创建PdfTemplate,作为图形容器 + PdfTemplate template = contentByte.createTemplate(90, 90); + PdfGraphics2D graphics2D = (PdfGraphics2D) template.createGraphics(90, 90); + + // 在Graphics2D上绘制图像或其他内容 + graphics2D.drawImage(image, 0, 0, null); + + // 释放Graphics2D资源 + graphics2D.dispose(); + + // 将PdfTemplate添加到PDF页面 + contentByte.addTemplate(template, 0, 0); // X, Y 坐标 + // 关闭文档 + document.close(); + + File actual = new File("actual.pdf"); + File expect = new File("expect.pdf"); + + Assert.assertTrue(checkFilesEqual(actual, expect)); + } + + + private boolean checkFilesEqual(File actual, File expect) throws IOException { + byte[] actualBytes = Arrays.copyOfRange(Files.readAllBytes(actual.toPath()), 0, 1024); + byte[] expectBytes = Arrays.copyOfRange(Files.readAllBytes(expect.toPath()), 0, 1024); + + return java.util.Arrays.equals(actualBytes, expectBytes); + } + + /** + * 检查Image是否是一种完全透明颜色+一种完全不透明颜色构成的 + */ + private boolean checkImageValid(BufferedImage image) { + int transparentColor = -1, unTransparentColor = -1; + + int width = image.getWidth(); + int height = image.getHeight(); + + for (int x = 0; x < width; x++) { + for (int y = 0; y < height; y++) { + int rgb = image.getRGB(x, y); + int alpha = (rgb >> 24) & 0xFF; + int color = rgb & 0xFFFFFF; + if(alpha == 0) { + if (transparentColor == -1) { + transparentColor = color; + } else if (transparentColor != color) { + return false; + } + } + if(alpha == 255) { + if (unTransparentColor == -1) { + unTransparentColor = color; + } else if (unTransparentColor != color) { + return false; + } + } + } + } + return true; + } +} \ No newline at end of file diff --git a/fine-itext-old/test/com/fr/third/com/lowagie/text/actual.pdf b/fine-itext-old/test/com/fr/third/com/lowagie/text/actual.pdf new file mode 100644 index 000000000..dbc229d9f Binary files /dev/null and b/fine-itext-old/test/com/fr/third/com/lowagie/text/actual.pdf differ diff --git a/fine-itext-old/test/com/fr/third/com/lowagie/text/expect.pdf b/fine-itext-old/test/com/fr/third/com/lowagie/text/expect.pdf new file mode 100644 index 000000000..001e575fe Binary files /dev/null and b/fine-itext-old/test/com/fr/third/com/lowagie/text/expect.pdf differ diff --git a/fine-itext-old/test/com/fr/third/com/lowagie/text/transparent_image.png b/fine-itext-old/test/com/fr/third/com/lowagie/text/transparent_image.png new file mode 100644 index 000000000..820cc05ca Binary files /dev/null and b/fine-itext-old/test/com/fr/third/com/lowagie/text/transparent_image.png differ