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.ImageFormats;
28  import org.apache.commons.imaging.ImageReadException;
29  import org.apache.commons.imaging.ImageWriteException;
30  import org.apache.commons.imaging.Imaging;
31  import org.apache.commons.imaging.common.itu_t4.T4AndT6Compression;
32  import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
33  import org.apache.commons.imaging.internal.Debug;
34  import org.junit.jupiter.api.Test;
35  
36  public class TiffCcittTest extends TiffBaseTest {
37  
38      @Test
39      public void testAll5x2Compressions() {
40          final byte[] uncompressed = new byte[2];
41          final int[] combinations = new int[10];
42          do {
43              for (int x = 0; x < 5; x++) {
44                  if (combinations[x] != 0) {
45                      uncompressed[0] |= (0x80 >>> x);
46                  }
47              }
48              for (int x = 0; x < 5; x++) {
49                  if (combinations[5 + x] != 0) {
50                      uncompressed[1] |= (0x80 >>> x);
51                  }
52              }
53  
54              try {
55                  final byte[] compressed = T4AndT6Compression.compressModifiedHuffman(
56                          uncompressed, 5, 2);
57                  final byte[] result = T4AndT6Compression.decompressModifiedHuffman(
58                          compressed, 5, 2);
59                  assertEquals(uncompressed.length, result.length);
60                  for (int i = 0; i < uncompressed.length; i++) {
61                      assertEquals(uncompressed[i], result[i]);
62                  }
63              } catch (final ImageWriteException | ImageReadException ex) {
64                  Debug.debug(ex);
65                  fail();
66              }
67  
68              try {
69                  final byte[] compressed = T4AndT6Compression.compressT4_1D(
70                          uncompressed, 5, 2, true);
71                  final byte[] result = T4AndT6Compression.decompressT4_1D(compressed,
72                          5, 2, true);
73                  assertEquals(uncompressed.length, result.length);
74                  for (int i = 0; i < uncompressed.length; i++) {
75                      assertEquals(uncompressed[i], result[i]);
76                  }
77              } catch (final ImageWriteException | ImageReadException ex) {
78                  Debug.debug(ex);
79                  fail();
80              }
81  
82              try {
83                  final byte[] compressed = T4AndT6Compression.compressT4_1D(
84                          uncompressed, 5, 2, false);
85                  final byte[] result = T4AndT6Compression.decompressT4_1D(compressed,
86                          5, 2, false);
87                  assertEquals(uncompressed.length, result.length);
88                  for (int i = 0; i < uncompressed.length; i++) {
89                      assertEquals(uncompressed[i], result[i]);
90                  }
91              } catch (final ImageWriteException | ImageReadException ex) {
92                  Debug.debug(ex);
93                  fail();
94              }
95  
96              try {
97                  final byte[] compressed = T4AndT6Compression.compressT4_2D(
98                          uncompressed, 5, 2, true, 2);
99                  final byte[] result = T4AndT6Compression.decompressT4_2D(compressed,
100                         5, 2, true);
101                 assertEquals(uncompressed.length, result.length);
102                 for (int i = 0; i < uncompressed.length; i++) {
103                     assertEquals(uncompressed[i], result[i]);
104                 }
105             } catch (final ImageWriteException | ImageReadException ex) {
106                 Debug.debug(ex);
107                 fail();
108             }
109 
110             try {
111                 final byte[] compressed = T4AndT6Compression.compressT4_2D(
112                         uncompressed, 5, 2, false, 2);
113                 final byte[] result = T4AndT6Compression.decompressT4_2D(compressed,
114                         5, 2, false);
115                 assertEquals(uncompressed.length, result.length);
116                 for (int i = 0; i < uncompressed.length; i++) {
117                     assertEquals(uncompressed[i], result[i]);
118                 }
119             } catch (final ImageWriteException | ImageReadException ex) {
120                 Debug.debug(ex);
121                 fail();
122             }
123 
124             try {
125                 final byte[] compressed = T4AndT6Compression.compressT6(uncompressed,
126                         5, 2);
127                 final byte[] result = T4AndT6Compression.decompressT6(compressed, 5,
128                         2);
129                 assertEquals(uncompressed.length, result.length);
130                 for (int i = 0; i < uncompressed.length; i++) {
131                     assertEquals(uncompressed[i], result[i]);
132                 }
133             } catch (final ImageWriteException | ImageReadException ex) {
134                 Debug.debug(ex);
135                 fail();
136             }
137         } while (nextCombination(combinations, 1));
138     }
139 
140     @Test
141     public void testAll5x2Images() {
142         final int[] combinations = new int[10];
143         final BufferedImage image = new BufferedImage(5, 2,
144                 BufferedImage.TYPE_INT_RGB);
145         do {
146             for (int x = 0; x < 5; x++) {
147                 if (combinations[x] == 0) {
148                     image.setRGB(x, 0, 0xFFFFFF);
149                 } else {
150                     image.setRGB(x, 0, 0);
151                 }
152             }
153             for (int x = 0; x < 5; x++) {
154                 if (combinations[5 + x] == 0) {
155                     image.setRGB(x, 1, 0xFFFFFF);
156                 } else {
157                     image.setRGB(x, 1, 0);
158                 }
159             }
160 
161             try {
162                 final TiffImagingParameters params = new TiffImagingParameters();
163                 params.setCompression(TiffConstants.TIFF_COMPRESSION_CCITT_1D);
164                 final TiffImageParser tiffImageParser = new TiffImageParser();
165                 final byte[] compressed;
166                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
167                     tiffImageParser.writeImage(image, baos, params);
168                     compressed = baos.toByteArray();
169                 }
170                 final BufferedImage result = Imaging.getBufferedImage(compressed);
171                 compareImages(image, result);
172             } catch (final ImageWriteException | ImageReadException | IOException ex) {
173                 Debug.debug(ex);
174                 fail();
175             }
176 
177             final TiffImageParser tiffImageParser = new TiffImageParser();
178 
179             try {
180                 final TiffImagingParameters params = new TiffImagingParameters();
181                 params.setCompression(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_3);
182                 params.setT4Options(0);
183                 final byte[] compressed;
184                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
185                     tiffImageParser.writeImage(image, baos, params);
186                     compressed = baos.toByteArray();
187                 }
188                 final BufferedImage result = Imaging.getBufferedImage(compressed);
189                 compareImages(image, result);
190             } catch (final ImageWriteException | ImageReadException | IOException ex) {
191                 Debug.debug(ex);
192                 fail();
193             }
194 
195             try {
196                 final TiffImagingParameters params = new TiffImagingParameters();
197                 params.setCompression(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_3);
198                 params.setT4Options(4);
199                 final byte[] compressed;
200                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
201                     tiffImageParser.writeImage(image, baos, params);
202                     compressed = baos.toByteArray();
203                 }
204                 final BufferedImage result = Imaging.getBufferedImage(compressed);
205                 compareImages(image, result);
206             } catch (final ImageWriteException | ImageReadException | IOException ex) {
207                 Debug.debug(ex);
208                 fail();
209             }
210 
211             try {
212                 final TiffImagingParameters params = new TiffImagingParameters();
213                 params.setCompression(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_3);
214                 params.setT4Options(1);
215                 final byte[] compressed;
216                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
217                     tiffImageParser.writeImage(image, baos, params);
218                     compressed = baos.toByteArray();
219                 }
220                 final BufferedImage result = Imaging.getBufferedImage(compressed);
221                 compareImages(image, result);
222             } catch (final ImageWriteException | ImageReadException | IOException ex) {
223                 Debug.debug(ex);
224                 fail();
225             }
226 
227             try {
228                 final TiffImagingParameters params = new TiffImagingParameters();
229                 params.setCompression(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_3);
230                 params.setT4Options(5);
231                 final byte[] compressed;
232                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
233                     tiffImageParser.writeImage(image, baos, params);
234                     compressed = baos.toByteArray();
235                 }
236                 final BufferedImage result = Imaging.getBufferedImage(compressed);
237                 compareImages(image, result);
238             } catch (final ImageWriteException | ImageReadException | IOException ex) {
239                 Debug.debug(ex);
240                 fail();
241             }
242 
243             try {
244                 final TiffImagingParameters params = new TiffImagingParameters();
245                 params.setCompression(TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4);
246                 final byte[] compressed;
247                 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
248                     tiffImageParser.writeImage(image, baos, params);
249                     compressed = baos.toByteArray();
250                 }
251                 final BufferedImage result = Imaging.getBufferedImage(compressed);
252                 compareImages(image, result);
253             } catch (final ImageWriteException | ImageReadException | IOException ex) {
254                 Debug.debug(ex);
255                 fail();
256             }
257         } while (nextCombination(combinations, 1));
258     }
259 
260     /**
261      * Generates the next combination of elements in the sequence array, with
262      * each element having a maximum value of max. Initially, the sequence
263      * should be set to minimum values of each element.
264      *
265      * @param sequence
266      *            the array of elements to update
267      * @param max
268      *            the maximum value of each element in the sequence
269      * @return false if there is no more combinations (ie. nothing was done),
270      *         true otherwise
271      */
272     private static boolean nextCombination(final int[] sequence, final int max) {
273         int i;
274         for (i = 0; i < sequence.length; i++) {
275             if (sequence[i] != max) {
276                 sequence[i]++;
277                 break;
278             }
279             sequence[i] = 0;
280         }
281         return i < sequence.length;
282     }
283 
284     private void compareImages(final BufferedImage a, final BufferedImage b) {
285         assertEquals(a.getWidth(), b.getWidth());
286         assertEquals(a.getHeight(), b.getHeight());
287 
288         for (int x = 0; x < a.getWidth(); x++) {
289             for (int y = 0; y < a.getHeight(); y++) {
290                 final int a_argb = a.getRGB(x, y);
291                 final int b_argb = b.getRGB(x, y);
292                 if (a_argb != b_argb) {
293                     Debug.debug("width: " + a.getWidth());
294                     Debug.debug("height: " + a.getHeight());
295                     Debug.debug("x: " + x);
296                     Debug.debug("y: " + y);
297                     Debug.debug("a_argb: " + a_argb + " (0x" + Integer.toHexString(a_argb) + ")");
298                     Debug.debug("b_argb: " + b_argb + " (0x" + Integer.toHexString(b_argb) + ")");
299                 }
300                 assertEquals(a_argb, b_argb);
301             }
302         }
303     }
304 }