1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.imaging.formats.tiff;
19
20 import static org.junit.jupiter.api.Assertions.assertEquals;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.nio.ByteOrder;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.apache.commons.imaging.ImagingException;
31 import org.apache.commons.imaging.bytesource.ByteSource;
32 import org.apache.commons.imaging.internal.Debug;
33 import org.apache.commons.imaging.mylzw.MyLzwCompressor;
34 import org.apache.commons.imaging.mylzw.MyLzwDecompressor;
35 import org.junit.jupiter.api.Disabled;
36 import org.junit.jupiter.api.Test;
37
38 public class TiffLzwTest extends AbstractTiffTest {
39
40 private void compressRoundtripAndValidate(final byte[] src) throws IOException, ImagingException {
41 final boolean DEBUG = false;
42
43 if (DEBUG) {
44 Debug.debug();
45 Debug.debug("roundtripAndValidate: " + src.length);
46 Debug.debug();
47 }
48
49 final int LZW_MINIMUM_CODE_SIZE = 8;
50 final List<Integer> codes = new ArrayList<>();
51 final MyLzwCompressor.Listener compressionListener = new MyLzwCompressor.Listener() {
52 @Override
53 public void clearCode(final int code) {
54 codes.add(code);
55 }
56
57 @Override
58 public void dataCode(final int code) {
59 codes.add(code);
60 }
61
62 @Override
63 public void eoiCode(final int code) {
64 codes.add(code);
65 }
66
67 @Override
68 public void init(final int clearCode, final int eoiCode) {
69 }
70 };
71
72 final MyLzwCompressor compressor = new MyLzwCompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, compressionListener);
73 final byte[] compressed = compressor.compress(src);
74
75 final MyLzwDecompressor.Listener decompressionListener = new MyLzwDecompressor.Listener() {
76
77 int index;
78 int clearCode;
79 int eoiCode;
80
81 @Override
82 public void code(final int code) {
83 if (DEBUG) {
84 if (code == clearCode) {
85 Debug.debug("clearCode: " + index + "/" + codes.size());
86 Debug.debug();
87 }
88 if (code == eoiCode) {
89 Debug.debug("eoiCode: " + index + "/" + codes.size());
90 Debug.debug();
91 }
92 }
93 final Integer expectedCode = codes.get(index++);
94 if (code != expectedCode) {
95 Debug.debug("bad code: " + index + "/" + codes.size());
96 Debug.debug("code: " + code + " (0x" + Integer.toHexString(code) + ") " + Integer.toBinaryString(code));
97 Debug.debug("expected: " + expectedCode + " (0x" + Integer.toHexString(expectedCode) + ") " + Integer.toBinaryString(expectedCode));
98 Debug.debug("clearCode: " + clearCode + " (0x" + Integer.toHexString(clearCode) + ") " + Integer.toBinaryString(clearCode));
99 Debug.debug("eoiCode: " + eoiCode + " (0x" + Integer.toHexString(eoiCode) + ") " + Integer.toBinaryString(eoiCode));
100 Debug.debug();
101 }
102 }
103
104 @Override
105 public void init(final int clearCode, final int eoiCode) {
106 this.clearCode = clearCode;
107 this.eoiCode = eoiCode;
108 }
109
110 };
111 final InputStream is = new ByteArrayInputStream(compressed);
112 final MyLzwDecompressor decompressor = new MyLzwDecompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, decompressionListener);
113 final byte[] decompressed = decompressor.decompress(is, src.length);
114
115 assertEquals(src.length, decompressed.length);
116 for (int i = 0; i < src.length; i++) {
117 assertEquals(src[i], decompressed[i]);
118 }
119 }
120
121 private void decompressRoundtripAndValidate(final byte[] src) throws IOException, ImagingException {
122 Debug.debug();
123 Debug.debug("roundtripAndValidate: " + src.length);
124 Debug.debug();
125
126 final int LZW_MINIMUM_CODE_SIZE = 8;
127 final List<Integer> codes = new ArrayList<>();
128
129 final MyLzwDecompressor.Listener decompressionListener = new MyLzwDecompressor.Listener() {
130
131 @Override
132 public void code(final int code) {
133 Debug.debug("listener code: " + code + " (0x" + Integer.toHexString(code) + ") " + Integer.toBinaryString(code) + ", index: " + codes.size());
134 codes.add(code);
135 }
136
137 @Override
138 public void init(final int clearCode, final int eoiCode) {
139 }
140
141 };
142 final InputStream is = new ByteArrayInputStream(src);
143 final MyLzwDecompressor decompressor = new MyLzwDecompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, decompressionListener);
144 final byte[] decompressed = decompressor.decompress(is, src.length);
145
146 final MyLzwCompressor.Listener compressionListener = new MyLzwCompressor.Listener() {
147
148 int clearCode;
149 int eoiCode;
150 int index;
151
152 @Override
153 public void clearCode(final int code) {
154 code(code);
155 }
156
157 private void code(final int code) {
158
159 if (code == clearCode) {
160 Debug.debug("clearCode: " + index + "/" + codes.size());
161 Debug.debug();
162 }
163 if (code == eoiCode) {
164 Debug.debug("eoiCode: " + index + "/" + codes.size());
165 Debug.debug();
166 }
167 final Integer expectedCode = codes.get(index++);
168 if (code != expectedCode) {
169 Debug.debug("bad code: " + index + "/" + codes.size());
170 Debug.debug("code: " + code + " (0x" + Integer.toHexString(code) + ") " + Integer.toBinaryString(code));
171 Debug.debug("expected: " + expectedCode + " (0x" + Integer.toHexString(expectedCode) + ") " + Integer.toBinaryString(expectedCode));
172 Debug.debug("clearCode: " + clearCode + " (0x" + Integer.toHexString(clearCode) + ") " + Integer.toBinaryString(clearCode));
173 Debug.debug("eoiCode: " + eoiCode + " (0x" + Integer.toHexString(eoiCode) + ") " + Integer.toBinaryString(eoiCode));
174 Debug.debug();
175 }
176 }
177
178 @Override
179 public void dataCode(final int code) {
180 code(code);
181 }
182
183 @Override
184 public void eoiCode(final int code) {
185 code(code);
186 }
187
188 @Override
189 public void init(final int clearCode, final int eoiCode) {
190 this.clearCode = clearCode;
191 this.eoiCode = eoiCode;
192 }
193
194 };
195
196 final MyLzwCompressor compressor = new MyLzwCompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, compressionListener);
197 final byte[] compressed = compressor.compress(decompressed);
198
199 assertEquals(src.length, compressed.length);
200 for (int i = 0; i < src.length; i++) {
201 assertEquals(src[i], compressed[i]);
202 }
203 }
204
205 @Test
206 public void testMedium() throws Exception {
207 final int LENGTH = 1024 * 32;
208 final byte[] bytes = new byte[LENGTH];
209 for (int modulator = 1; modulator < 255; modulator += 3) {
210 for (int i = 0; i < LENGTH; i++) {
211 bytes[i] = (byte) (0xff & i % modulator);
212 }
213
214 compressRoundtripAndValidate(bytes);
215 }
216 }
217
218 @Disabled
219 @Test
220 public void testTiffImageData() throws IOException, ImagingException {
221 final List<File> images = getTiffImages();
222 for (final File image : images) {
223
224 Debug.debug("imageFile", image);
225
226 final ByteSource byteSource = ByteSource.file(image);
227 final List<byte[]> data = new TiffImageParser().collectRawImageData(byteSource, new TiffImagingParameters());
228
229 for (final byte[] bytes : data) {
230 decompressRoundtripAndValidate(bytes);
231 }
232 }
233 }
234
235 @Test
236 public void testTrivial() throws Exception {
237 final byte[] bytes = { 0, };
238 compressRoundtripAndValidate(bytes);
239 }
240
241 }