View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.imaging.formats.tiff;
19  
20  import static org.junit.jupiter.api.Assertions.assertEquals;
21  import static org.junit.jupiter.api.Assertions.fail;
22  
23  import java.awt.image.BufferedImage;
24  import java.io.ByteArrayOutputStream;
25  import java.io.IOException;
26  
27  import org.apache.commons.imaging.Imaging;
28  import org.apache.commons.imaging.ImagingException;
29  import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
30  import org.apache.commons.imaging.formats.tiff.itu_t4.T4AndT6Compression;
31  import org.apache.commons.imaging.internal.Debug;
32  import org.junit.jupiter.api.Test;
33  
34  public class TiffCcittTest extends AbstractTiffTest {
35  
36      /**
37       * Generates the next combination of elements in the sequence array, with each element having a maximum value of max. Initially, the sequence should be set
38       * to minimum values of each element.
39       *
40       * @param sequence the array of elements to update
41       * @param max      the maximum value of each element in the sequence
42       * @return false if there is no more combinations (ie. nothing was done), true otherwise
43       */
44      private static boolean nextCombination(final int[] sequence, final int max) {
45          int i;
46          for (i = 0; i < sequence.length; i++) {
47              if (sequence[i] != max) {
48                  sequence[i]++;
49                  break;
50              }
51              sequence[i] = 0;
52          }
53          return i < sequence.length;
54      }
55  
56      private void compareImages(final BufferedImage a, final BufferedImage b) {
57          assertEquals(a.getWidth(), b.getWidth());
58          assertEquals(a.getHeight(), b.getHeight());
59  
60          for (int x = 0; x < a.getWidth(); x++) {
61              for (int y = 0; y < a.getHeight(); y++) {
62                  final int aArgb = a.getRGB(x, y);
63                  final int bArgb = b.getRGB(x, y);
64                  if (aArgb != bArgb) {
65                      Debug.debug("width: " + a.getWidth());
66                      Debug.debug("height: " + a.getHeight());
67                      Debug.debug("x: " + x);
68                      Debug.debug("y: " + y);
69                      Debug.debug("aArgb: " + aArgb + " (0x" + Integer.toHexString(aArgb) + ")");
70                      Debug.debug("bArgb: " + bArgb + " (0x" + Integer.toHexString(bArgb) + ")");
71                  }
72                  assertEquals(aArgb, bArgb);
73              }
74          }
75      }
76  
77      @Test
78      public void testAll5x2Compressions() {
79          final byte[] uncompressed = new byte[2];
80          final int[] combinations = new int[10];
81          do {
82              for (int x = 0; x < 5; x++) {
83                  if (combinations[x] != 0) {
84                      uncompressed[0] |= 0x80 >>> x;
85                  }
86              }
87              for (int x = 0; x < 5; x++) {
88                  if (combinations[5 + x] != 0) {
89                      uncompressed[1] |= 0x80 >>> x;
90                  }
91              }
92  
93              try {
94                  final byte[] compressed = T4AndT6Compression.compressModifiedHuffman(uncompressed, 5, 2);
95                  final byte[] result = T4AndT6Compression.decompressModifiedHuffman(compressed, 5, 2);
96                  assertEquals(uncompressed.length, result.length);
97                  for (int i = 0; i < uncompressed.length; i++) {
98                      assertEquals(uncompressed[i], result[i]);
99                  }
100             } catch (final ImagingException ex) {
101                 Debug.debug(ex);
102                 fail();
103             }
104 
105             try {
106                 final byte[] compressed = T4AndT6Compression.compressT4_1D(uncompressed, 5, 2, true);
107                 final byte[] result = T4AndT6Compression.decompressT4_1D(compressed, 5, 2, true);
108                 assertEquals(uncompressed.length, result.length);
109                 for (int i = 0; i < uncompressed.length; i++) {
110                     assertEquals(uncompressed[i], result[i]);
111                 }
112             } catch (final ImagingException ex) {
113                 Debug.debug(ex);
114                 fail();
115             }
116 
117             try {
118                 final byte[] compressed = T4AndT6Compression.compressT4_1D(uncompressed, 5, 2, false);
119                 final byte[] result = T4AndT6Compression.decompressT4_1D(compressed, 5, 2, false);
120                 assertEquals(uncompressed.length, result.length);
121                 for (int i = 0; i < uncompressed.length; i++) {
122                     assertEquals(uncompressed[i], result[i]);
123                 }
124             } catch (final ImagingException ex) {
125                 Debug.debug(ex);
126                 fail();
127             }
128 
129             try {
130                 final byte[] compressed = T4AndT6Compression.compressT4_2D(uncompressed, 5, 2, true, 2);
131                 final byte[] result = T4AndT6Compression.decompressT4_2D(compressed, 5, 2, true);
132                 assertEquals(uncompressed.length, result.length);
133                 for (int i = 0; i < uncompressed.length; i++) {
134                     assertEquals(uncompressed[i], result[i]);
135                 }
136             } catch (final ImagingException ex) {
137                 Debug.debug(ex);
138                 fail();
139             }
140 
141             try {
142                 final byte[] compressed = T4AndT6Compression.compressT4_2D(uncompressed, 5, 2, false, 2);
143                 final byte[] result = T4AndT6Compression.decompressT4_2D(compressed, 5, 2, false);
144                 assertEquals(uncompressed.length, result.length);
145                 for (int i = 0; i < uncompressed.length; i++) {
146                     assertEquals(uncompressed[i], result[i]);
147                 }
148             } catch (final ImagingException ex) {
149                 Debug.debug(ex);
150                 fail();
151             }
152 
153             try {
154                 final byte[] compressed = T4AndT6Compression.compressT6(uncompressed, 5, 2);
155                 final byte[] result = T4AndT6Compression.decompressT6(compressed, 5, 2);
156                 assertEquals(uncompressed.length, result.length);
157                 for (int i = 0; i < uncompressed.length; i++) {
158                     assertEquals(uncompressed[i], result[i]);
159                 }
160             } catch (final ImagingException ex) {
161                 Debug.debug(ex);
162                 fail();
163             }
164         } while (nextCombination(combinations, 1));
165     }
166 
167     @Test
168     public void testAll5x2Images() {
169         final int[] combinations = new int[10];
170         final BufferedImage image = new BufferedImage(5, 2, BufferedImage.TYPE_INT_RGB);
171         do {
172             for (int x = 0; x < 5; x++) {
173                 if (combinations[x] == 0) {
174                     image.setRGB(x, 0, 0xFFFFFF);
175                 } else {
176                     image.setRGB(x, 0, 0);
177                 }
178             }
179             for (int x = 0; x < 5; x++) {
180                 if (combinations[5 + x] == 0) {
181                     image.setRGB(x, 1, 0xFFFFFF);
182                 } else {
183                     image.setRGB(x, 1, 0);
184                 }
185             }
186 
187             try {
188                 final TiffImagingParameters params = new TiffImagingParameters();
189                 params.setCompression(TiffConstants.COMPRESSION_CCITT_1D);
190                 final TiffImageParser tiffImageParser = new TiffImageParser();
191                 final byte[] compressed;
192                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
193                     tiffImageParser.writeImage(image, baos, params);
194                     compressed = baos.toByteArray();
195                 }
196                 final BufferedImage result = Imaging.getBufferedImage(compressed);
197                 compareImages(image, result);
198             } catch (final IOException ex) {
199                 Debug.debug(ex);
200                 fail();
201             }
202 
203             final TiffImageParser tiffImageParser = new TiffImageParser();
204 
205             try {
206                 final TiffImagingParameters params = new TiffImagingParameters();
207                 params.setCompression(TiffConstants.COMPRESSION_CCITT_GROUP_3);
208                 params.setT4Options(0);
209                 final byte[] compressed;
210                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
211                     tiffImageParser.writeImage(image, baos, params);
212                     compressed = baos.toByteArray();
213                 }
214                 final BufferedImage result = Imaging.getBufferedImage(compressed);
215                 compareImages(image, result);
216             } catch (final IOException ex) {
217                 Debug.debug(ex);
218                 fail();
219             }
220 
221             try {
222                 final TiffImagingParameters params = new TiffImagingParameters();
223                 params.setCompression(TiffConstants.COMPRESSION_CCITT_GROUP_3);
224                 params.setT4Options(4);
225                 final byte[] compressed;
226                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
227                     tiffImageParser.writeImage(image, baos, params);
228                     compressed = baos.toByteArray();
229                 }
230                 final BufferedImage result = Imaging.getBufferedImage(compressed);
231                 compareImages(image, result);
232             } catch (final IOException ex) {
233                 Debug.debug(ex);
234                 fail();
235             }
236 
237             try {
238                 final TiffImagingParameters params = new TiffImagingParameters();
239                 params.setCompression(TiffConstants.COMPRESSION_CCITT_GROUP_3);
240                 params.setT4Options(1);
241                 final byte[] compressed;
242                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
243                     tiffImageParser.writeImage(image, baos, params);
244                     compressed = baos.toByteArray();
245                 }
246                 final BufferedImage result = Imaging.getBufferedImage(compressed);
247                 compareImages(image, result);
248             } catch (final IOException ex) {
249                 Debug.debug(ex);
250                 fail();
251             }
252 
253             try {
254                 final TiffImagingParameters params = new TiffImagingParameters();
255                 params.setCompression(TiffConstants.COMPRESSION_CCITT_GROUP_3);
256                 params.setT4Options(5);
257                 final byte[] compressed;
258                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
259                     tiffImageParser.writeImage(image, baos, params);
260                     compressed = baos.toByteArray();
261                 }
262                 final BufferedImage result = Imaging.getBufferedImage(compressed);
263                 compareImages(image, result);
264             } catch (final IOException ex) {
265                 Debug.debug(ex);
266                 fail();
267             }
268 
269             try {
270                 final TiffImagingParameters params = new TiffImagingParameters();
271                 params.setCompression(TiffConstants.COMPRESSION_CCITT_GROUP_4);
272                 final byte[] compressed;
273                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
274                     tiffImageParser.writeImage(image, baos, params);
275                     compressed = baos.toByteArray();
276                 }
277                 final BufferedImage result = Imaging.getBufferedImage(compressed);
278                 compareImages(image, result);
279             } catch (final IOException ex) {
280                 Debug.debug(ex);
281                 fail();
282             }
283         } while (nextCombination(combinations, 1));
284     }
285 }