1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.imaging.formats.png;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertNotNull;
23 import static org.junit.jupiter.api.Assertions.assertTrue;
24
25 import java.awt.image.BufferedImage;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.util.LinkedList;
29 import java.util.List;
30 import java.util.Random;
31
32 import org.apache.commons.imaging.AbstractImagingTest;
33 import org.apache.commons.imaging.ImageFormats;
34 import org.apache.commons.imaging.Imaging;
35 import org.apache.commons.imaging.ImagingException;
36 import org.apache.commons.imaging.common.GenericImageMetadata;
37 import org.apache.commons.imaging.common.ImageMetadata;
38 import org.junit.jupiter.api.Test;
39
40 public class PngWriteReadTest extends AbstractImagingTest {
41
42 private int[][] bufferedImageToImageData(final BufferedImage image) {
43 final int width = image.getWidth();
44 final int height = image.getHeight();
45 final int[][] result = new int[height][width];
46
47 for (int y = 0; y < height; y++) {
48 for (int x = 0; x < width; x++) {
49 result[y][x] = image.getRGB(x, y);
50 }
51 }
52 return result;
53 }
54
55 private int[][] getAscendingRawData(final int width, final int height) {
56 final int[][] result = new int[height][width];
57 for (int y = 0; y < height; y++) {
58 for (int x = 0; x < width; x++) {
59 final int alpha = (x + y) % 256;
60 final int value = (x + y) % 256;
61 final int argb = (0xff & alpha) << 24 | (0xff & value) << 16 | (0xff & value) << 8 | (0xff & value) << 0;
62
63 result[y][x] = argb;
64 }
65 }
66 return result;
67 }
68
69 private int[][] getSimpleRawData(final int width, final int height, final int value) {
70 final int[][] result = new int[height][width];
71 for (int y = 0; y < height; y++) {
72 for (int x = 0; x < width; x++) {
73 result[y][x] = value;
74 }
75 }
76 return result;
77 }
78
79 private BufferedImage imageDataToBufferedImage(final int[][] rawData) {
80 final int width = rawData[0].length;
81 final int height = rawData.length;
82 final BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
83 for (int y = 0; y < height; y++) {
84 for (int x = 0; x < width; x++) {
85 image.setRGB(x, y, rawData[y][x]);
86 }
87 }
88 return image;
89 }
90
91 private int[][] randomRawData(final int width, final int height) {
92 final Random random = new Random();
93 final int[][] result = new int[height][width];
94 for (int y = 0; y < height; y++) {
95 for (int x = 0; x < width; x++) {
96 final int argb = random.nextInt();
97 result[y][x] = argb;
98 }
99 }
100 return result;
101 }
102
103 @Test
104 public void test() throws Exception {
105 final int[][] smallBlackPixels = getSimpleRawData(256, 256, 0);
106 final int[][] singleBlackPixel = getSimpleRawData(1, 1, 0);
107 final int[][] smallRedPixels = getSimpleRawData(256, 256, 0xffff0000);
108 final int[][] singleRedPixel = getSimpleRawData(1, 1, 0xffff0000);
109 final int[][] smallAscendingPixels = getAscendingRawData(256, 256);
110 final int[][] smallRandomPixels = randomRawData(256, 256);
111
112 final int[][][] testData = { smallBlackPixels, singleBlackPixel, smallRedPixels, singleRedPixel, smallAscendingPixels, smallRandomPixels, };
113
114 for (final int[][] rawData : testData) {
115 writeAndReadImageData(rawData);
116 }
117 }
118
119 @Test
120 public void testMultipletEXt() throws Exception {
121 final int[][] smallBlackPixels = getSimpleRawData(256, 256, 0);
122
123 writeAndReadMultipleEXt(smallBlackPixels);
124 }
125
126 @Test
127 public void testPhysicalScaleMeters() throws Exception {
128 final PngImageParser pngImageParser = new PngImageParser();
129 final PngImagingParameters optionalParams = new PngImagingParameters();
130 optionalParams.setPhysicalScale(PhysicalScale.createFromMeters(0.01, 0.02));
131
132 final int[][] smallAscendingPixels = getAscendingRawData(256, 256);
133 final byte[] pngBytes;
134 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
135 pngImageParser.writeImage(imageDataToBufferedImage(smallAscendingPixels), baos, optionalParams);
136 pngBytes = baos.toByteArray();
137 }
138 final PngImageInfo imageInfo = (PngImageInfo) Imaging.getImageInfo(pngBytes);
139 final PhysicalScale physicalScale = imageInfo.getPhysicalScale();
140 assertTrue(physicalScale.isInMeters());
141 assertEquals(0.01, physicalScale.getHorizontalUnitsPerPixel(), 0.001);
142 assertEquals(0.02, physicalScale.getVerticalUnitsPerPixel(), 0.001);
143 }
144
145 @Test
146 public void testPhysicalScaleRadians() throws Exception {
147 final PngImageParser pngImageParser = new PngImageParser();
148 final PngImagingParameters optionalParams = new PngImagingParameters();
149 optionalParams.setPhysicalScale(PhysicalScale.createFromRadians(0.01, 0.02));
150
151 final int[][] smallAscendingPixels = getAscendingRawData(256, 256);
152 final byte[] pngBytes;
153 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
154 pngImageParser.writeImage(imageDataToBufferedImage(smallAscendingPixels), baos, optionalParams);
155 pngBytes = baos.toByteArray();
156 }
157 final PngImageInfo imageInfo = (PngImageInfo) Imaging.getImageInfo(pngBytes);
158 final PhysicalScale physicalScale = imageInfo.getPhysicalScale();
159 assertTrue(physicalScale.isInRadians());
160 assertEquals(0.01, physicalScale.getHorizontalUnitsPerPixel(), 0.001);
161 assertEquals(0.02, physicalScale.getVerticalUnitsPerPixel(), 0.001);
162 }
163
164 @Test
165 public void testTransparency() throws Exception {
166
167 final int[][] smallAscendingPixels = getAscendingRawData(256, 256);
168 final byte[] pngBytes = Imaging.writeImageToBytes(imageDataToBufferedImage(smallAscendingPixels), ImageFormats.PNG);
169 assertTrue(Imaging.getImageInfo(pngBytes).isTransparent());
170 }
171
172 private void writeAndReadImageData(final int[][] rawData) throws IOException, ImagingException, ImagingException {
173 final BufferedImage srcImage = imageDataToBufferedImage(rawData);
174
175 final byte[] bytes = Imaging.writeImageToBytes(srcImage, ImageFormats.PNG);
176
177 final BufferedImage dstImage = Imaging.getBufferedImage(bytes);
178
179 assertNotNull(dstImage);
180 assertEquals(srcImage.getWidth(), dstImage.getWidth());
181 assertEquals(srcImage.getHeight(), dstImage.getHeight());
182
183 final int[][] dstData = bufferedImageToImageData(dstImage);
184 assertArrayEquals(rawData, dstData);
185 }
186
187 private void writeAndReadMultipleEXt(final int[][] rawData) throws IOException, ImagingException, ImagingException {
188 final BufferedImage srcImage = imageDataToBufferedImage(rawData);
189
190 final List<AbstractPngText.Text> textChunks = new LinkedList<>();
191 textChunks.add(new AbstractPngText.Text("a", "b"));
192 textChunks.add(new AbstractPngText.Text("c", "d"));
193 final PngImagingParameters writeParams = new PngImagingParameters();
194 writeParams.setTextChunks(textChunks);
195
196 final PngImageParser pngImageParser = new PngImageParser();
197 final byte[] bytes;
198 try (ByteArrayOutputStream os = new ByteArrayOutputStream()) {
199 pngImageParser.writeImage(srcImage, os, writeParams);
200 bytes = os.toByteArray();
201 }
202
203 final BufferedImage dstImage = Imaging.getBufferedImage(bytes);
204
205 assertNotNull(dstImage);
206 assertEquals(srcImage.getWidth(), dstImage.getWidth());
207 assertEquals(srcImage.getHeight(), dstImage.getHeight());
208
209 final int[][] dstData = bufferedImageToImageData(dstImage);
210 assertArrayEquals(rawData, dstData);
211
212 final ImageMetadata imageMetadata = Imaging.getMetadata(bytes);
213 assertEquals(imageMetadata.getItems().size(), 2);
214 final GenericImageMetadata.GenericImageMetadataItem item0 = (GenericImageMetadata.GenericImageMetadataItem) imageMetadata.getItems().get(0);
215 assertEquals(item0.getKeyword(), "a");
216 assertEquals(item0.getText(), "b");
217 final GenericImageMetadata.GenericImageMetadataItem item1 = (GenericImageMetadata.GenericImageMetadataItem) imageMetadata.getItems().get(1);
218 assertEquals(item1.getKeyword(), "c");
219 assertEquals(item1.getText(), "d");
220 }
221 }