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 TiffBaseTest {
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 = 0;
78 int clearCode, eoiCode;
79
80 @Override
81 public void code(final int code) {
82 if (DEBUG) {
83 if (code == clearCode) {
84 Debug.debug("clearCode: " + index + "/" + codes.size());
85 Debug.debug();
86 }
87 if (code == eoiCode) {
88 Debug.debug("eoiCode: " + index + "/" + codes.size());
89 Debug.debug();
90 }
91 }
92 final Integer expectedCode = codes.get(index++);
93 if (code != expectedCode) {
94 Debug.debug("bad code: " + index + "/" + codes.size());
95 Debug.debug("code: " + code + " (0x" + Integer.toHexString(code) + ") " + Integer.toBinaryString(code));
96 Debug.debug("expected: " + expectedCode + " (0x" + Integer.toHexString(expectedCode) + ") " + Integer.toBinaryString(expectedCode));
97 Debug.debug("clearCode: " + clearCode + " (0x" + Integer.toHexString(clearCode) + ") " + Integer.toBinaryString(clearCode));
98 Debug.debug("eoiCode: " + eoiCode + " (0x" + Integer.toHexString(eoiCode) + ") " + Integer.toBinaryString(eoiCode));
99 Debug.debug();
100 }
101 }
102
103 @Override
104 public void init(final int clearCode, final int eoiCode) {
105 this.clearCode = clearCode;
106 this.eoiCode = eoiCode;
107 }
108
109 };
110 final InputStream is = new ByteArrayInputStream(compressed);
111 final MyLzwDecompressor decompressor = new MyLzwDecompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, decompressionListener);
112 final byte[] decompressed = decompressor.decompress(is, src.length);
113
114 assertEquals(src.length, decompressed.length);
115 for (int i = 0; i < src.length; i++) {
116 assertEquals(src[i], decompressed[i]);
117 }
118 }
119
120 private void decompressRoundtripAndValidate(final byte[] src) throws IOException, ImagingException {
121 Debug.debug();
122 Debug.debug("roundtripAndValidate: " + src.length);
123 Debug.debug();
124
125 final int LZW_MINIMUM_CODE_SIZE = 8;
126 final List<Integer> codes = new ArrayList<>();
127
128 final MyLzwDecompressor.Listener decompressionListener = new MyLzwDecompressor.Listener() {
129
130 @Override
131 public void code(final int code) {
132 Debug.debug("listener code: " + code + " (0x" + Integer.toHexString(code) + ") " + Integer.toBinaryString(code) + ", index: " + codes.size());
133 codes.add(code);
134 }
135
136 @Override
137 public void init(final int clearCode, final int eoiCode) {
138 }
139
140 };
141 final InputStream is = new ByteArrayInputStream(src);
142 final MyLzwDecompressor decompressor = new MyLzwDecompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, decompressionListener);
143 final byte[] decompressed = decompressor.decompress(is, src.length);
144
145 final MyLzwCompressor.Listener compressionListener = new MyLzwCompressor.Listener() {
146
147 int clearCode, eoiCode;
148
149 int index = 0;
150
151 @Override
152 public void clearCode(final int code) {
153 code(code);
154 }
155
156 private void code(final int code) {
157
158 if (code == clearCode) {
159 Debug.debug("clearCode: " + index + "/" + codes.size());
160 Debug.debug();
161 }
162 if (code == eoiCode) {
163 Debug.debug("eoiCode: " + index + "/" + codes.size());
164 Debug.debug();
165 }
166 final Integer expectedCode = codes.get(index++);
167 if (code != expectedCode) {
168 Debug.debug("bad code: " + index + "/" + codes.size());
169 Debug.debug("code: " + code + " (0x" + Integer.toHexString(code) + ") " + Integer.toBinaryString(code));
170 Debug.debug("expected: " + expectedCode + " (0x" + Integer.toHexString(expectedCode) + ") " + Integer.toBinaryString(expectedCode));
171 Debug.debug("clearCode: " + clearCode + " (0x" + Integer.toHexString(clearCode) + ") " + Integer.toBinaryString(clearCode));
172 Debug.debug("eoiCode: " + eoiCode + " (0x" + Integer.toHexString(eoiCode) + ") " + Integer.toBinaryString(eoiCode));
173 Debug.debug();
174 }
175 }
176
177 @Override
178 public void dataCode(final int code) {
179 code(code);
180 }
181
182 @Override
183 public void eoiCode(final int code) {
184 code(code);
185 }
186
187 @Override
188 public void init(final int clearCode, final int eoiCode) {
189 this.clearCode = clearCode;
190 this.eoiCode = eoiCode;
191 }
192
193 };
194
195 final MyLzwCompressor compressor = new MyLzwCompressor(LZW_MINIMUM_CODE_SIZE, ByteOrder.BIG_ENDIAN, true, compressionListener);
196 final byte[] compressed = compressor.compress(decompressed);
197
198 assertEquals(src.length, compressed.length);
199 for (int i = 0; i < src.length; i++) {
200 assertEquals(src[i], compressed[i]);
201 }
202 }
203
204 @Test
205 public void testMedium() throws Exception {
206 final int LENGTH = 1024 * 32;
207 final byte[] bytes = new byte[LENGTH];
208 for (int modulator = 1; modulator < 255; modulator += 3) {
209 for (int i = 0; i < LENGTH; i++) {
210 bytes[i] = (byte) (0xff & i % modulator);
211 }
212
213 compressRoundtripAndValidate(bytes);
214 }
215 }
216
217 @Disabled
218 @Test
219 public void testTiffImageData() throws IOException, ImagingException {
220 final List<File> images = getTiffImages();
221 for (final File image : images) {
222
223 Debug.debug("imageFile", image);
224
225 final ByteSource byteSource = ByteSource.file(image);
226 final List<byte[]> data = new TiffImageParser().collectRawImageData(byteSource, new TiffImagingParameters());
227
228 for (final byte[] bytes : data) {
229 decompressRoundtripAndValidate(bytes);
230 }
231 }
232 }
233
234 @Test
235 public void testTrivial() throws Exception {
236 final byte[] bytes = { 0, };
237 compressRoundtripAndValidate(bytes);
238 }
239
240 }