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