001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.imaging.formats.tiff; 018 019import java.awt.image.BufferedImage; 020import java.io.IOException; 021import java.nio.ByteOrder; 022import java.util.ArrayList; 023import java.util.Collections; 024import java.util.List; 025import java.util.Map; 026 027import org.apache.commons.imaging.ImageReadException; 028import org.apache.commons.imaging.common.ByteConversions; 029import org.apache.commons.imaging.common.RationalNumber; 030import org.apache.commons.imaging.formats.tiff.constants.TiffConstants; 031import org.apache.commons.imaging.formats.tiff.constants.TiffDirectoryConstants; 032import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants; 033import org.apache.commons.imaging.formats.tiff.fieldtypes.FieldType; 034import org.apache.commons.imaging.formats.tiff.taginfos.TagInfo; 035import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoAscii; 036import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoByte; 037import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoBytes; 038import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoDouble; 039import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoDoubles; 040import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoFloat; 041import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoFloats; 042import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoGpsText; 043import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoLong; 044import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoLongs; 045import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoRational; 046import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoRationals; 047import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSByte; 048import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSBytes; 049import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSLong; 050import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSLongs; 051import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSRational; 052import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSRationals; 053import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSShort; 054import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoSShorts; 055import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShort; 056import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShortOrLong; 057import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoShorts; 058import org.apache.commons.imaging.formats.tiff.taginfos.TagInfoXpString; 059 060public class TiffDirectory extends TiffElement { 061 public final int type; 062 public final List<TiffField> entries; 063 public final long nextDirectoryOffset; 064 private TiffImageData tiffImageData; 065 private JpegImageData jpegImageData; 066 067 public TiffDirectory(final int type, final List<TiffField> entries, final long offset, final long nextDirectoryOffset) { 068 super(offset, TiffConstants.TIFF_DIRECTORY_HEADER_LENGTH 069 + entries.size() * TiffConstants.TIFF_ENTRY_LENGTH 070 + TiffConstants.TIFF_DIRECTORY_FOOTER_LENGTH); 071 072 this.type = type; 073 this.entries = Collections.unmodifiableList(entries); 074 this.nextDirectoryOffset = nextDirectoryOffset; 075 } 076 077 public String description() { 078 return TiffDirectory.description(type); 079 } 080 081 @Override 082 public String getElementDescription() { 083 long entryOffset = offset + TiffConstants.TIFF_DIRECTORY_HEADER_LENGTH; 084 085 final StringBuilder result = new StringBuilder(); 086 for (final TiffField entry : entries) { 087 result.append(String.format("\t[%d]: %s (%d, 0x%x), %s, %d: %s%n", 088 entryOffset, entry.getTagInfo().name, 089 entry.getTag(), entry.getTag(), 090 entry.getFieldType().getName(), entry.getBytesLength(), 091 entry.getValueDescription())); 092 093 entryOffset += TiffConstants.TIFF_ENTRY_LENGTH; 094 } 095 return result.toString(); 096 } 097 098 public static String description(final int type) { 099 switch (type) { 100 case TiffDirectoryConstants.DIRECTORY_TYPE_UNKNOWN: 101 return "Unknown"; 102 case TiffDirectoryConstants.DIRECTORY_TYPE_ROOT: 103 return "Root"; 104 case TiffDirectoryConstants.DIRECTORY_TYPE_SUB: 105 return "Sub"; 106 case TiffDirectoryConstants.DIRECTORY_TYPE_THUMBNAIL: 107 return "Thumbnail"; 108 case TiffDirectoryConstants.DIRECTORY_TYPE_EXIF: 109 return "Exif"; 110 case TiffDirectoryConstants.DIRECTORY_TYPE_GPS: 111 return "Gps"; 112 case TiffDirectoryConstants.DIRECTORY_TYPE_INTEROPERABILITY: 113 return "Interoperability"; 114 default: 115 return "Bad Type"; 116 } 117 } 118 119 120 public List<TiffField> getDirectoryEntries() { 121 return new ArrayList<>(entries); 122 } 123 124 public void dump() { 125 for (final TiffField entry : entries) { 126 entry.dump(); 127 } 128 129 } 130 131 public boolean hasJpegImageData() throws ImageReadException { 132 if (null != findField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT)) { 133 return true; 134 } 135 136 return false; 137 } 138 139 public boolean hasTiffImageData() throws ImageReadException { 140 if (null != findField(TiffTagConstants.TIFF_TAG_TILE_OFFSETS)) { 141 return true; 142 } 143 144 if (null != findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS)) { 145 return true; 146 } 147 148 return false; 149 } 150 151 public BufferedImage getTiffImage(final ByteOrder byteOrder) throws ImageReadException, 152 IOException { 153 final Map<String, Object> params = null; 154 return getTiffImage(byteOrder, params); 155 } 156 157 public BufferedImage getTiffImage(final ByteOrder byteOrder, final Map<String, Object> params) 158 throws ImageReadException, IOException { 159 if (null == tiffImageData) { 160 return null; 161 } 162 163 return new TiffImageParser().getBufferedImage(this, byteOrder, params); 164 } 165 166 public TiffField findField(final TagInfo tag) throws ImageReadException { 167 final boolean failIfMissing = false; 168 return findField(tag, failIfMissing); 169 } 170 171 public TiffField findField(final TagInfo tag, final boolean failIfMissing) 172 throws ImageReadException { 173 if (entries == null) { 174 return null; 175 } 176 177 for (final TiffField field : entries) { 178 if (field.getTag() == tag.tag) { 179 return field; 180 } 181 } 182 183 if (failIfMissing) { 184 throw new ImageReadException("Missing expected field: " 185 + tag.getDescription()); 186 } 187 188 return null; 189 } 190 191 public Object getFieldValue(final TagInfo tag) throws ImageReadException { 192 final TiffField field = findField(tag); 193 if (field == null) { 194 return null; 195 } 196 return field.getValue(); 197 } 198 199 public String getSingleFieldValue(final TagInfoAscii tag) 200 throws ImageReadException { 201 final String[] result = getFieldValue(tag, true); 202 if (result.length != 1) { 203 throw new ImageReadException("Field \"" + tag.name 204 + "\" has incorrect length " + result.length); 205 } 206 return result[0]; 207 } 208 209 public int getSingleFieldValue(final TagInfoShortOrLong tag) throws ImageReadException { 210 final int[] result = getFieldValue(tag, true); 211 if (result.length != 1) { 212 throw new ImageReadException("Field \"" + tag.name 213 + "\" has incorrect length " + result.length); 214 } 215 return result[0]; 216 } 217 218 public byte getFieldValue(final TagInfoByte tag) 219 throws ImageReadException { 220 final TiffField field = findField(tag); 221 if (field == null) { 222 throw new ImageReadException("Required field \"" + tag.name 223 + "\" is missing"); 224 } 225 if (!tag.dataTypes.contains(field.getFieldType())) { 226 throw new ImageReadException("Required field \"" + tag.name 227 + "\" has incorrect type " + field.getFieldType().getName()); 228 } 229 if (field.getCount() != 1) { 230 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 231 } 232 return field.getByteArrayValue()[0]; 233 } 234 235 public byte[] getFieldValue(final TagInfoBytes tag, final boolean mustExist) 236 throws ImageReadException { 237 final TiffField field = findField(tag); 238 if (field == null) { 239 if (mustExist) { 240 throw new ImageReadException("Required field \"" + tag.name 241 + "\" is missing"); 242 } else { 243 return null; 244 } 245 } 246 if (!tag.dataTypes.contains(field.getFieldType())) { 247 if (mustExist) { 248 throw new ImageReadException("Required field \"" + tag.name 249 + "\" has incorrect type " + field.getFieldType().getName()); 250 } else { 251 return null; 252 } 253 } 254 return field.getByteArrayValue(); 255 } 256 257 public String[] getFieldValue(final TagInfoAscii tag, final boolean mustExist) 258 throws ImageReadException { 259 final TiffField field = findField(tag); 260 if (field == null) { 261 if (mustExist) { 262 throw new ImageReadException("Required field \"" + tag.name 263 + "\" is missing"); 264 } else { 265 return null; 266 } 267 } 268 if (!tag.dataTypes.contains(field.getFieldType())) { 269 if (mustExist) { 270 throw new ImageReadException("Required field \"" + tag.name 271 + "\" has incorrect type " + field.getFieldType().getName()); 272 } else { 273 return null; 274 } 275 } 276 final byte[] bytes = field.getByteArrayValue(); 277 return tag.getValue(field.getByteOrder(), bytes); 278 } 279 280 public short getFieldValue(final TagInfoShort tag) 281 throws ImageReadException { 282 final TiffField field = findField(tag); 283 if (field == null) { 284 throw new ImageReadException("Required field \"" + tag.name 285 + "\" is missing"); 286 } 287 if (!tag.dataTypes.contains(field.getFieldType())) { 288 throw new ImageReadException("Required field \"" + tag.name 289 + "\" has incorrect type " + field.getFieldType().getName()); 290 } 291 if (field.getCount() != 1) { 292 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 293 } 294 final byte[] bytes = field.getByteArrayValue(); 295 return tag.getValue(field.getByteOrder(), bytes); 296 } 297 298 public short[] getFieldValue(final TagInfoShorts tag, final boolean mustExist) 299 throws ImageReadException { 300 final TiffField field = findField(tag); 301 if (field == null) { 302 if (mustExist) { 303 throw new ImageReadException("Required field \"" + tag.name 304 + "\" is missing"); 305 } else { 306 return null; 307 } 308 } 309 if (!tag.dataTypes.contains(field.getFieldType())) { 310 if (mustExist) { 311 throw new ImageReadException("Required field \"" + tag.name 312 + "\" has incorrect type " + field.getFieldType().getName()); 313 } else { 314 return null; 315 } 316 } 317 final byte[] bytes = field.getByteArrayValue(); 318 return tag.getValue(field.getByteOrder(), bytes); 319 } 320 321 public int getFieldValue(final TagInfoLong tag) 322 throws ImageReadException { 323 final TiffField field = findField(tag); 324 if (field == null) { 325 throw new ImageReadException("Required field \"" + tag.name 326 + "\" is missing"); 327 } 328 if (!tag.dataTypes.contains(field.getFieldType())) { 329 throw new ImageReadException("Required field \"" + tag.name 330 + "\" has incorrect type " + field.getFieldType().getName()); 331 } 332 if (field.getCount() != 1) { 333 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 334 } 335 final byte[] bytes = field.getByteArrayValue(); 336 return tag.getValue(field.getByteOrder(), bytes); 337 } 338 339 public int[] getFieldValue(final TagInfoLongs tag, final boolean mustExist) 340 throws ImageReadException { 341 final TiffField field = findField(tag); 342 if (field == null) { 343 if (mustExist) { 344 throw new ImageReadException("Required field \"" + tag.name 345 + "\" is missing"); 346 } else { 347 return null; 348 } 349 } 350 if (!tag.dataTypes.contains(field.getFieldType())) { 351 if (mustExist) { 352 throw new ImageReadException("Required field \"" + tag.name 353 + "\" has incorrect type " + field.getFieldType().getName()); 354 } else { 355 return null; 356 } 357 } 358 final byte[] bytes = field.getByteArrayValue(); 359 return tag.getValue(field.getByteOrder(), bytes); 360 } 361 362 public int[] getFieldValue(final TagInfoShortOrLong tag, final boolean mustExist) 363 throws ImageReadException { 364 final TiffField field = findField(tag); 365 if (field == null) { 366 if (mustExist) { 367 throw new ImageReadException("Required field \"" + tag.name 368 + "\" is missing"); 369 } else { 370 return null; 371 } 372 } 373 if (!tag.dataTypes.contains(field.getFieldType())) { 374 if (mustExist) { 375 throw new ImageReadException("Required field \"" + tag.name 376 + "\" has incorrect type " + field.getFieldType().getName()); 377 } else { 378 return null; 379 } 380 } 381 final byte[] bytes = field.getByteArrayValue(); 382 if (field.getFieldType() == FieldType.SHORT) { 383 return ByteConversions.toUInt16s(bytes, field.getByteOrder()); 384 } else { 385 return ByteConversions.toInts(bytes, field.getByteOrder()); 386 } 387 } 388 389 public RationalNumber getFieldValue(final TagInfoRational tag) 390 throws ImageReadException { 391 final TiffField field = findField(tag); 392 if (field == null) { 393 throw new ImageReadException("Required field \"" + tag.name 394 + "\" is missing"); 395 } 396 if (!tag.dataTypes.contains(field.getFieldType())) { 397 throw new ImageReadException("Required field \"" + tag.name 398 + "\" has incorrect type " + field.getFieldType().getName()); 399 } 400 if (field.getCount() != 1) { 401 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 402 } 403 final byte[] bytes = field.getByteArrayValue(); 404 return tag.getValue(field.getByteOrder(), bytes); 405 } 406 407 public RationalNumber[] getFieldValue(final TagInfoRationals tag, final boolean mustExist) 408 throws ImageReadException { 409 final TiffField field = findField(tag); 410 if (field == null) { 411 if (mustExist) { 412 throw new ImageReadException("Required field \"" + tag.name 413 + "\" is missing"); 414 } else { 415 return null; 416 } 417 } 418 if (!tag.dataTypes.contains(field.getFieldType())) { 419 if (mustExist) { 420 throw new ImageReadException("Required field \"" + tag.name 421 + "\" has incorrect type " + field.getFieldType().getName()); 422 } else { 423 return null; 424 } 425 } 426 final byte[] bytes = field.getByteArrayValue(); 427 return tag.getValue(field.getByteOrder(), bytes); 428 } 429 430 public byte getFieldValue(final TagInfoSByte tag) 431 throws ImageReadException { 432 final TiffField field = findField(tag); 433 if (field == null) { 434 throw new ImageReadException("Required field \"" + tag.name 435 + "\" is missing"); 436 } 437 if (!tag.dataTypes.contains(field.getFieldType())) { 438 throw new ImageReadException("Required field \"" + tag.name 439 + "\" has incorrect type " + field.getFieldType().getName()); 440 } 441 if (field.getCount() != 1) { 442 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 443 } 444 return field.getByteArrayValue()[0]; 445 } 446 447 public byte[] getFieldValue(final TagInfoSBytes tag, final boolean mustExist) 448 throws ImageReadException { 449 final TiffField field = findField(tag); 450 if (field == null) { 451 if (mustExist) { 452 throw new ImageReadException("Required field \"" + tag.name 453 + "\" is missing"); 454 } else { 455 return null; 456 } 457 } 458 if (!tag.dataTypes.contains(field.getFieldType())) { 459 if (mustExist) { 460 throw new ImageReadException("Required field \"" + tag.name 461 + "\" has incorrect type " + field.getFieldType().getName()); 462 } else { 463 return null; 464 } 465 } 466 return field.getByteArrayValue(); 467 } 468 469 public short getFieldValue(final TagInfoSShort tag) 470 throws ImageReadException { 471 final TiffField field = findField(tag); 472 if (field == null) { 473 throw new ImageReadException("Required field \"" + tag.name 474 + "\" is missing"); 475 } 476 if (!tag.dataTypes.contains(field.getFieldType())) { 477 throw new ImageReadException("Required field \"" + tag.name 478 + "\" has incorrect type " + field.getFieldType().getName()); 479 } 480 if (field.getCount() != 1) { 481 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 482 } 483 final byte[] bytes = field.getByteArrayValue(); 484 return tag.getValue(field.getByteOrder(), bytes); 485 } 486 487 public short[] getFieldValue(final TagInfoSShorts tag, final boolean mustExist) 488 throws ImageReadException { 489 final TiffField field = findField(tag); 490 if (field == null) { 491 if (mustExist) { 492 throw new ImageReadException("Required field \"" + tag.name 493 + "\" is missing"); 494 } else { 495 return null; 496 } 497 } 498 if (!tag.dataTypes.contains(field.getFieldType())) { 499 if (mustExist) { 500 throw new ImageReadException("Required field \"" + tag.name 501 + "\" has incorrect type " + field.getFieldType().getName()); 502 } else { 503 return null; 504 } 505 } 506 final byte[] bytes = field.getByteArrayValue(); 507 return tag.getValue(field.getByteOrder(), bytes); 508 } 509 510 public int getFieldValue(final TagInfoSLong tag) 511 throws ImageReadException { 512 final TiffField field = findField(tag); 513 if (field == null) { 514 throw new ImageReadException("Required field \"" + tag.name 515 + "\" is missing"); 516 } 517 if (!tag.dataTypes.contains(field.getFieldType())) { 518 throw new ImageReadException("Required field \"" + tag.name 519 + "\" has incorrect type " + field.getFieldType().getName()); 520 } 521 if (field.getCount() != 1) { 522 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 523 } 524 final byte[] bytes = field.getByteArrayValue(); 525 return tag.getValue(field.getByteOrder(), bytes); 526 } 527 528 public int[] getFieldValue(final TagInfoSLongs tag, final boolean mustExist) 529 throws ImageReadException { 530 final TiffField field = findField(tag); 531 if (field == null) { 532 if (mustExist) { 533 throw new ImageReadException("Required field \"" + tag.name 534 + "\" is missing"); 535 } else { 536 return null; 537 } 538 } 539 if (!tag.dataTypes.contains(field.getFieldType())) { 540 if (mustExist) { 541 throw new ImageReadException("Required field \"" + tag.name 542 + "\" has incorrect type " + field.getFieldType().getName()); 543 } else { 544 return null; 545 } 546 } 547 final byte[] bytes = field.getByteArrayValue(); 548 return tag.getValue(field.getByteOrder(), bytes); 549 } 550 551 public RationalNumber getFieldValue(final TagInfoSRational tag) throws ImageReadException { 552 final TiffField field = findField(tag); 553 if (field == null) { 554 throw new ImageReadException("Required field \"" + tag.name 555 + "\" is missing"); 556 } 557 if (!tag.dataTypes.contains(field.getFieldType())) { 558 throw new ImageReadException("Required field \"" + tag.name 559 + "\" has incorrect type " + field.getFieldType().getName()); 560 } 561 if (field.getCount() != 1) { 562 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 563 } 564 final byte[] bytes = field.getByteArrayValue(); 565 return tag.getValue(field.getByteOrder(), bytes); 566 } 567 568 public RationalNumber[] getFieldValue(final TagInfoSRationals tag, 569 final boolean mustExist) throws ImageReadException { 570 final TiffField field = findField(tag); 571 if (field == null) { 572 if (mustExist) { 573 throw new ImageReadException("Required field \"" + tag.name 574 + "\" is missing"); 575 } else { 576 return null; 577 } 578 } 579 if (!tag.dataTypes.contains(field.getFieldType())) { 580 if (mustExist) { 581 throw new ImageReadException("Required field \"" + tag.name 582 + "\" has incorrect type " + field.getFieldType().getName()); 583 } else { 584 return null; 585 } 586 } 587 final byte[] bytes = field.getByteArrayValue(); 588 return tag.getValue(field.getByteOrder(), bytes); 589 } 590 591 public float getFieldValue(final TagInfoFloat tag) 592 throws ImageReadException { 593 final TiffField field = findField(tag); 594 if (field == null) { 595 throw new ImageReadException("Required field \"" + tag.name 596 + "\" is missing"); 597 } 598 if (!tag.dataTypes.contains(field.getFieldType())) { 599 throw new ImageReadException("Required field \"" + tag.name 600 + "\" has incorrect type " + field.getFieldType().getName()); 601 } 602 if (field.getCount() != 1) { 603 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 604 } 605 final byte[] bytes = field.getByteArrayValue(); 606 return tag.getValue(field.getByteOrder(), bytes); 607 } 608 609 public float[] getFieldValue(final TagInfoFloats tag, final boolean mustExist) 610 throws ImageReadException { 611 final TiffField field = findField(tag); 612 if (field == null) { 613 if (mustExist) { 614 throw new ImageReadException("Required field \"" + tag.name 615 + "\" is missing"); 616 } else { 617 return null; 618 } 619 } 620 if (!tag.dataTypes.contains(field.getFieldType())) { 621 if (mustExist) { 622 throw new ImageReadException("Required field \"" + tag.name 623 + "\" has incorrect type " + field.getFieldType().getName()); 624 } else { 625 return null; 626 } 627 } 628 final byte[] bytes = field.getByteArrayValue(); 629 return tag.getValue(field.getByteOrder(), bytes); 630 } 631 632 public double getFieldValue(final TagInfoDouble tag) 633 throws ImageReadException { 634 final TiffField field = findField(tag); 635 if (field == null) { 636 throw new ImageReadException("Required field \"" + tag.name 637 + "\" is missing"); 638 } 639 if (!tag.dataTypes.contains(field.getFieldType())) { 640 throw new ImageReadException("Required field \"" + tag.name 641 + "\" has incorrect type " + field.getFieldType().getName()); 642 } 643 if (field.getCount() != 1) { 644 throw new ImageReadException("Field \"" + tag.name + "\" has wrong count " + field.getCount()); 645 } 646 final byte[] bytes = field.getByteArrayValue(); 647 return tag.getValue(field.getByteOrder(), bytes); 648 } 649 650 public double[] getFieldValue(final TagInfoDoubles tag, final boolean mustExist) 651 throws ImageReadException { 652 final TiffField field = findField(tag); 653 if (field == null) { 654 if (mustExist) { 655 throw new ImageReadException("Required field \"" + tag.name 656 + "\" is missing"); 657 } else { 658 return null; 659 } 660 } 661 if (!tag.dataTypes.contains(field.getFieldType())) { 662 if (mustExist) { 663 throw new ImageReadException("Required field \"" + tag.name 664 + "\" has incorrect type " + field.getFieldType().getName()); 665 } else { 666 return null; 667 } 668 } 669 final byte[] bytes = field.getByteArrayValue(); 670 return tag.getValue(field.getByteOrder(), bytes); 671 } 672 673 public String getFieldValue(final TagInfoGpsText tag, final boolean mustExist) 674 throws ImageReadException { 675 final TiffField field = findField(tag); 676 if (field == null) { 677 if (mustExist) { 678 throw new ImageReadException("Required field \"" + tag.name 679 + "\" is missing"); 680 } else { 681 return null; 682 } 683 } 684 return tag.getValue(field); 685 } 686 687 public String getFieldValue(final TagInfoXpString tag, final boolean mustExist) 688 throws ImageReadException { 689 final TiffField field = findField(tag); 690 if (field == null) { 691 if (mustExist) { 692 throw new ImageReadException("Required field \"" + tag.name 693 + "\" is missing"); 694 } else { 695 return null; 696 } 697 } 698 return tag.getValue(field); 699 } 700 701 public static final class ImageDataElement extends TiffElement { 702 public ImageDataElement(final long offset, final int length) { 703 super(offset, length); 704 } 705 706 @Override 707 public String getElementDescription() { 708 return "ImageDataElement"; 709 } 710 } 711 712 private List<ImageDataElement> getRawImageDataElements( 713 final TiffField offsetsField, final TiffField byteCountsField) 714 throws ImageReadException { 715 final int[] offsets = offsetsField.getIntArrayValue(); 716 final int[] byteCounts = byteCountsField.getIntArrayValue(); 717 718 if (offsets.length != byteCounts.length) { 719 throw new ImageReadException("offsets.length(" + offsets.length 720 + ") != byteCounts.length(" + byteCounts.length + ")"); 721 } 722 723 final List<ImageDataElement> result = new ArrayList<>(offsets.length); 724 for (int i = 0; i < offsets.length; i++) { 725 result.add(new ImageDataElement(offsets[i], byteCounts[i])); 726 } 727 return result; 728 } 729 730 public List<ImageDataElement> getTiffRawImageDataElements() 731 throws ImageReadException { 732 final TiffField tileOffsets = findField(TiffTagConstants.TIFF_TAG_TILE_OFFSETS); 733 final TiffField tileByteCounts = findField(TiffTagConstants.TIFF_TAG_TILE_BYTE_COUNTS); 734 final TiffField stripOffsets = findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS); 735 final TiffField stripByteCounts = findField(TiffTagConstants.TIFF_TAG_STRIP_BYTE_COUNTS); 736 737 if ((tileOffsets != null) && (tileByteCounts != null)) { 738 return getRawImageDataElements(tileOffsets, tileByteCounts); 739 } else if ((stripOffsets != null) && (stripByteCounts != null)) { 740 return getRawImageDataElements(stripOffsets, stripByteCounts); 741 } else { 742 throw new ImageReadException("Couldn't find image data."); 743 } 744 } 745 746 public boolean imageDataInStrips() throws ImageReadException { 747 final TiffField tileOffsets = findField(TiffTagConstants.TIFF_TAG_TILE_OFFSETS); 748 final TiffField tileByteCounts = findField(TiffTagConstants.TIFF_TAG_TILE_BYTE_COUNTS); 749 final TiffField stripOffsets = findField(TiffTagConstants.TIFF_TAG_STRIP_OFFSETS); 750 final TiffField stripByteCounts = findField(TiffTagConstants.TIFF_TAG_STRIP_BYTE_COUNTS); 751 752 if ((tileOffsets != null) && (tileByteCounts != null)) { 753 return false; 754 } else if ((stripOffsets != null) && (stripByteCounts != null)) { 755 return true; 756 } else { 757 throw new ImageReadException("Couldn't find image data."); 758 } 759 } 760 761 public ImageDataElement getJpegRawImageDataElement() throws ImageReadException { 762 final TiffField jpegInterchangeFormat = findField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT); 763 final TiffField jpegInterchangeFormatLength = findField(TiffTagConstants.TIFF_TAG_JPEG_INTERCHANGE_FORMAT_LENGTH); 764 765 if (jpegInterchangeFormat != null && jpegInterchangeFormatLength != null) { 766 final int offSet = jpegInterchangeFormat.getIntArrayValue()[0]; 767 final int byteCount = jpegInterchangeFormatLength.getIntArrayValue()[0]; 768 769 return new ImageDataElement(offSet, byteCount); 770 } else { 771 throw new ImageReadException("Couldn't find image data."); 772 } 773 } 774 775 public void setTiffImageData(final TiffImageData rawImageData) { 776 this.tiffImageData = rawImageData; 777 } 778 779 public TiffImageData getTiffImageData() { 780 return tiffImageData; 781 } 782 783 public void setJpegImageData(final JpegImageData value) { 784 this.jpegImageData = value; 785 } 786 787 public JpegImageData getJpegImageData() { 788 return jpegImageData; 789 } 790 791}