1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.formats.tiff.datareaders;
18
19 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_CCITT_1D;
20 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_3;
21 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_CCITT_GROUP_4;
22 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_DEFLATE_ADOBE;
23 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_DEFLATE_PKZIP;
24 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_LZW;
25 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_PACKBITS;
26 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_COMPRESSION_UNCOMPRESSED;
27 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T4_OPTIONS_2D;
28 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T4_OPTIONS_FILL;
29 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T4_OPTIONS_UNCOMPRESSED_MODE;
30 import static org.apache.commons.imaging.formats.tiff.constants.TiffConstants.TIFF_FLAG_T6_OPTIONS_UNCOMPRESSED_MODE;
31
32 import java.awt.Rectangle;
33 import java.io.ByteArrayInputStream;
34 import java.io.IOException;
35 import java.io.InputStream;
36 import java.nio.ByteOrder;
37 import java.util.Arrays;
38
39 import org.apache.commons.imaging.ImagingException;
40 import org.apache.commons.imaging.common.Allocator;
41 import org.apache.commons.imaging.common.ImageBuilder;
42 import org.apache.commons.imaging.common.PackBits;
43 import org.apache.commons.imaging.common.ZlibDeflate;
44 import org.apache.commons.imaging.formats.tiff.TiffDirectory;
45 import org.apache.commons.imaging.formats.tiff.TiffField;
46 import org.apache.commons.imaging.formats.tiff.TiffRasterData;
47 import org.apache.commons.imaging.formats.tiff.constants.TiffPlanarConfiguration;
48 import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
49 import org.apache.commons.imaging.formats.tiff.itu_t4.T4AndT6Compression;
50 import org.apache.commons.imaging.formats.tiff.photometricinterpreters.PhotometricInterpreter;
51 import org.apache.commons.imaging.mylzw.MyLzwDecompressor;
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 public abstract class ImageDataReader {
145
146 protected final TiffDirectory directory;
147 protected final PhotometricInterpreter photometricInterpreter;
148 private final int[] bitsPerSample;
149 protected final int bitsPerSampleLength;
150 private final int[] last;
151
152 protected final int predictor;
153 protected final int samplesPerPixel;
154 protected final int width;
155 protected final int height;
156 protected final int sampleFormat;
157
158 protected final TiffPlanarConfiguration planarConfiguration;
159
160 public ImageDataReader(final TiffDirectory directory, final PhotometricInterpreter photometricInterpreter, final int[] bitsPerSample, final int predictor,
161 final int samplesPerPixel, final int sampleFormat, final int width, final int height, final TiffPlanarConfiguration planarConfiguration) {
162 this.directory = directory;
163 this.photometricInterpreter = photometricInterpreter;
164 this.bitsPerSample = bitsPerSample;
165 this.bitsPerSampleLength = bitsPerSample.length;
166 this.samplesPerPixel = samplesPerPixel;
167 this.sampleFormat = sampleFormat;
168 this.predictor = predictor;
169 this.width = width;
170 this.height = height;
171 this.planarConfiguration = planarConfiguration;
172 last = Allocator.intArray(samplesPerPixel);
173
174 }
175
176 protected int[] applyPredictor(final int[] samples) {
177 if (predictor == 2) {
178
179 for (int i = 0; i < samples.length; i++) {
180 samples[i] = 0xff & samples[i] + last[i];
181 last[i] = samples[i];
182 }
183 }
184
185 return samples;
186 }
187
188 protected void applyPredictorToBlock(final int width, final int height, final int nSamplesPerPixel, final byte[] p) {
189 final int k = width * nSamplesPerPixel;
190 for (int i = 0; i < height; i++) {
191 final int j0 = i * k + nSamplesPerPixel;
192 final int j1 = (i + 1) * k;
193 for (int j = j0; j < j1; j++) {
194 p[j] += p[j - nSamplesPerPixel];
195 }
196 }
197 }
198
199 protected byte[] decompress(final byte[] compressedInput, final int compression, final int expectedSize, final int tileWidth, final int tileHeight)
200 throws ImagingException, IOException {
201 final TiffField fillOrderField = directory.findField(TiffTagConstants.TIFF_TAG_FILL_ORDER);
202 int fillOrder = TiffTagConstants.FILL_ORDER_VALUE_NORMAL;
203 if (fillOrderField != null) {
204 fillOrder = fillOrderField.getIntValue();
205 }
206 final byte[] compressedOrdered;
207 if (fillOrder == TiffTagConstants.FILL_ORDER_VALUE_NORMAL) {
208 compressedOrdered = compressedInput;
209
210 } else if (fillOrder == TiffTagConstants.FILL_ORDER_VALUE_REVERSED) {
211 compressedOrdered = new byte[compressedInput.length];
212 for (int i = 0; i < compressedInput.length; i++) {
213 compressedOrdered[i] = (byte) (Integer.reverse(0xff & compressedInput[i]) >>> 24);
214 }
215 } else {
216 throw new ImagingException("TIFF FillOrder=" + fillOrder + " is invalid");
217 }
218
219 switch (compression) {
220 case TIFF_COMPRESSION_UNCOMPRESSED:
221
222 return compressedOrdered;
223 case TIFF_COMPRESSION_CCITT_1D:
224
225 return T4AndT6Compression.decompressModifiedHuffman(compressedOrdered, tileWidth, tileHeight);
226 case TIFF_COMPRESSION_CCITT_GROUP_3: {
227 int t4Options = 0;
228 final TiffField field = directory.findField(TiffTagConstants.TIFF_TAG_T4_OPTIONS);
229 if (field != null) {
230 t4Options = field.getIntValue();
231 }
232 final boolean is2D = (t4Options & TIFF_FLAG_T4_OPTIONS_2D) != 0;
233 final boolean usesUncompressedMode = (t4Options & TIFF_FLAG_T4_OPTIONS_UNCOMPRESSED_MODE) != 0;
234 if (usesUncompressedMode) {
235 throw new ImagingException("T.4 compression with the uncompressed mode extension is not yet supported");
236 }
237 final boolean hasFillBitsBeforeEOL = (t4Options & TIFF_FLAG_T4_OPTIONS_FILL) != 0;
238 if (is2D) {
239 return T4AndT6Compression.decompressT4_2D(compressedOrdered, tileWidth, tileHeight, hasFillBitsBeforeEOL);
240 }
241 return T4AndT6Compression.decompressT4_1D(compressedOrdered, tileWidth, tileHeight, hasFillBitsBeforeEOL);
242 }
243 case TIFF_COMPRESSION_CCITT_GROUP_4: {
244 int t6Options = 0;
245 final TiffField field = directory.findField(TiffTagConstants.TIFF_TAG_T6_OPTIONS);
246 if (field != null) {
247 t6Options = field.getIntValue();
248 }
249 final boolean usesUncompressedMode = (t6Options & TIFF_FLAG_T6_OPTIONS_UNCOMPRESSED_MODE) != 0;
250 if (usesUncompressedMode) {
251 throw new ImagingException("T.6 compression with the uncompressed mode extension is not yet supported");
252 }
253 return T4AndT6Compression.decompressT6(compressedOrdered, tileWidth, tileHeight);
254 }
255 case TIFF_COMPRESSION_LZW: {
256 final InputStream is = new ByteArrayInputStream(compressedOrdered);
257 final int lzwMinimumCodeSize = 8;
258 return new MyLzwDecompressor(lzwMinimumCodeSize, ByteOrder.BIG_ENDIAN, true).decompress(is, expectedSize);
259 }
260
261
262 case TIFF_COMPRESSION_PACKBITS: {
263 return PackBits.decompress(compressedOrdered, expectedSize);
264 }
265
266
267 case TIFF_COMPRESSION_DEFLATE_ADOBE:
268 case TIFF_COMPRESSION_DEFLATE_PKZIP: {
269 return ZlibDeflate.decompress(compressedInput, expectedSize);
270 }
271
272 default:
273 throw new ImagingException("Tiff: unknown/unsupported compression: " + compression);
274 }
275 }
276
277
278
279
280
281
282
283
284 void getSamplesAsBytes(final BitInputStream bis, final int[] result) throws IOException {
285 for (int i = 0; i < bitsPerSample.length; i++) {
286 final int bits = bitsPerSample[i];
287 int sample = bis.readBits(bits);
288 if (bits < 8) {
289 final int sign = sample & 1;
290 sample = sample << 8 - bits;
291 if (sign > 0) {
292 sample = sample | (1 << 8 - bits) - 1;
293 }
294 } else if (bits > 8) {
295 sample = sample >> bits - 8;
296 }
297 result[i] = sample;
298 }
299 }
300
301
302
303
304
305
306
307 protected boolean isHomogenous(final int size) {
308 for (final int element : bitsPerSample) {
309 if (element != size) {
310 return false;
311 }
312 }
313 return true;
314 }
315
316
317
318
319
320
321
322
323
324
325
326 public abstract ImageBuilder readImageData(Rectangle subImageSpecification, boolean hasAlpha, boolean isAlphaPremultiplied)
327 throws IOException, ImagingException;
328
329
330
331
332
333
334
335
336
337
338 public abstract TiffRasterData readRasterData(Rectangle subImage) throws ImagingException, IOException;
339
340 protected void resetPredictor() {
341 Arrays.fill(last, 0);
342 }
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 void transferBlockToRaster(final int xBlock, final int yBlock, final int blockWidth, final int blockHeight, final int[] blockData, final int xRaster,
359 final int yRaster, final int rasterWidth, final int rasterHeight, final int samplesPerPixel, final float[] rasterData) {
360
361
362
363 int xR0 = xBlock - xRaster;
364 int yR0 = yBlock - yRaster;
365 int xR1 = xR0 + blockWidth;
366 int yR1 = yR0 + blockHeight;
367 if (xR0 < 0) {
368 xR0 = 0;
369 }
370 if (yR0 < 0) {
371 yR0 = 0;
372 }
373 if (xR1 > rasterWidth) {
374 xR1 = rasterWidth;
375 }
376 if (yR1 > rasterHeight) {
377 yR1 = rasterHeight;
378 }
379
380
381
382
383
384
385
386 int xB0 = xR0 + xRaster - xBlock;
387 int yB0 = yR0 + yRaster - yBlock;
388 if (xB0 < 0) {
389 xR0 -= xB0;
390 xB0 = 0;
391 }
392 if (yB0 < 0) {
393 yR0 -= yB0;
394 yB0 = 0;
395 }
396
397 int w = xR1 - xR0;
398 int h = yR1 - yR0;
399 if (w <= 0 || h <= 0) {
400
401
402
403
404 return;
405 }
406
407 if (w > blockWidth) {
408 w = blockWidth;
409 }
410 if (h > blockHeight) {
411 h = blockHeight;
412 }
413
414
415
416
417 if (samplesPerPixel == 1) {
418 for (int i = 0; i < h; i++) {
419 final int yR = yR0 + i;
420 final int yB = yB0 + i;
421 final int rOffset = yR * rasterWidth + xR0;
422 final int bOffset = yB * blockWidth + xB0;
423 for (int j = 0; j < w; j++) {
424 rasterData[rOffset + j] = Float.intBitsToFloat(blockData[bOffset + j]);
425 }
426 }
427 } else if (this.planarConfiguration == TiffPlanarConfiguration.CHUNKY) {
428
429
430
431 final int pixelsPerPlane = rasterWidth * rasterHeight;
432 for (int i = 0; i < h; i++) {
433 final int yR = yR0 + i;
434 final int yB = yB0 + i;
435 final int rOffset = yR * rasterWidth + xR0;
436 final int bOffset = yB * blockWidth + xB0;
437 for (int j = 0; j < w; j++) {
438 for (int k = 0; k < samplesPerPixel; k++) {
439 rasterData[k * pixelsPerPlane + rOffset + j] = Float.intBitsToFloat(blockData[(bOffset + j) * samplesPerPixel + k]);
440 }
441 }
442 }
443 } else {
444 for (int iPlane = 0; iPlane < samplesPerPixel; iPlane++) {
445 final int rPlanarOffset = iPlane * rasterWidth * rasterHeight;
446 final int bPlanarOffset = iPlane * blockWidth * blockHeight;
447 for (int i = 0; i < h; i++) {
448 final int yR = yR0 + i;
449 final int yB = yB0 + i;
450 final int rOffset = rPlanarOffset + yR * rasterWidth + xR0;
451 final int bOffset = bPlanarOffset + yB * blockWidth + xB0;
452 for (int j = 0; j < w; j++) {
453 rasterData[rOffset + j] = Float.intBitsToFloat(blockData[bOffset + j]);
454 }
455 }
456 }
457 }
458
459 }
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475 void transferBlockToRaster(final int xBlock, final int yBlock, final int blockWidth, final int blockHeight, final int[] blockData, final int xRaster,
476 final int yRaster, final int rasterWidth, final int rasterHeight, final int[] rasterData) {
477
478
479
480 int xR0 = xBlock - xRaster;
481 int yR0 = yBlock - yRaster;
482 int xR1 = xR0 + blockWidth;
483 int yR1 = yR0 + blockHeight;
484 if (xR0 < 0) {
485 xR0 = 0;
486 }
487 if (yR0 < 0) {
488 yR0 = 0;
489 }
490 if (xR1 > rasterWidth) {
491 xR1 = rasterWidth;
492 }
493 if (yR1 > rasterHeight) {
494 yR1 = rasterHeight;
495 }
496
497
498
499
500
501
502
503 int xB0 = xR0 + xRaster - xBlock;
504 int yB0 = yR0 + yRaster - yBlock;
505 if (xB0 < 0) {
506 xR0 -= xB0;
507 xB0 = 0;
508 }
509 if (yB0 < 0) {
510 yR0 -= yB0;
511 yB0 = 0;
512 }
513
514 int w = xR1 - xR0;
515 int h = yR1 - yR0;
516 if (w <= 0 || h <= 0) {
517
518
519
520
521 return;
522 }
523
524 if (w > blockWidth) {
525 w = blockWidth;
526 }
527 if (h > blockHeight) {
528 h = blockHeight;
529 }
530
531 for (int i = 0; i < h; i++) {
532 final int yR = yR0 + i;
533 final int yB = yB0 + i;
534 final int rOffset = yR * rasterWidth + xR0;
535 final int bOffset = yB * blockWidth + xB0;
536 System.arraycopy(blockData, bOffset, rasterData, rOffset, w);
537 }
538 }
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558 protected int[] unpackFloatingPointSamples(final int width, final int height, final int scanSize, final byte[] bytes, final int bitsPerPixel,
559 final ByteOrder byteOrder) throws ImagingException {
560 final int bitsPerSample = bitsPerPixel / samplesPerPixel;
561 final int bytesPerSample = bitsPerSample / 8;
562 final int bytesPerScan = scanSize * samplesPerPixel * bytesPerSample;
563 final int nBytes = bytesPerScan * height;
564 final int length = bytes.length < nBytes ? nBytes / bytesPerScan : height;
565 final int[] samples = Allocator.intArray(scanSize * samplesPerPixel * height);
566
567 if (predictor == TiffTagConstants.PREDICTOR_VALUE_FLOATING_POINT_DIFFERENCING) {
568
569
570
571 if (bitsPerPixel / samplesPerPixel != 32) {
572 throw new ImagingException(
573 "Imaging does not yet support floating-point data" + " with predictor type 3 for " + bitsPerPixel + " bits per sample");
574 }
575
576 if (planarConfiguration == TiffPlanarConfiguration.CHUNKY) {
577 final int bytesInRow = scanSize * 4 * samplesPerPixel;
578 for (int i = 0; i < length; i++) {
579 final int aOffset = i * bytesInRow;
580 final int bOffset = aOffset + scanSize * samplesPerPixel;
581 final int cOffset = bOffset + scanSize * samplesPerPixel;
582 final int dOffset = cOffset + scanSize * samplesPerPixel;
583
584
585
586 for (int j = 1; j < bytesInRow; j++) {
587 bytes[aOffset + j] += bytes[aOffset + j - 1];
588 }
589
590
591 int index = i * scanSize;
592 for (int j = 0; j < width * samplesPerPixel; j++) {
593 final int a = bytes[aOffset + j];
594 final int b = bytes[bOffset + j];
595 final int c = bytes[cOffset + j];
596 final int d = bytes[dOffset + j];
597
598
599 samples[index++] = (a & 0xff) << 24 | (b & 0xff) << 16 | (c & 0xff) << 8 | d & 0xff;
600 }
601 }
602 } else {
603 final int bytesInRow = scanSize * 4;
604 for (int iPlane = 0; iPlane < samplesPerPixel; iPlane++) {
605 final int planarIntOffset = iPlane * length * scanSize;
606 final int planarByteOffset = planarIntOffset * 4;
607
608 for (int i = 0; i < length; i++) {
609 final int aOffset = i * bytesInRow + planarByteOffset;
610 final int bOffset = aOffset + scanSize;
611 final int cOffset = bOffset + scanSize;
612 final int dOffset = cOffset + scanSize;
613
614
615
616 for (int j = 1; j < bytesInRow; j++) {
617 bytes[aOffset + j] += bytes[aOffset + j - 1];
618 }
619
620
621 int index = planarIntOffset + i * scanSize;
622 for (int j = 0; j < width; j++) {
623 final int a = bytes[aOffset + j];
624 final int b = bytes[bOffset + j];
625 final int c = bytes[cOffset + j];
626 final int d = bytes[dOffset + j];
627
628
629 samples[index++] = (a & 0xff) << 24 | (b & 0xff) << 16 | (c & 0xff) << 8 | d & 0xff;
630 }
631 }
632 }
633
634 }
635 return samples;
636 }
637
638
639 if (bitsPerSample == 64) {
640 int k = 0;
641 int index = 0;
642 for (int i = 0; i < length; i++) {
643 for (int j = 0; j < scanSize; j++) {
644 final long b0 = bytes[k++] & 0xffL;
645 final long b1 = bytes[k++] & 0xffL;
646 final long b2 = bytes[k++] & 0xffL;
647 final long b3 = bytes[k++] & 0xffL;
648 final long b4 = bytes[k++] & 0xffL;
649 final long b5 = bytes[k++] & 0xffL;
650 final long b6 = bytes[k++] & 0xffL;
651 final long b7 = bytes[k++] & 0xffL;
652 long sbits;
653 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
654 sbits = b7 << 56 | b6 << 48 | b5 << 40 | b4 << 32 | b3 << 24 | b2 << 16 | b1 << 8 | b0;
655
656 } else {
657 sbits = b0 << 56 | b1 << 48 | b2 << 40 | b3 << 32 | b4 << 24 | b5 << 16 | b6 << 8 | b7;
658 }
659
660
661
662
663 final float f = (float) Double.longBitsToDouble(sbits);
664 samples[index++] = Float.floatToRawIntBits(f);
665 }
666 }
667 } else if (bitsPerSample == 32) {
668 int k = 0;
669 int index = 0;
670 for (int i = 0; i < length; i++) {
671 for (int j = 0; j < scanSize * samplesPerPixel; j++) {
672 final int b0 = bytes[k++] & 0xff;
673 final int b1 = bytes[k++] & 0xff;
674 final int b2 = bytes[k++] & 0xff;
675 final int b3 = bytes[k++] & 0xff;
676 int sbits;
677 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
678 sbits = b3 << 24 | b2 << 16 | b1 << 8 | b0;
679
680 } else {
681 sbits = b0 << 24 | b1 << 16 | b2 << 8 | b3;
682 }
683
684
685
686
687 samples[index++] = sbits;
688 }
689 }
690 } else {
691 throw new ImagingException("Imaging does not support floating-point samples with " + bitsPerPixel + " bits per sample");
692 }
693
694 return samples;
695 }
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 protected int[] unpackIntSamples(final int width, final int height, final int scanSize, final byte[] bytes, final int predictor, final int bitsPerSample,
716 final ByteOrder byteOrder) {
717 final int bytesPerSample = bitsPerSample / 8;
718 final int nBytes = bytesPerSample * scanSize * height;
719 final int length = bytes.length < nBytes ? nBytes / scanSize : height;
720
721 final int[] samples = Allocator.intArray(scanSize * height);
722
723
724
725
726
727
728
729 final boolean useDifferencing = predictor == TiffTagConstants.PREDICTOR_VALUE_HORIZONTAL_DIFFERENCING;
730
731 for (int i = 0; i < length; i++) {
732 final int index = i * scanSize;
733 int offset = index * bytesPerSample;
734 if (bitsPerSample == 16) {
735 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
736 for (int j = 0; j < width; j++, offset += 2) {
737 samples[index + j] = bytes[offset + 1] << 8 | bytes[offset] & 0xff;
738 }
739 } else {
740 for (int j = 0; j < width; j++, offset += 2) {
741 samples[index + j] = bytes[offset] << 8 | bytes[offset + 1] & 0xff;
742 }
743 }
744 } else if (bitsPerSample == 32) {
745 if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
746 for (int j = 0; j < width; j++, offset += 4) {
747 samples[index + j] = bytes[offset + 3] << 24 | (bytes[offset + 2] & 0xff) << 16 | (bytes[offset + 1] & 0xff) << 8
748 | bytes[offset] & 0xff;
749 }
750 } else {
751 for (int j = 0; j < width; j++, offset += 4) {
752 samples[index + j] = bytes[offset] << 24 | (bytes[offset + 1] & 0xff) << 16 | (bytes[offset + 2] & 0xff) << 8
753 | bytes[offset + 3] & 0xff;
754 }
755 }
756 }
757 if (useDifferencing) {
758 for (int j = 1; j < width; j++) {
759 samples[index + j] += samples[index + j - 1];
760 }
761 }
762 }
763
764 return samples;
765 }
766 }