1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.imaging.formats.tiff;
18
19 import java.awt.image.BufferedImage;
20 import java.io.IOException;
21 import java.nio.ByteOrder;
22 import java.util.ArrayList;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26
27 import org.apache.commons.imaging.ImagingException;
28 import org.apache.commons.imaging.common.Allocator;
29 import org.apache.commons.imaging.common.ByteConversions;
30 import org.apache.commons.imaging.common.RationalNumber;
31 import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
32 import org.apache.commons.imaging.formats.tiff.constants.TiffDirectoryConstants;
33 import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
34 import org.apache.commons.imaging.formats.tiff.fieldtypes.AbstractFieldType;
35 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo;
36 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoAscii;
37 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoByte;
38 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoBytes;
39 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoDouble;
40 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoDoubles;
41 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoFloat;
42 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoFloats;
43 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoGpsText;
44 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoLong;
45 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoLongs;
46 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoRational;
47 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoRationals;
48 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSByte;
49 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSBytes;
50 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSLong;
51 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSLongs;
52 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSRational;
53 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSRationals;
54 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSShort;
55 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSShorts;
56 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShort;
57 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShortOrLong;
58 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShorts;
59 import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoXpString;
60
61
62
63
64
65 public class TiffDirectory extends AbstractTiffElement implements Iterable<TiffField> {
66
67 public static final class ImageDataElement extends AbstractTiffElement {
68 public ImageDataElement(final long offset, final int length) {
69 super(offset, length);
70 }
71
72 @Override
73 public String getElementDescription() {
74 return "ImageDataElement";
75 }
76 }
77
78 public static String description(final int type) {
79 switch (type) {
80 case TiffDirectoryConstants.DIRECTORY_TYPE_UNKNOWN:
81 return "Unknown";
82 case TiffDirectoryConstants.DIRECTORY_TYPE_ROOT:
83 return "Root";
84 case TiffDirectoryConstants.DIRECTORY_TYPE_SUB:
85 return "Sub";
86 case TiffDirectoryConstants.DIRECTORY_TYPE_THUMBNAIL:
87 return "Thumbnail";
88 case TiffDirectoryConstants.DIRECTORY_TYPE_EXIF:
89 return "Exif";
90 case TiffDirectoryConstants.DIRECTORY_TYPE_GPS:
91 return "Gps";
92 case TiffDirectoryConstants.DIRECTORY_TYPE_INTEROPERABILITY:
93 return "Interoperability";
94 default:
95 return "Bad Type";
96 }
97 }
98
99 private final List<TiffField> entries;
100
101
102
103
104
105 private final ByteOrder headerByteOrder;
106
107 private JpegImageData jpegImageData;
108
109 private final long nextDirectoryOffset;
110
111 private AbstractTiffImageData abstractTiffImageData;
112
113 public final int type;
114
115 public TiffDirectory(final int type, final List<TiffField> entries, final long offset, final long nextDirectoryOffset, final ByteOrder byteOrder) {
116 super(offset,
117 TiffConstants.DIRECTORY_HEADER_LENGTH + entries.size() * TiffConstants.ENTRY_LENGTH + TiffConstants.DIRECTORY_FOOTER_LENGTH);
118
119 this.type = type;
120 this.entries = Collections.unmodifiableList(entries);
121 this.nextDirectoryOffset = nextDirectoryOffset;
122 this.headerByteOrder = byteOrder;
123 }
124
125 public String description() {
126 return description(type);
127 }
128
129 public void dump() {
130 entries.forEach(TiffField::dump);
131 }
132
133 public TiffField findField(final TagInfo tag) throws ImagingException {
134 final boolean failIfMissing = false;
135 return findField(tag, failIfMissing);
136 }
137
138 public TiffField findField(final TagInfo tag, final boolean failIfMissing) throws ImagingException {
139 for (final TiffField field : entries) {
140 if (field.getTag() == tag.tag) {
141 return field;
142 }
143 }
144
145 if (failIfMissing) {
146 throw new ImagingException("Missing expected field: " + tag.getDescription());
147 }
148
149 return null;
150 }
151
152
153
154
155
156
157 public ByteOrder getByteOrder() {
158 return headerByteOrder;
159 }
160
161 public List<TiffField> getDirectoryEntries() {
162 return new ArrayList<>(entries);
163 }
164
165 @Override
166 public String getElementDescription() {
167 long entryOffset = offset + TiffConstants.DIRECTORY_HEADER_LENGTH;
168
169 final StringBuilder result = new StringBuilder();
170 for (final TiffField entry : entries) {
171 result.append(String.format("\t[%d]: %s (%d, 0x%x), %s, %d: %s%n", entryOffset, entry.getTagInfo().name, entry.getTag(), entry.getTag(),
172 entry.getFieldType().getName(), entry.getBytesLength(), entry.getValueDescription()));
173
174 entryOffset += TiffConstants.ENTRY_LENGTH;
175 }
176 return result.toString();
177 }
178
179 public Object getFieldValue(final TagInfo tag) throws ImagingException {
180 final TiffField field = findField(tag);
181 if (field == null) {
182 return null;
183 }
184 return field.getValue();
185 }
186
187 public String[] getFieldValue(final TagInfoAscii tag, final boolean mustExist) throws ImagingException {
188 final TiffField field = findField(tag);
189 if (field == null) {
190 if (mustExist) {
191 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
192 }
193 return null;
194 }
195 if (!tag.dataTypes.contains(field.getFieldType())) {
196 if (mustExist) {
197 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
198 }
199 return null;
200 }
201 final byte[] bytes = field.getByteArrayValue();
202 return tag.getValue(field.getByteOrder(), bytes);
203 }
204
205 public byte getFieldValue(final TagInfoByte tag) throws ImagingException {
206 final TiffField field = findField(tag);
207 if (field == null) {
208 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
209 }
210 if (!tag.dataTypes.contains(field.getFieldType())) {
211 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
212 }
213 if (field.getCount() != 1) {
214 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
215 }
216 return field.getByteArrayValue()[0];
217 }
218
219 public byte[] getFieldValue(final TagInfoBytes tag, final boolean mustExist) throws ImagingException {
220 final TiffField field = findField(tag);
221 if (field == null) {
222 if (mustExist) {
223 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
224 }
225 return null;
226 }
227 if (!tag.dataTypes.contains(field.getFieldType())) {
228 if (mustExist) {
229 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
230 }
231 return null;
232 }
233 return field.getByteArrayValue();
234 }
235
236 public double getFieldValue(final TagInfoDouble tag) throws ImagingException {
237 final TiffField field = findField(tag);
238 if (field == null) {
239 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
240 }
241 if (!tag.dataTypes.contains(field.getFieldType())) {
242 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
243 }
244 if (field.getCount() != 1) {
245 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
246 }
247 final byte[] bytes = field.getByteArrayValue();
248 return tag.getValue(field.getByteOrder(), bytes);
249 }
250
251 public double[] getFieldValue(final TagInfoDoubles tag, final boolean mustExist) throws ImagingException {
252 final TiffField field = findField(tag);
253 if (field == null) {
254 if (mustExist) {
255 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
256 }
257 return null;
258 }
259 if (!tag.dataTypes.contains(field.getFieldType())) {
260 if (mustExist) {
261 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
262 }
263 return null;
264 }
265 final byte[] bytes = field.getByteArrayValue();
266 return tag.getValue(field.getByteOrder(), bytes);
267 }
268
269 public float getFieldValue(final TagInfoFloat tag) throws ImagingException {
270 final TiffField field = findField(tag);
271 if (field == null) {
272 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
273 }
274 if (!tag.dataTypes.contains(field.getFieldType())) {
275 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
276 }
277 if (field.getCount() != 1) {
278 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
279 }
280 final byte[] bytes = field.getByteArrayValue();
281 return tag.getValue(field.getByteOrder(), bytes);
282 }
283
284 public float[] getFieldValue(final TagInfoFloats tag, final boolean mustExist) throws ImagingException {
285 final TiffField field = findField(tag);
286 if (field == null) {
287 if (mustExist) {
288 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
289 }
290 return null;
291 }
292 if (!tag.dataTypes.contains(field.getFieldType())) {
293 if (mustExist) {
294 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
295 }
296 return null;
297 }
298 final byte[] bytes = field.getByteArrayValue();
299 return tag.getValue(field.getByteOrder(), bytes);
300 }
301
302 public String getFieldValue(final TagInfoGpsText tag, final boolean mustExist) throws ImagingException {
303 final TiffField field = findField(tag);
304 if (field == null) {
305 if (mustExist) {
306 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
307 }
308 return null;
309 }
310 return tag.getValue(field);
311 }
312
313 public int getFieldValue(final TagInfoLong tag) throws ImagingException {
314 final TiffField field = findField(tag);
315 if (field == null) {
316 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
317 }
318 if (!tag.dataTypes.contains(field.getFieldType())) {
319 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
320 }
321 if (field.getCount() != 1) {
322 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
323 }
324 final byte[] bytes = field.getByteArrayValue();
325 return tag.getValue(field.getByteOrder(), bytes);
326 }
327
328 public int[] getFieldValue(final TagInfoLongs tag, final boolean mustExist) throws ImagingException {
329 final TiffField field = findField(tag);
330 if (field == null) {
331 if (mustExist) {
332 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
333 }
334 return null;
335 }
336 if (!tag.dataTypes.contains(field.getFieldType())) {
337 if (mustExist) {
338 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
339 }
340 return null;
341 }
342 final byte[] bytes = field.getByteArrayValue();
343 return tag.getValue(field.getByteOrder(), bytes);
344 }
345
346 public RationalNumber getFieldValue(final TagInfoRational tag) throws ImagingException {
347 final TiffField field = findField(tag);
348 if (field == null) {
349 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
350 }
351 if (!tag.dataTypes.contains(field.getFieldType())) {
352 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
353 }
354 if (field.getCount() != 1) {
355 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
356 }
357 final byte[] bytes = field.getByteArrayValue();
358 return tag.getValue(field.getByteOrder(), bytes);
359 }
360
361 public RationalNumber[] getFieldValue(final TagInfoRationals tag, final boolean mustExist) throws ImagingException {
362 final TiffField field = findField(tag);
363 if (field == null) {
364 if (mustExist) {
365 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
366 }
367 return null;
368 }
369 if (!tag.dataTypes.contains(field.getFieldType())) {
370 if (mustExist) {
371 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
372 }
373 return null;
374 }
375 final byte[] bytes = field.getByteArrayValue();
376 return tag.getValue(field.getByteOrder(), bytes);
377 }
378
379 public byte getFieldValue(final TagInfoSByte tag) throws ImagingException {
380 final TiffField field = findField(tag);
381 if (field == null) {
382 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
383 }
384 if (!tag.dataTypes.contains(field.getFieldType())) {
385 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
386 }
387 if (field.getCount() != 1) {
388 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
389 }
390 return field.getByteArrayValue()[0];
391 }
392
393 public byte[] getFieldValue(final TagInfoSBytes tag, final boolean mustExist) throws ImagingException {
394 final TiffField field = findField(tag);
395 if (field == null) {
396 if (mustExist) {
397 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
398 }
399 return null;
400 }
401 if (!tag.dataTypes.contains(field.getFieldType())) {
402 if (mustExist) {
403 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
404 }
405 return null;
406 }
407 return field.getByteArrayValue();
408 }
409
410 public short getFieldValue(final TagInfoShort tag) throws ImagingException {
411 final TiffField field = findField(tag);
412 if (field == null) {
413 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
414 }
415 if (!tag.dataTypes.contains(field.getFieldType())) {
416 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
417 }
418 if (field.getCount() != 1) {
419 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
420 }
421 final byte[] bytes = field.getByteArrayValue();
422 return tag.getValue(field.getByteOrder(), bytes);
423 }
424
425 public int[] getFieldValue(final TagInfoShortOrLong tag, final boolean mustExist) throws ImagingException {
426 final TiffField field = findField(tag);
427 if (field == null) {
428 if (mustExist) {
429 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
430 }
431 return null;
432 }
433 if (!tag.dataTypes.contains(field.getFieldType())) {
434 if (mustExist) {
435 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
436 }
437 return null;
438 }
439 final byte[] bytes = field.getByteArrayValue();
440 if (field.getFieldType() == AbstractFieldType.SHORT) {
441 return ByteConversions.toUInt16s(bytes, field.getByteOrder());
442 }
443 return ByteConversions.toInts(bytes, field.getByteOrder());
444 }
445
446 public short[] getFieldValue(final TagInfoShorts tag, final boolean mustExist) throws ImagingException {
447 final TiffField field = findField(tag);
448 if (field == null) {
449 if (mustExist) {
450 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
451 }
452 return null;
453 }
454 if (!tag.dataTypes.contains(field.getFieldType())) {
455 if (mustExist) {
456 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
457 }
458 return null;
459 }
460 final byte[] bytes = field.getByteArrayValue();
461 return tag.getValue(field.getByteOrder(), bytes);
462 }
463
464 public int getFieldValue(final TagInfoSLong tag) throws ImagingException {
465 final TiffField field = findField(tag);
466 if (field == null) {
467 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
468 }
469 if (!tag.dataTypes.contains(field.getFieldType())) {
470 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
471 }
472 if (field.getCount() != 1) {
473 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
474 }
475 final byte[] bytes = field.getByteArrayValue();
476 return tag.getValue(field.getByteOrder(), bytes);
477 }
478
479 public int[] getFieldValue(final TagInfoSLongs tag, final boolean mustExist) throws ImagingException {
480 final TiffField field = findField(tag);
481 if (field == null) {
482 if (mustExist) {
483 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
484 }
485 return null;
486 }
487 if (!tag.dataTypes.contains(field.getFieldType())) {
488 if (mustExist) {
489 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
490 }
491 return null;
492 }
493 final byte[] bytes = field.getByteArrayValue();
494 return tag.getValue(field.getByteOrder(), bytes);
495 }
496
497 public RationalNumber getFieldValue(final TagInfoSRational tag) throws ImagingException {
498 final TiffField field = findField(tag);
499 if (field == null) {
500 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
501 }
502 if (!tag.dataTypes.contains(field.getFieldType())) {
503 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
504 }
505 if (field.getCount() != 1) {
506 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
507 }
508 final byte[] bytes = field.getByteArrayValue();
509 return tag.getValue(field.getByteOrder(), bytes);
510 }
511
512 public RationalNumber[] getFieldValue(final TagInfoSRationals tag, final boolean mustExist) throws ImagingException {
513 final TiffField field = findField(tag);
514 if (field == null) {
515 if (mustExist) {
516 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
517 }
518 return null;
519 }
520 if (!tag.dataTypes.contains(field.getFieldType())) {
521 if (mustExist) {
522 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
523 }
524 return null;
525 }
526 final byte[] bytes = field.getByteArrayValue();
527 return tag.getValue(field.getByteOrder(), bytes);
528 }
529
530 public short getFieldValue(final TagInfoSShort tag) throws ImagingException {
531 final TiffField field = findField(tag);
532 if (field == null) {
533 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
534 }
535 if (!tag.dataTypes.contains(field.getFieldType())) {
536 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
537 }
538 if (field.getCount() != 1) {
539 throw new ImagingException("Field \"" + tag.name + "\" has wrong count " + field.getCount());
540 }
541 final byte[] bytes = field.getByteArrayValue();
542 return tag.getValue(field.getByteOrder(), bytes);
543 }
544
545 public short[] getFieldValue(final TagInfoSShorts tag, final boolean mustExist) throws ImagingException {
546 final TiffField field = findField(tag);
547 if (field == null) {
548 if (mustExist) {
549 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
550 }
551 return null;
552 }
553 if (!tag.dataTypes.contains(field.getFieldType())) {
554 if (mustExist) {
555 throw new ImagingException("Required field \"" + tag.name + "\" has incorrect type " + field.getFieldType().getName());
556 }
557 return null;
558 }
559 final byte[] bytes = field.getByteArrayValue();
560 return tag.getValue(field.getByteOrder(), bytes);
561 }
562
563 public String getFieldValue(final TagInfoXpString tag, final boolean mustExist) throws ImagingException {
564 final TiffField field = findField(tag);
565 if (field == null) {
566 if (mustExist) {
567 throw new ImagingException("Required field \"" + tag.name + "\" is missing");
568 }
569 return null;
570 }
571 return tag.getValue(field);
572 }
573
574 public JpegImageData getJpegImageData() {
575 return jpegImageData;
576 }
577
578 public ImageDataElement getJpegRawImageDataElement() throws ImagingException {
579 final TiffField jpegInterchangeFormat = findField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT);
580 final TiffField jpegInterchangeFormatLength = findField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
581
582 if (jpegInterchangeFormat != null && jpegInterchangeFormatLength != null) {
583 final int offSet = jpegInterchangeFormat.getIntArrayValue()[0];
584 final int byteCount = jpegInterchangeFormatLength.getIntArrayValue()[0];
585
586 return new ImageDataElement(offSet, byteCount);
587 }
588 throw new ImagingException("Couldn't find image data.");
589 }
590
591 public long getNextDirectoryOffset() {
592 return nextDirectoryOffset;
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625 public AbstractTiffRasterData getRasterData(final TiffImagingParameters params) throws ImagingException, IOException {
626
627 final TiffImageParser parser = new TiffImageParser();
628 return parser.getRasterData(this, headerByteOrder, params);
629 }
630
631 private List<ImageDataElement> getRawImageDataElements(final TiffField offsetsField, final TiffField byteCountsField) throws ImagingException {
632 final long[] offsets = offsetsField.getLongArrayValue();
633 final int[] byteCounts = byteCountsField.getIntArrayValue();
634
635 if (offsets.length != byteCounts.length) {
636 throw new ImagingException("offsets.length(" + offsets.length + ") != byteCounts.length(" + byteCounts.length + ")");
637 }
638
639 final List<ImageDataElement> result = Allocator.arrayList(offsets.length);
640 for (int i = 0; i < offsets.length; i++) {
641 result.add(new ImageDataElement(offsets[i], byteCounts[i]));
642 }
643 return result;
644 }
645
646 public String getSingleFieldValue(final TagInfoAscii tag) throws ImagingException {
647 final String[] result = getFieldValue(tag, true);
648 if (result.length != 1) {
649 throw new ImagingException("Field \"" + tag.name + "\" has incorrect length " + result.length);
650 }
651 return result[0];
652 }
653
654 public int getSingleFieldValue(final TagInfoShortOrLong tag) throws ImagingException {
655 final int[] result = getFieldValue(tag, true);
656 if (result.length != 1) {
657 throw new ImagingException("Field \"" + tag.name + "\" has incorrect length " + result.length);
658 }
659 return result[0];
660 }
661
662
663
664
665
666
667
668
669 public BufferedImage getTiffImage() throws ImagingException, IOException {
670 if (null == abstractTiffImageData) {
671 return null;
672 }
673
674 return new TiffImageParser().getBufferedImage(this, headerByteOrder, null);
675 }
676
677
678
679
680
681
682
683
684
685
686
687
688 public BufferedImage getTiffImage(final ByteOrder byteOrder) throws ImagingException, IOException {
689 return getTiffImage(byteOrder, new TiffImagingParameters());
690 }
691
692
693
694
695
696
697
698
699
700
701
702
703
704 public BufferedImage getTiffImage(final ByteOrder byteOrder, final TiffImagingParameters params) throws ImagingException, IOException {
705 if (null == abstractTiffImageData) {
706 return null;
707 }
708
709 return new TiffImageParser().getBufferedImage(this, byteOrder, params);
710 }
711
712
713
714
715
716
717
718
719
720
721
722
723 public BufferedImage getTiffImage(final TiffImagingParameters params) throws ImagingException, IOException {
724 if (null == abstractTiffImageData) {
725 return null;
726 }
727
728 return new TiffImageParser().getBufferedImage(this, headerByteOrder, params);
729 }
730
731 public AbstractTiffImageData getTiffImageData() {
732 return abstractTiffImageData;
733 }
734
735 public List<ImageDataElement> getTiffRawImageDataElements() throws ImagingException {
736 final TiffField tileOffsets = findField(TiffTagConstants.TIFF_TAG_TILE_OFFSETS);
737 final TiffField tileByteCounts = findField(TiffTagConstants.TIFF_TAG_TILE_BYTE_COUNTS);
738 final TiffField stripOffsets = findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS);
739 final TiffField stripByteCounts = findField(TiffTagConstants.TIFF_TAG_STRIP_BYTE_COUNTS);
740
741 if (tileOffsets != null && tileByteCounts != null) {
742 return getRawImageDataElements(tileOffsets, tileByteCounts);
743 }
744 if (stripOffsets != null && stripByteCounts != null) {
745 return getRawImageDataElements(stripOffsets, stripByteCounts);
746 }
747 throw new ImagingException("Couldn't find image data.");
748 }
749
750 public boolean hasJpegImageData() throws ImagingException {
751 return null != findField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT);
752 }
753
754
755
756
757
758
759
760 public boolean hasTiffFloatingPointRasterData() throws ImagingException {
761 if (!hasTiffImageData()) {
762 return false;
763 }
764 final short[] s = getFieldValue(TiffTagConstants.TIFF_TAG_SAMPLE_FORMAT, false);
765 return s != null && s.length > 0 && s[0] == TiffTagConstants.SAMPLE_FORMAT_VALUE_IEEE_FLOATING_POINT;
766
767 }
768
769 public boolean hasTiffImageData() throws ImagingException {
770 if (null != findField(TiffTagConstants.TIFF_TAG_TILE_OFFSETS)) {
771 return true;
772 }
773
774 return null != findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS);
775 }
776
777
778
779
780
781
782
783
784 public boolean hasTiffRasterData() throws ImagingException {
785 if (!hasTiffImageData()) {
786 return false;
787 }
788 final short[] s = getFieldValue(TiffTagConstants.TIFF_TAG_SAMPLE_FORMAT, false);
789 return s != null && s.length > 0 && (s[0] == TiffTagConstants.SAMPLE_FORMAT_VALUE_IEEE_FLOATING_POINT
790 || s[0] == TiffTagConstants.SAMPLE_FORMAT_VALUE_TWOS_COMPLEMENT_SIGNED_INTEGER);
791 }
792
793 public boolean imageDataInStrips() throws ImagingException {
794 final TiffField tileOffsets = findField(TiffTagConstants.TIFF_TAG_TILE_OFFSETS);
795 final TiffField tileByteCounts = findField(TiffTagConstants.TIFF_TAG_TILE_BYTE_COUNTS);
796 final TiffField stripOffsets = findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS);
797 final TiffField stripByteCounts = findField(TiffTagConstants.TIFF_TAG_STRIP_BYTE_COUNTS);
798
799 if (tileOffsets != null && tileByteCounts != null) {
800 return false;
801 }
802 if (stripOffsets != null && stripByteCounts != null) {
803 return true;
804 }
805 throw new ImagingException("Couldn't find image data.");
806 }
807
808 @Override
809 public Iterator<TiffField> iterator() {
810 return entries.iterator();
811 }
812
813 public void setJpegImageData(final JpegImageData value) {
814 this.jpegImageData = value;
815 }
816
817 public void setTiffImageData(final AbstractTiffImageData rawImageData) {
818 this.abstractTiffImageData = rawImageData;
819 }
820
821 public int size() {
822 return entries.size();
823 }
824 }