1 /* 2 * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package javax.imageio.plugins.tiff; 26 27 import java.util.StringTokenizer; 28 import org.w3c.dom.NamedNodeMap; 29 import org.w3c.dom.Node; 30 import com.sun.imageio.plugins.tiff.TIFFFieldNode; 31 import com.sun.imageio.plugins.tiff.TIFFIFD; 32 33 /** 34 * A class representing a field in a TIFF 6.0 Image File Directory. 35 * 36 * <p> A field in a TIFF Image File Directory (IFD) is defined as a 37 * tag number accompanied by a sequence of values of identical data type. 38 * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is 39 * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These 40 * TIFF data types are referred to by Java constants and mapped internally 41 * onto Java language data types and type names as follows: 42 * 43 * <br> 44 * <br> 45 * <table border="1"> 46 * <caption>TIFF Data Type to Java Data Type Mapping</caption> 47 * 48 * <tr> 49 * <th> 50 * <b>TIFF Data Type</b> 51 * </th> 52 * <th> 53 * <b>Java Constant</b> 54 * </th> 55 * <th> 56 * <b>Java Data Type</b> 57 * </th> 58 * <th> 59 * <b>Java Type Name</b> 60 * </th> 61 * </tr> 62 * 63 * <tr> 64 * <td> 65 * <tt>BYTE</tt> 66 * </td> 67 * <td> 68 * {@link TIFFTag#TIFF_BYTE} 69 * </td> 70 * <td> 71 * {@code byte} 72 * </td> 73 * <td> 74 * {@code "Byte"} 75 * </td> 76 * </tr> 77 * 78 * <tr> 79 * <td> 80 * <tt>ASCII</tt> 81 * </td> 82 * <td> 83 * {@link TIFFTag#TIFF_ASCII} 84 * </td> 85 * <td> 86 * {@code String} 87 * </td> 88 * <td> 89 * {@code "Ascii"} 90 * </td> 91 * </tr> 92 * 93 * <tr> 94 * <td> 95 * <tt>SHORT</tt> 96 * </td> 97 * <td> 98 * {@link TIFFTag#TIFF_SHORT} 99 * </td> 100 * <td> 101 * {@code char} 102 * </td> 103 * <td> 104 * {@code "Short"} 105 * </td> 106 * </tr> 107 * 108 * <tr> 109 * <td> 110 * <tt>LONG</tt> 111 * </td> 112 * <td> 113 * {@link TIFFTag#TIFF_LONG} 114 * </td> 115 * <td> 116 * {@code long} 117 * </td> 118 * <td> 119 * {@code "Long"} 120 * </td> 121 * </tr> 122 * 123 * <tr> 124 * <td> 125 * <tt>RATIONAL</tt> 126 * </td> 127 * <td> 128 * {@link TIFFTag#TIFF_RATIONAL} 129 * </td> 130 * <td> 131 * {@code long[2]} {numerator, denominator} 132 * </td> 133 * <td> 134 * {@code "Rational"} 135 * </td> 136 * </tr> 137 * 138 * <tr> 139 * <td> 140 * <tt>SBYTE</tt> 141 * </td> 142 * <td> 143 * {@link TIFFTag#TIFF_SBYTE} 144 * </td> 145 * <td> 146 * {@code byte} 147 * </td> 148 * <td> 149 * {@code "SByte"} 150 * </td> 151 * </tr> 152 * 153 * <tr> 154 * <td> 155 * <tt>UNDEFINED</tt> 156 * </td> 157 * <td> 158 * {@link TIFFTag#TIFF_UNDEFINED} 159 * </td> 160 * <td> 161 * {@code byte} 162 * </td> 163 * <td> 164 * {@code "Undefined"} 165 * </td> 166 * </tr> 167 * 168 * <tr> 169 * <td> 170 * <tt>SSHORT</tt> 171 * </td> 172 * <td> 173 * {@link TIFFTag#TIFF_SSHORT} 174 * </td> 175 * <td> 176 * {@code short} 177 * </td> 178 * <td> 179 * {@code "SShort"} 180 * </td> 181 * </tr> 182 * 183 * <tr> 184 * <td> 185 * <tt>SLONG</tt> 186 * </td> 187 * <td> 188 * {@link TIFFTag#TIFF_SLONG} 189 * </td> 190 * <td> 191 * {@code int} 192 * </td> 193 * <td> 194 * {@code "SLong"} 195 * </td> 196 * </tr> 197 * 198 * <tr> 199 * <td> 200 * <tt>SRATIONAL</tt> 201 * </td> 202 * <td> 203 * {@link TIFFTag#TIFF_SRATIONAL} 204 * </td> 205 * <td> 206 * {@code int[2]} {numerator, denominator} 207 * </td> 208 * <td> 209 * {@code "SRational"} 210 * </td> 211 * </tr> 212 * 213 * <tr> 214 * <td> 215 * <tt>FLOAT</tt> 216 * </td> 217 * <td> 218 * {@link TIFFTag#TIFF_FLOAT} 219 * </td> 220 * <td> 221 * {@code float} 222 * </td> 223 * <td> 224 * {@code "Float"} 225 * </td> 226 * </tr> 227 * 228 * <tr> 229 * <td> 230 * <tt>DOUBLE</tt> 231 * </td> 232 * <td> 233 * {@link TIFFTag#TIFF_DOUBLE} 234 * </td> 235 * <td> 236 * {@code double} 237 * </td> 238 * <td> 239 * {@code "Double"} 240 * </td> 241 * </tr> 242 * 243 * <tr> 244 * <td> 245 * <tt>IFD</tt> 246 * </td> 247 * <td> 248 * {@link TIFFTag#TIFF_IFD_POINTER} 249 * </td> 250 * <td> 251 * {@code long} 252 * </td> 253 * <td> 254 * {@code "IFDPointer"} 255 * </td> 256 * </tr> 257 * 258 * </table> 259 * 260 * @since 9 261 * @see TIFFDirectory 262 * @see TIFFTag 263 */ 264 public final class TIFFField implements Cloneable { 265 266 private static final long MAX_UINT32 = 0xffffffffL; 267 268 private static final String[] TYPE_NAMES = { 269 null, 270 "Byte", "Ascii", "Short", "Long", "Rational", 271 "SByte", "Undefined", "SShort", "SLong", "SRational", 272 "Float", "Double", "IFDPointer" 273 }; 274 275 private static final boolean[] IS_INTEGRAL = { 276 false, 277 true, false, true, true, false, 278 true, true, true, true, false, 279 false, false, false 280 }; 281 282 /** The tag. */ 283 private TIFFTag tag; 284 285 /** The tag number. */ 286 private int tagNumber; 287 288 /** The tag type. */ 289 private int type; 290 291 /** The number of data items present in the field. */ 292 private int count; 293 294 /** The field data. */ 295 private Object data; 296 297 /** The IFD contents if available. This will usually be a TIFFIFD. */ 298 private TIFFDirectory dir; 299 300 /** The default constructor. */ 301 private TIFFField() {} 302 303 private static String getAttribute(Node node, String attrName) { 304 NamedNodeMap attrs = node.getAttributes(); 305 return attrs.getNamedItem(attrName).getNodeValue(); 306 } 307 308 private static void initData(Node node, 309 int[] otype, int[] ocount, Object[] odata) { 310 int type; 311 int count; 312 Object data = null; 313 314 String typeName = node.getNodeName(); 315 typeName = typeName.substring(4); 316 typeName = typeName.substring(0, typeName.length() - 1); 317 type = TIFFField.getTypeByName(typeName); 318 if (type == -1) { 319 throw new IllegalArgumentException("typeName = " + typeName); 320 } 321 322 Node child = node.getFirstChild(); 323 324 count = 0; 325 while (child != null) { 326 String childTypeName = child.getNodeName().substring(4); 327 if (!typeName.equals(childTypeName)) { 328 // warning 329 } 330 331 ++count; 332 child = child.getNextSibling(); 333 } 334 335 if (count > 0) { 336 data = createArrayForType(type, count); 337 child = node.getFirstChild(); 338 int idx = 0; 339 while (child != null) { 340 String value = getAttribute(child, "value"); 341 342 String numerator, denominator; 343 int slashPos; 344 345 switch (type) { 346 case TIFFTag.TIFF_ASCII: 347 ((String[])data)[idx] = value; 348 break; 349 case TIFFTag.TIFF_BYTE: 350 case TIFFTag.TIFF_SBYTE: 351 ((byte[])data)[idx] = 352 (byte)Integer.parseInt(value); 353 break; 354 case TIFFTag.TIFF_SHORT: 355 ((char[])data)[idx] = 356 (char)Integer.parseInt(value); 357 break; 358 case TIFFTag.TIFF_SSHORT: 359 ((short[])data)[idx] = 360 (short)Integer.parseInt(value); 361 break; 362 case TIFFTag.TIFF_SLONG: 363 ((int[])data)[idx] = 364 Integer.parseInt(value); 365 break; 366 case TIFFTag.TIFF_LONG: 367 case TIFFTag.TIFF_IFD_POINTER: 368 ((long[])data)[idx] = 369 Long.parseLong(value); 370 break; 371 case TIFFTag.TIFF_FLOAT: 372 ((float[])data)[idx] = 373 Float.parseFloat(value); 374 break; 375 case TIFFTag.TIFF_DOUBLE: 376 ((double[])data)[idx] = 377 Double.parseDouble(value); 378 break; 379 case TIFFTag.TIFF_SRATIONAL: 380 slashPos = value.indexOf("/"); 381 numerator = value.substring(0, slashPos); 382 denominator = value.substring(slashPos + 1); 383 384 ((int[][])data)[idx] = new int[2]; 385 ((int[][])data)[idx][0] = 386 Integer.parseInt(numerator); 387 ((int[][])data)[idx][1] = 388 Integer.parseInt(denominator); 389 break; 390 case TIFFTag.TIFF_RATIONAL: 391 slashPos = value.indexOf("/"); 392 numerator = value.substring(0, slashPos); 393 denominator = value.substring(slashPos + 1); 394 395 ((long[][])data)[idx] = new long[2]; 396 ((long[][])data)[idx][0] = 397 Long.parseLong(numerator); 398 ((long[][])data)[idx][1] = 399 Long.parseLong(denominator); 400 break; 401 default: 402 // error 403 } 404 405 idx++; 406 child = child.getNextSibling(); 407 } 408 } 409 410 otype[0] = type; 411 ocount[0] = count; 412 odata[0] = data; 413 } 414 415 /** 416 * Creates a {@code TIFFField} from a TIFF native image 417 * metadata node. If the value of the {@code "number"} attribute 418 * of the node is not found in {@code tagSet} then a new 419 * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME} 420 * will be created and assigned to the field. 421 * 422 * @param tagSet The {@code TIFFTagSet} to which the 423 * {@code TIFFTag} of the field belongs. 424 * @param node A native TIFF image metadata {@code TIFFField} node. 425 * @throws IllegalArgumentException If the {@code Node} parameter content 426 * does not adhere to the {@code TIFFField} element structure defined by 427 * the <a href="../../metadata/doc-files/tiff_metadata.html#ImageMetadata"> 428 * TIFF native image metadata format specification</a>, or if the 429 * combination of node attributes and data is not legal per the 430 * {@link #TIFFField(TIFFTag,int,int,Object)} constructor specification. 431 * Note that a cause might be set on such an exception. 432 * @return A new {@code TIFFField}. 433 */ 434 public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, 435 Node node) { 436 if (node == null) { 437 // This method is specified to throw only IllegalArgumentExceptions 438 // so we create an IAE with a NullPointerException as its cause. 439 throw new IllegalArgumentException(new NullPointerException 440 ("node == null!")); 441 } 442 String name = node.getNodeName(); 443 if (!name.equals("TIFFField")) { 444 throw new IllegalArgumentException("!name.equals(\"TIFFField\")"); 445 } 446 447 int tagNumber = Integer.parseInt(getAttribute(node, "number")); 448 TIFFTag tag = null; 449 if (tagSet != null) { 450 tag = tagSet.getTag(tagNumber); 451 } 452 453 int type = TIFFTag.TIFF_UNDEFINED; 454 int count = 0; 455 Object data = null; 456 457 Node child = node.getFirstChild(); 458 if (child != null) { 459 String typeName = child.getNodeName(); 460 if (typeName.equals("TIFFUndefined")) { 461 String values = getAttribute(child, "value"); 462 StringTokenizer st = new StringTokenizer(values, ","); 463 count = st.countTokens(); 464 465 byte[] bdata = new byte[count]; 466 for (int i = 0; i < count; i++) { 467 bdata[i] = (byte)Integer.parseInt(st.nextToken()); 468 } 469 470 type = TIFFTag.TIFF_UNDEFINED; 471 data = bdata; 472 } else { 473 int[] otype = new int[1]; 474 int[] ocount = new int[1]; 475 Object[] odata = new Object[1]; 476 477 initData(node.getFirstChild(), otype, ocount, odata); 478 type = otype[0]; 479 count = ocount[0]; 480 data = odata[0]; 481 } 482 } else if (tag != null) { 483 int t = TIFFTag.MAX_DATATYPE; 484 while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) { 485 t--; 486 } 487 type = t; 488 } 489 490 if (tag == null) { 491 tag = new TIFFTag(TIFFTag.UNKNOWN_TAG_NAME, tagNumber, 1 << type); 492 } 493 494 TIFFField field; 495 try { 496 field = new TIFFField(tag, type, count, data); 497 } catch (NullPointerException npe) { 498 // This method is specified to throw only IllegalArgumentExceptions 499 // so we catch the NullPointerException and set it as the cause of 500 // the IAE which is thrown. 501 throw new IllegalArgumentException(npe); 502 } 503 504 return field; 505 } 506 507 /** 508 * Constructs a {@code TIFFField} with arbitrary data. The 509 * {@code type} parameter must be a value for which 510 * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()} 511 * returns {@code true}. The {@code data} parameter must 512 * be an array of a Java type appropriate for the type of the TIFF 513 * field. 514 * 515 * <p>Note that the value (data) of the {@code TIFFField} 516 * will always be the actual field value regardless of the number of 517 * bytes required for that value. This is the case despite the fact 518 * that the TIFF <i>IFD Entry</i> corresponding to the field may 519 * actually contain the offset to the value of the field rather than 520 * the value itself (the latter occurring if and only if the 521 * value fits into 4 bytes). In other words, the value of the 522 * field will already have been read from the TIFF stream. (An exception 523 * to this case may occur when the field represents the contents of a 524 * non-baseline IFD. In that case the data will be a {@code long[]} 525 * containing the offset to the IFD and the {@code TIFFDirectory} 526 * returned by {@link #getDirectory()} will be its contents.) 527 * 528 * @param tag The tag to associated with this field. 529 * @param type One of the {@code TIFFTag.TIFF_*} constants 530 * indicating the data type of the field as written to the TIFF stream. 531 * @param count The number of data values. 532 * @param data The actual data content of the field. 533 * 534 * @throws NullPointerException if {@code tag == null}. 535 * @throws IllegalArgumentException if {@code type} is not 536 * one of the {@code TIFFTag.TIFF_*} data type constants. 537 * @throws IllegalArgumentException if {@code type} is an unacceptable 538 * data type for the supplied {@code TIFFTag}. 539 * @throws IllegalArgumentException if {@code count < 0}. 540 * @throws IllegalArgumentException if {@code count < 1} 541 * and {@code type} is {@code TIFF_RATIONAL} or 542 * {@code TIFF_SRATIONAL}. 543 * @throws IllegalArgumentException if {@code count != 1} 544 * and {@code type} is {@code TIFF_IFD_POINTER}. 545 * @throws NullPointerException if {@code data == null}. 546 * @throws IllegalArgumentException if {@code data} is an instance of 547 * a class incompatible with the specified type. 548 * @throws IllegalArgumentException if the size of the data array is wrong. 549 * @throws IllegalArgumentException if the type of the data array is 550 * {@code TIFF_LONG}, {@code TIFF_RATIONAL}, or {@code TIFF_IFD_POINTER} 551 * and any of the elements is negative or greater than {@code 0xffffffff}. 552 */ 553 public TIFFField(TIFFTag tag, int type, int count, Object data) { 554 if(tag == null) { 555 throw new NullPointerException("tag == null!"); 556 } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) { 557 throw new IllegalArgumentException("Unknown data type "+type); 558 } else if(!tag.isDataTypeOK(type)) { 559 throw new IllegalArgumentException("Illegal data type " + type 560 + " for " + tag.getName() + " tag"); 561 } else if(count < 0) { 562 throw new IllegalArgumentException("count < 0!"); 563 } else if((type == TIFFTag.TIFF_RATIONAL 564 || type == TIFFTag.TIFF_SRATIONAL) 565 && count < 1) { 566 throw new IllegalArgumentException 567 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); 568 } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) { 569 throw new IllegalArgumentException 570 ("Type is TIFF_IFD_POINTER and count != 1"); 571 } else if(data == null) { 572 throw new NullPointerException("data == null!"); 573 } 574 575 boolean isDataArrayCorrect = false; 576 577 switch (type) { 578 case TIFFTag.TIFF_BYTE: 579 case TIFFTag.TIFF_SBYTE: 580 case TIFFTag.TIFF_UNDEFINED: 581 isDataArrayCorrect = data instanceof byte[] 582 && ((byte[])data).length == count; 583 break; 584 case TIFFTag.TIFF_ASCII: 585 isDataArrayCorrect = data instanceof String[] 586 && ((String[])data).length == count; 587 break; 588 case TIFFTag.TIFF_SHORT: 589 isDataArrayCorrect = data instanceof char[] 590 && ((char[])data).length == count; 591 break; 592 case TIFFTag.TIFF_LONG: 593 isDataArrayCorrect = data instanceof long[] 594 && ((long[])data).length == count; 595 if (isDataArrayCorrect) { 596 for (long datum : (long[])data) { 597 if (datum < 0) { 598 throw new IllegalArgumentException 599 ("Negative value supplied for TIFF_LONG"); 600 } 601 if (datum > MAX_UINT32) { 602 throw new IllegalArgumentException 603 ("Too large value supplied for TIFF_LONG"); 604 } 605 } 606 } 607 break; 608 case TIFFTag.TIFF_IFD_POINTER: 609 isDataArrayCorrect = data instanceof long[] 610 && ((long[])data).length == 1; 611 if (((long[])data)[0] < 0) { 612 throw new IllegalArgumentException 613 ("Negative value supplied for TIFF_IFD_POINTER"); 614 } 615 if (((long[])data)[0] > MAX_UINT32) { 616 throw new IllegalArgumentException 617 ("Too large value supplied for TIFF_IFD_POINTER"); 618 } 619 break; 620 case TIFFTag.TIFF_RATIONAL: 621 isDataArrayCorrect = data instanceof long[][] 622 && ((long[][])data).length == count; 623 if (isDataArrayCorrect) { 624 for (long[] datum : (long[][])data) { 625 if (datum.length != 2) { 626 isDataArrayCorrect = false; 627 break; 628 } 629 if (datum[0] < 0 || datum[1] < 0) { 630 throw new IllegalArgumentException 631 ("Negative value supplied for TIFF_RATIONAL"); 632 } 633 if (datum[0] > MAX_UINT32 || datum[1] > MAX_UINT32) { 634 throw new IllegalArgumentException 635 ("Too large value supplied for TIFF_RATIONAL"); 636 } 637 } 638 } 639 break; 640 case TIFFTag.TIFF_SSHORT: 641 isDataArrayCorrect = data instanceof short[] 642 && ((short[])data).length == count; 643 break; 644 case TIFFTag.TIFF_SLONG: 645 isDataArrayCorrect = data instanceof int[] 646 && ((int[])data).length == count; 647 break; 648 case TIFFTag.TIFF_SRATIONAL: 649 isDataArrayCorrect = data instanceof int[][] 650 && ((int[][])data).length == count; 651 if (isDataArrayCorrect) { 652 for (int[] datum : (int[][])data) { 653 if (datum.length != 2) { 654 isDataArrayCorrect = false; 655 break; 656 } 657 } 658 } 659 break; 660 case TIFFTag.TIFF_FLOAT: 661 isDataArrayCorrect = data instanceof float[] 662 && ((float[])data).length == count; 663 break; 664 case TIFFTag.TIFF_DOUBLE: 665 isDataArrayCorrect = data instanceof double[] 666 && ((double[])data).length == count; 667 break; 668 default: 669 throw new IllegalArgumentException("Unknown data type "+type); 670 } 671 672 if (!isDataArrayCorrect) { 673 throw new IllegalArgumentException 674 ("Illegal class or length for data array"); 675 } 676 677 this.tag = tag; 678 this.tagNumber = tag.getNumber(); 679 this.type = type; 680 this.count = count; 681 this.data = data; 682 } 683 684 /** 685 * Constructs a data array using {@link #createArrayForType 686 * createArrayForType()} and invokes 687 * {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied 688 * parameters and the created array. 689 * 690 * @param tag The tag to associated with this field. 691 * @param type One of the {@code TIFFTag.TIFF_*} constants 692 * indicating the data type of the field as written to the TIFF stream. 693 * @param count The number of data values. 694 * @throws NullPointerException if {@code tag == null}. 695 * @throws IllegalArgumentException if {@code type} is not 696 * one of the {@code TIFFTag.TIFF_*} data type constants. 697 * @throws IllegalArgumentException if {@code type} is an unacceptable 698 * data type for the supplied {@code TIFFTag}. 699 * @throws IllegalArgumentException if {@code count < 0}. 700 * @see #TIFFField(TIFFTag,int,int,Object) 701 * @throws IllegalArgumentException if {@code count < 1} 702 * and {@code type} is {@code TIFF_RATIONAL} or 703 * {@code TIFF_SRATIONAL}. 704 * @throws IllegalArgumentException if {@code count != 1} 705 * and {@code type} is {@code TIFF_IFD_POINTER}. 706 */ 707 public TIFFField(TIFFTag tag, int type, int count) { 708 this(tag, type, count, createArrayForType(type, count)); 709 } 710 711 /** 712 * Constructs a {@code TIFFField} with a single non-negative integral 713 * value. The field will have type {@link TIFFTag#TIFF_SHORT TIFF_SHORT} 714 * if {@code value} is in {@code [0,0xffff]}, and type 715 * {@link TIFFTag#TIFF_LONG TIFF_LONG} if {@code value} is in 716 * {@code [0x10000,0xffffffff]}. The count of the field will be unity. 717 * 718 * @param tag The tag to associate with this field. 719 * @param value The value to associate with this field. 720 * @throws NullPointerException if {@code tag == null}. 721 * @throws IllegalArgumentException if {@code value} is not in 722 * {@code [0,0xffffffff]}. 723 * @throws IllegalArgumentException if {@code value} is in 724 * {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type 725 * for the {@code TIFFTag}, or if {@code value} is in 726 * {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable 727 * type for the {@code TIFFTag}. 728 */ 729 public TIFFField(TIFFTag tag, long value) { 730 if(tag == null) { 731 throw new NullPointerException("tag == null!"); 732 } 733 if (value < 0) { 734 throw new IllegalArgumentException("value < 0!"); 735 } 736 if (value > MAX_UINT32) { 737 throw new IllegalArgumentException("value > 0xffffffff!"); 738 } 739 740 this.tag = tag; 741 this.tagNumber = tag.getNumber(); 742 this.count = 1; 743 744 if (value < 65536) { 745 if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) { 746 throw new IllegalArgumentException("Illegal data type " 747 + getTypeName(TIFFTag.TIFF_SHORT) + " for tag " 748 + "\"" + tag.getName() + "\""); 749 } 750 this.type = TIFFTag.TIFF_SHORT; 751 char[] cdata = new char[1]; 752 cdata[0] = (char)value; 753 this.data = cdata; 754 } else { 755 if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) { 756 throw new IllegalArgumentException("Illegal data type " 757 + getTypeName(TIFFTag.TIFF_LONG) + " for tag " 758 + "\"" + tag.getName() + "\""); 759 } 760 this.type = TIFFTag.TIFF_LONG; 761 long[] ldata = new long[1]; 762 ldata[0] = value; 763 this.data = ldata; 764 } 765 } 766 767 /** 768 * Constructs a {@code TIFFField} with an IFD offset and contents. 769 * The offset will be stored as the data of this field as 770 * {@code long[] {offset}}. The directory will not be cloned. The count 771 * of the field will be unity. 772 * 773 * @param tag The tag to associated with this field. 774 * @param type One of the constants {@code TIFFTag.TIFF_LONG} or 775 * {@code TIFFTag.TIFF_IFD_POINTER}. 776 * @param offset The IFD offset. 777 * @param dir The directory. 778 * 779 * @throws NullPointerException if {@code tag == null}. 780 * @throws IllegalArgumentException if {@code type} is an unacceptable 781 * data type for the supplied {@code TIFFTag}. 782 * @throws IllegalArgumentException if {@code type} is neither 783 * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}. 784 * @throws IllegalArgumentException if {@code offset <= 0}. 785 * @throws NullPointerException if {@code dir == null}. 786 * 787 * @see #TIFFField(TIFFTag,int,int,Object) 788 */ 789 public TIFFField(TIFFTag tag, int type, long offset, TIFFDirectory dir) { 790 if (tag == null) { 791 throw new NullPointerException("tag == null!"); 792 } else if (type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) { 793 throw new IllegalArgumentException("Unknown data type "+type); 794 } else if (!tag.isDataTypeOK(type)) { 795 throw new IllegalArgumentException("Illegal data type " + type 796 + " for " + tag.getName() + " tag"); 797 } else if (type != TIFFTag.TIFF_LONG 798 && type != TIFFTag.TIFF_IFD_POINTER) { 799 throw new IllegalArgumentException("type " + type 800 + " is neither TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER"); 801 } else if (offset <= 0) { 802 throw new IllegalArgumentException("offset " + offset 803 + " is non-positive"); 804 } else if (dir == null) { 805 throw new NullPointerException("dir == null"); 806 } 807 808 this.tag = tag; 809 this.tagNumber = tag.getNumber(); 810 this.type = type; 811 this.count = 1; 812 this.data = new long[] {offset}; 813 814 this.dir = dir; 815 } 816 817 /** 818 * Retrieves the tag associated with this field. 819 * 820 * @return The associated {@code TIFFTag}. 821 */ 822 public TIFFTag getTag() { 823 return tag; 824 } 825 826 /** 827 * Retrieves the tag number in the range {@code [0,65535]}. 828 * 829 * @return The tag number. 830 */ 831 public int getTagNumber() { 832 return tagNumber; 833 } 834 835 /** 836 * Returns the type of the data stored in the field. For a TIFF 6.0 837 * stream, the value will equal one of the {@code TIFFTag.TIFF_*} 838 * constants. For future revisions of TIFF, higher values are possible. 839 * 840 * @return The data type of the field value. 841 */ 842 public int getType() { 843 return type; 844 } 845 846 /** 847 * Returns the name of the supplied data type constant. 848 * 849 * @param dataType One of the {@code TIFFTag.TIFF_*} constants 850 * indicating the data type of the field as written to the TIFF stream. 851 * @return The type name corresponding to the supplied type constant. 852 * @throws IllegalArgumentException if {@code dataType} is not 853 * one of the {@code TIFFTag.TIFF_*} data type constants. 854 */ 855 public static String getTypeName(int dataType) { 856 if (dataType < TIFFTag.MIN_DATATYPE || 857 dataType > TIFFTag.MAX_DATATYPE) { 858 throw new IllegalArgumentException("Unknown data type "+dataType); 859 } 860 861 return TYPE_NAMES[dataType]; 862 } 863 864 /** 865 * Returns the data type constant corresponding to the supplied data 866 * type name. If the name is unknown {@code -1} will be returned. 867 * 868 * @param typeName The type name. 869 * @return One of the {@code TIFFTag.TIFF_*} constants or 870 * {@code -1} if the name is not recognized. 871 */ 872 public static int getTypeByName(String typeName) { 873 for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { 874 if (typeName.equals(TYPE_NAMES[i])) { 875 return i; 876 } 877 } 878 879 return -1; 880 } 881 882 /** 883 * Creates an array appropriate for the indicated data type. 884 * 885 * @param dataType One of the {@code TIFFTag.TIFF_*} data type 886 * constants. 887 * @param count The number of values in the array. 888 * @return An array appropriate for the specified data type. 889 * 890 * @throws IllegalArgumentException if {@code dataType} is not 891 * one of the {@code TIFFTag.TIFF_*} data type constants. 892 * @throws IllegalArgumentException if {@code count < 0}. 893 * @throws IllegalArgumentException if {@code count < 1} 894 * and {@code type} is {@code TIFF_RATIONAL} or 895 * {@code TIFF_SRATIONAL}. 896 * @throws IllegalArgumentException if {@code count != 1} 897 * and {@code type} is {@code TIFF_IFD_POINTER}. 898 */ 899 public static Object createArrayForType(int dataType, int count) { 900 901 if(count < 0) { 902 throw new IllegalArgumentException("count < 0!"); 903 } else if ((dataType == TIFFTag.TIFF_RATIONAL 904 || dataType == TIFFTag.TIFF_SRATIONAL) 905 && count < 1) { 906 throw new IllegalArgumentException 907 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); 908 } else if (dataType == TIFFTag.TIFF_IFD_POINTER && count != 1) { 909 throw new IllegalArgumentException 910 ("Type is TIFF_IFD_POINTER and count != 1"); 911 } 912 913 switch (dataType) { 914 case TIFFTag.TIFF_BYTE: 915 case TIFFTag.TIFF_SBYTE: 916 case TIFFTag.TIFF_UNDEFINED: 917 return new byte[count]; 918 case TIFFTag.TIFF_ASCII: 919 return new String[count]; 920 case TIFFTag.TIFF_SHORT: 921 return new char[count]; 922 case TIFFTag.TIFF_LONG: 923 case TIFFTag.TIFF_IFD_POINTER: 924 return new long[count]; 925 case TIFFTag.TIFF_RATIONAL: 926 return new long[count][2]; 927 case TIFFTag.TIFF_SSHORT: 928 return new short[count]; 929 case TIFFTag.TIFF_SLONG: 930 return new int[count]; 931 case TIFFTag.TIFF_SRATIONAL: 932 return new int[count][2]; 933 case TIFFTag.TIFF_FLOAT: 934 return new float[count]; 935 case TIFFTag.TIFF_DOUBLE: 936 return new double[count]; 937 default: 938 throw new IllegalArgumentException("Unknown data type "+dataType); 939 } 940 } 941 942 /** 943 * Returns the {@code TIFFField} as a node named either 944 * <tt>"TIFFField"</tt> or <tt>"TIFFIFD"</tt> as described in the 945 * TIFF native image metadata specification. The node will be named 946 * <tt>"TIFFIFD"</tt> if and only if {@link #hasDirectory()} returns 947 * {@code true} and the field's type is either {@link TIFFTag#TIFF_LONG} 948 * or {@link TIFFTag#TIFF_IFD_POINTER}. 949 * 950 * @return a {@code Node} named <tt>"TIFFField"</tt> or 951 * <tt>"TIFFIFD"</tt>. 952 */ 953 public Node getAsNativeNode() { 954 return new TIFFFieldNode(this); 955 } 956 957 /** 958 * Indicates whether the value associated with the field is of 959 * integral data type. 960 * 961 * @return Whether the field type is integral. 962 */ 963 public boolean isIntegral() { 964 return IS_INTEGRAL[type]; 965 } 966 967 /** 968 * Returns the number of data items present in the field. For 969 * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the 970 * number of {@code String}s, not the total length of the 971 * data as in the file representation. 972 * 973 * @return The number of data items present in the field. 974 */ 975 public int getCount() { 976 return count; 977 } 978 979 /** 980 * Returns a reference to the data object associated with the field. 981 * 982 * @return The data object of the field. 983 */ 984 public Object getData() { 985 return data; 986 } 987 988 /** 989 * Returns the data as an uninterpreted array of 990 * {@code byte}s. The type of the field must be one of 991 * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or 992 * {@code TIFF_UNDEFINED}. 993 * 994 * <p> For data in {@code TIFFTag.TIFF_BYTE} format, the application 995 * must take care when promoting the data to longer integral types 996 * to avoid sign extension. 997 * 998 * @throws ClassCastException if the field is not of type 999 * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or 1000 * {@code TIFF_UNDEFINED}. 1001 * @return The data as an uninterpreted array of bytes. 1002 */ 1003 public byte[] getAsBytes() { 1004 return (byte[])data; 1005 } 1006 1007 /** 1008 * Returns {@code TIFFTag.TIFF_SHORT} data as an array of 1009 * {@code char}s (unsigned 16-bit integers). 1010 * 1011 * @throws ClassCastException if the field is not of type 1012 * {@code TIFF_SHORT}. 1013 * @return The data as an array of {@code char}s. 1014 */ 1015 public char[] getAsChars() { 1016 return (char[])data; 1017 } 1018 1019 /** 1020 * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of 1021 * {@code short}s (signed 16-bit integers). 1022 * 1023 * @throws ClassCastException if the field is not of type 1024 * {@code TIFF_SSHORT}. 1025 * @return The data as an array of {@code short}s. 1026 */ 1027 public short[] getAsShorts() { 1028 return (short[])data; 1029 } 1030 1031 /** 1032 * Returns {@code TIFFTag.TIFF_SLONG} data as an array of 1033 * {@code int}s (signed 32-bit integers). 1034 * 1035 * @throws ClassCastException if the field is not of type 1036 * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or 1037 * {@code TIFF_SLONG}. 1038 * @return The data as an array of {@code int}s. 1039 */ 1040 public int[] getAsInts() { 1041 if (data instanceof int[]) { 1042 return (int[])data; 1043 } else if (data instanceof char[]){ 1044 char[] cdata = (char[])data; 1045 int[] idata = new int[cdata.length]; 1046 for (int i = 0; i < cdata.length; i++) { 1047 idata[i] = cdata[i] & 0xffff; 1048 } 1049 return idata; 1050 } else if (data instanceof short[]){ 1051 short[] sdata = (short[])data; 1052 int[] idata = new int[sdata.length]; 1053 for (int i = 0; i < sdata.length; i++) { 1054 idata[i] = (int)sdata[i]; 1055 } 1056 return idata; 1057 } else { 1058 throw new ClassCastException("Data not char[], short[], or int[]!"); 1059 } 1060 } 1061 1062 /** 1063 * Returns {@code TIFFTag.TIFF_LONG} or 1064 * {@code TIFF_IFD_POINTER} data as an array of 1065 * {@code long}s (signed 64-bit integers). 1066 * 1067 * @throws ClassCastException if the field is not of type 1068 * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}. 1069 * @return The data as an array of {@code long}s. 1070 */ 1071 public long[] getAsLongs() { 1072 return (long[])data; 1073 } 1074 1075 /** 1076 * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of 1077 * {@code float}s (32-bit floating-point values). 1078 * 1079 * @throws ClassCastException if the field is not of type 1080 * {@code TIFF_FLOAT}. 1081 * @return The data as an array of {@code float}s. 1082 */ 1083 public float[] getAsFloats() { 1084 return (float[])data; 1085 } 1086 1087 /** 1088 * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of 1089 * {@code double}s (64-bit floating-point values). 1090 * 1091 * @throws ClassCastException if the field is not of type 1092 * {@code TIFF_DOUBLE}. 1093 * @return The data as an array of {@code double}s. 1094 */ 1095 public double[] getAsDoubles() { 1096 return (double[])data; 1097 } 1098 1099 /** 1100 * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of 1101 * 2-element arrays of {@code int}s. 1102 * 1103 * @throws ClassCastException if the field is not of type 1104 * {@code TIFF_SRATIONAL}. 1105 * @return The data as an array of signed rationals. 1106 */ 1107 public int[][] getAsSRationals() { 1108 return (int[][])data; 1109 } 1110 1111 /** 1112 * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of 1113 * 2-element arrays of {@code long}s. 1114 * 1115 * @throws ClassCastException if the field is not of type 1116 * {@code TIFF_RATIONAL}. 1117 * @return The data as an array of unsigned rationals. 1118 */ 1119 public long[][] getAsRationals() { 1120 return (long[][])data; 1121 } 1122 1123 /** 1124 * Returns data in any format as an {@code int}. 1125 * 1126 * <p> {@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that 1127 * is, no sign extension will take place and the returned value 1128 * will be in the range [0, 255]. {@code TIFF_SBYTE} data 1129 * will be returned in the range [-128, 127]. 1130 * 1131 * <p> A {@code TIFF_UNDEFINED} value is treated as though 1132 * it were a {@code TIFF_BYTE}. 1133 * 1134 * <p> Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, 1135 * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or 1136 * {@code TIFF_IFD_POINTER} format are simply cast to 1137 * {@code int} and may suffer from truncation. 1138 * 1139 * <p> Data in {@code TIFF_SRATIONAL} or 1140 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1141 * numerator into the denominator using double-precision 1142 * arithmetic and then casting to {@code int}. Loss of 1143 * precision and truncation may occur. 1144 * 1145 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1146 * the {@code Double.parseDouble} method, with the result 1147 * case to {@code int}. 1148 * 1149 * @param index The index of the data. 1150 * @return The data at the given index as an {@code int}. 1151 */ 1152 public int getAsInt(int index) { 1153 switch (type) { 1154 case TIFFTag.TIFF_BYTE: 1155 case TIFFTag.TIFF_UNDEFINED: 1156 return ((byte[])data)[index] & 0xff; 1157 case TIFFTag.TIFF_SBYTE: 1158 return ((byte[])data)[index]; 1159 case TIFFTag.TIFF_SHORT: 1160 return ((char[])data)[index] & 0xffff; 1161 case TIFFTag.TIFF_SSHORT: 1162 return ((short[])data)[index]; 1163 case TIFFTag.TIFF_SLONG: 1164 return ((int[])data)[index]; 1165 case TIFFTag.TIFF_LONG: 1166 case TIFFTag.TIFF_IFD_POINTER: 1167 return (int)((long[])data)[index]; 1168 case TIFFTag.TIFF_FLOAT: 1169 return (int)((float[])data)[index]; 1170 case TIFFTag.TIFF_DOUBLE: 1171 return (int)((double[])data)[index]; 1172 case TIFFTag.TIFF_SRATIONAL: 1173 int[] ivalue = getAsSRational(index); 1174 return (int)((double)ivalue[0]/ivalue[1]); 1175 case TIFFTag.TIFF_RATIONAL: 1176 long[] lvalue = getAsRational(index); 1177 return (int)((double)lvalue[0]/lvalue[1]); 1178 case TIFFTag.TIFF_ASCII: 1179 String s = ((String[])data)[index]; 1180 return (int)Double.parseDouble(s); 1181 default: 1182 throw new ClassCastException(); // should never happen 1183 } 1184 } 1185 1186 /** 1187 * Returns data in any format as a {@code long}. 1188 * 1189 * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data 1190 * are treated as unsigned; that is, no sign extension will take 1191 * place and the returned value will be in the range [0, 255]. 1192 * {@code TIFF_SBYTE} data will be returned in the range 1193 * [-128, 127]. 1194 * 1195 * <p> Data in {@code TIFF_FLOAT} and {@code TIFF_DOUBLE} are 1196 * simply cast to {@code long} and may suffer from truncation. 1197 * 1198 * <p> Data in {@code TIFF_SRATIONAL} or 1199 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1200 * numerator into the denominator using double-precision 1201 * arithmetic and then casting to {@code long}. Loss of 1202 * precision and truncation may occur. 1203 * 1204 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1205 * the {@code Double.parseDouble} method, with the result 1206 * cast to {@code long}. 1207 * 1208 * @param index The index of the data. 1209 * @return The data at the given index as a {@code long}. 1210 */ 1211 public long getAsLong(int index) { 1212 switch (type) { 1213 case TIFFTag.TIFF_BYTE: 1214 case TIFFTag.TIFF_UNDEFINED: 1215 return ((byte[])data)[index] & 0xff; 1216 case TIFFTag.TIFF_SBYTE: 1217 return ((byte[])data)[index]; 1218 case TIFFTag.TIFF_SHORT: 1219 return ((char[])data)[index] & 0xffff; 1220 case TIFFTag.TIFF_SSHORT: 1221 return ((short[])data)[index]; 1222 case TIFFTag.TIFF_SLONG: 1223 return ((int[])data)[index]; 1224 case TIFFTag.TIFF_LONG: 1225 case TIFFTag.TIFF_IFD_POINTER: 1226 return ((long[])data)[index]; 1227 case TIFFTag.TIFF_FLOAT: 1228 return (long)((float[])data)[index]; 1229 case TIFFTag.TIFF_DOUBLE: 1230 return (long)((double[])data)[index]; 1231 case TIFFTag.TIFF_SRATIONAL: 1232 int[] ivalue = getAsSRational(index); 1233 return (long)((double)ivalue[0]/ivalue[1]); 1234 case TIFFTag.TIFF_RATIONAL: 1235 long[] lvalue = getAsRational(index); 1236 return (long)((double)lvalue[0]/lvalue[1]); 1237 case TIFFTag.TIFF_ASCII: 1238 String s = ((String[])data)[index]; 1239 return (long)Double.parseDouble(s); 1240 default: 1241 throw new ClassCastException(); // should never happen 1242 } 1243 } 1244 1245 /** 1246 * Returns data in any format as a {@code float}. 1247 * 1248 * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data 1249 * are treated as unsigned; that is, no sign extension will take 1250 * place and the returned value will be in the range [0, 255]. 1251 * {@code TIFF_SBYTE} data will be returned in the range 1252 * [-128, 127]. 1253 * 1254 * <p> Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, 1255 * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are 1256 * simply cast to {@code float} and may suffer from 1257 * truncation. 1258 * 1259 * <p> Data in {@code TIFF_SRATIONAL} or 1260 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1261 * numerator into the denominator using double-precision 1262 * arithmetic and then casting to {@code float}. 1263 * 1264 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1265 * the {@code Double.parseDouble} method, with the result 1266 * cast to {@code float}. 1267 * 1268 * @param index The index of the data. 1269 * @return The data at the given index as a {@code float}. 1270 */ 1271 public float getAsFloat(int index) { 1272 switch (type) { 1273 case TIFFTag.TIFF_BYTE: 1274 case TIFFTag.TIFF_UNDEFINED: 1275 return ((byte[])data)[index] & 0xff; 1276 case TIFFTag.TIFF_SBYTE: 1277 return ((byte[])data)[index]; 1278 case TIFFTag.TIFF_SHORT: 1279 return ((char[])data)[index] & 0xffff; 1280 case TIFFTag.TIFF_SSHORT: 1281 return ((short[])data)[index]; 1282 case TIFFTag.TIFF_SLONG: 1283 return ((int[])data)[index]; 1284 case TIFFTag.TIFF_LONG: 1285 case TIFFTag.TIFF_IFD_POINTER: 1286 return ((long[])data)[index]; 1287 case TIFFTag.TIFF_FLOAT: 1288 return ((float[])data)[index]; 1289 case TIFFTag.TIFF_DOUBLE: 1290 return (float)((double[])data)[index]; 1291 case TIFFTag.TIFF_SRATIONAL: 1292 int[] ivalue = getAsSRational(index); 1293 return (float)((double)ivalue[0]/ivalue[1]); 1294 case TIFFTag.TIFF_RATIONAL: 1295 long[] lvalue = getAsRational(index); 1296 return (float)((double)lvalue[0]/lvalue[1]); 1297 case TIFFTag.TIFF_ASCII: 1298 String s = ((String[])data)[index]; 1299 return (float)Double.parseDouble(s); 1300 default: 1301 throw new ClassCastException(); // should never happen 1302 } 1303 } 1304 1305 /** 1306 * Returns data in any format as a {@code double}. 1307 * 1308 * <p> {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data 1309 * are treated as unsigned; that is, no sign extension will take 1310 * place and the returned value will be in the range [0, 255]. 1311 * {@code TIFF_SBYTE} data will be returned in the range 1312 * [-128, 127]. 1313 * 1314 * <p> Data in {@code TIFF_SRATIONAL} or 1315 * {@code TIFF_RATIONAL} format are evaluated by dividing the 1316 * numerator into the denominator using double-precision 1317 * arithmetic. 1318 * 1319 * <p> Data in {@code TIFF_ASCII} format will be parsed as by 1320 * the {@code Double.parseDouble} method. 1321 * 1322 * @param index The index of the data. 1323 * @return The data at the given index as a {@code double}. 1324 */ 1325 public double getAsDouble(int index) { 1326 switch (type) { 1327 case TIFFTag.TIFF_BYTE: 1328 case TIFFTag.TIFF_UNDEFINED: 1329 return ((byte[])data)[index] & 0xff; 1330 case TIFFTag.TIFF_SBYTE: 1331 return ((byte[])data)[index]; 1332 case TIFFTag.TIFF_SHORT: 1333 return ((char[])data)[index] & 0xffff; 1334 case TIFFTag.TIFF_SSHORT: 1335 return ((short[])data)[index]; 1336 case TIFFTag.TIFF_SLONG: 1337 return ((int[])data)[index]; 1338 case TIFFTag.TIFF_LONG: 1339 case TIFFTag.TIFF_IFD_POINTER: 1340 return ((long[])data)[index]; 1341 case TIFFTag.TIFF_FLOAT: 1342 return ((float[])data)[index]; 1343 case TIFFTag.TIFF_DOUBLE: 1344 return ((double[])data)[index]; 1345 case TIFFTag.TIFF_SRATIONAL: 1346 int[] ivalue = getAsSRational(index); 1347 return (double)ivalue[0]/ivalue[1]; 1348 case TIFFTag.TIFF_RATIONAL: 1349 long[] lvalue = getAsRational(index); 1350 return (double)lvalue[0]/lvalue[1]; 1351 case TIFFTag.TIFF_ASCII: 1352 String s = ((String[])data)[index]; 1353 return Double.parseDouble(s); 1354 default: 1355 throw new ClassCastException(); // should never happen 1356 } 1357 } 1358 1359 /** 1360 * Returns a {@code TIFFTag.TIFF_ASCII} value as a 1361 * {@code String}. 1362 * 1363 * @throws ClassCastException if the field is not of type 1364 * {@code TIFF_ASCII}. 1365 * 1366 * @param index The index of the data. 1367 * @return The data at the given index as a {@code String}. 1368 */ 1369 public String getAsString(int index) { 1370 return ((String[])data)[index]; 1371 } 1372 1373 /** 1374 * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a 1375 * two-element array of {@code int}s. 1376 * 1377 * @param index The index of the data. 1378 * @return The data at the given index as a signed rational. 1379 * @throws ClassCastException if the field is not of type 1380 * {@code TIFF_SRATIONAL}. 1381 */ 1382 public int[] getAsSRational(int index) { 1383 return ((int[][])data)[index]; 1384 } 1385 1386 /** 1387 * Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array 1388 * of ints. 1389 * 1390 * @param index The index of the data. 1391 * @return The data at the given index as an unsigned rational. 1392 * @throws ClassCastException if the field is not of type 1393 * {@code TIFF_RATIONAL}. 1394 */ 1395 public long[] getAsRational(int index) { 1396 return ((long[][])data)[index]; 1397 } 1398 1399 1400 /** 1401 * Returns a {@code String} containing a human-readable 1402 * version of the data item. Data of type 1403 * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are 1404 * represented as a pair of integers separated by a 1405 * {@code '/'} character. If the numerator of a 1406 * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} is an integral 1407 * multiple of the denominator, then the value is represented as 1408 * {@code "q/1"} where {@code q} is the quotient of the numerator and 1409 * denominator. 1410 * 1411 * @param index The index of the data. 1412 * @return The data at the given index as a {@code String}. 1413 * @throws ClassCastException if the field is not of one of the 1414 * legal field types. 1415 */ 1416 public String getValueAsString(int index) { 1417 switch (type) { 1418 case TIFFTag.TIFF_ASCII: 1419 return ((String[])data)[index]; 1420 case TIFFTag.TIFF_BYTE: 1421 case TIFFTag.TIFF_UNDEFINED: 1422 return Integer.toString(((byte[])data)[index] & 0xff); 1423 case TIFFTag.TIFF_SBYTE: 1424 return Integer.toString(((byte[])data)[index]); 1425 case TIFFTag.TIFF_SHORT: 1426 return Integer.toString(((char[])data)[index] & 0xffff); 1427 case TIFFTag.TIFF_SSHORT: 1428 return Integer.toString(((short[])data)[index]); 1429 case TIFFTag.TIFF_SLONG: 1430 return Integer.toString(((int[])data)[index]); 1431 case TIFFTag.TIFF_LONG: 1432 case TIFFTag.TIFF_IFD_POINTER: 1433 return Long.toString(((long[])data)[index]); 1434 case TIFFTag.TIFF_FLOAT: 1435 return Float.toString(((float[])data)[index]); 1436 case TIFFTag.TIFF_DOUBLE: 1437 return Double.toString(((double[])data)[index]); 1438 case TIFFTag.TIFF_SRATIONAL: 1439 int[] ivalue = getAsSRational(index); 1440 String srationalString; 1441 if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) { 1442 // If the denominator is a non-zero integral divisor 1443 // of the numerator then convert the fraction to be 1444 // with respect to a unity denominator. 1445 srationalString = 1446 Integer.toString(ivalue[0] / ivalue[1]) + "/1"; 1447 } else { 1448 // Use the values directly. 1449 srationalString = 1450 Integer.toString(ivalue[0]) + 1451 "/" + 1452 Integer.toString(ivalue[1]); 1453 } 1454 return srationalString; 1455 case TIFFTag.TIFF_RATIONAL: 1456 long[] lvalue = getAsRational(index); 1457 String rationalString; 1458 if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) { 1459 // If the denominator is a non-zero integral divisor 1460 // of the numerator then convert the fraction to be 1461 // with respect to a unity denominator. 1462 rationalString = 1463 Long.toString(lvalue[0] / lvalue[1]) + "/1"; 1464 } else { 1465 // Use the values directly. 1466 rationalString = 1467 Long.toString(lvalue[0]) + 1468 "/" + 1469 Long.toString(lvalue[1]); 1470 } 1471 return rationalString; 1472 default: 1473 throw new ClassCastException(); // should never happen 1474 } 1475 } 1476 1477 /** 1478 * Returns whether the field has a {@code TIFFDirectory}. 1479 * 1480 * @return true if and only if getDirectory() returns non-null. 1481 */ 1482 public boolean hasDirectory() { 1483 return getDirectory() != null; 1484 } 1485 1486 /** 1487 * Returns the associated {@code TIFFDirectory}, if available. If no 1488 * directory is set, then {@code null} will be returned. 1489 * 1490 * @return the TIFFDirectory instance or null. 1491 */ 1492 public TIFFDirectory getDirectory() { 1493 return dir; 1494 } 1495 1496 /** 1497 * Clones the field and all the information contained therein. 1498 * 1499 * @return A clone of this {@code TIFFField}. 1500 * @throws CloneNotSupportedException if the instance cannot be cloned. 1501 */ 1502 @Override 1503 public TIFFField clone() throws CloneNotSupportedException { 1504 TIFFField field = (TIFFField)super.clone(); 1505 1506 Object fieldData; 1507 switch (type) { 1508 case TIFFTag.TIFF_BYTE: 1509 case TIFFTag.TIFF_UNDEFINED: 1510 case TIFFTag.TIFF_SBYTE: 1511 fieldData = ((byte[])data).clone(); 1512 break; 1513 case TIFFTag.TIFF_SHORT: 1514 fieldData = ((char[])data).clone(); 1515 break; 1516 case TIFFTag.TIFF_SSHORT: 1517 fieldData = ((short[])data).clone(); 1518 break; 1519 case TIFFTag.TIFF_SLONG: 1520 fieldData = ((int[])data).clone(); 1521 break; 1522 case TIFFTag.TIFF_LONG: 1523 case TIFFTag.TIFF_IFD_POINTER: 1524 fieldData = ((long[])data).clone(); 1525 break; 1526 case TIFFTag.TIFF_FLOAT: 1527 fieldData = ((float[])data).clone(); 1528 break; 1529 case TIFFTag.TIFF_DOUBLE: 1530 fieldData = ((double[])data).clone(); 1531 break; 1532 case TIFFTag.TIFF_SRATIONAL: 1533 fieldData = ((int[][])data).clone(); 1534 break; 1535 case TIFFTag.TIFF_RATIONAL: 1536 fieldData = ((long[][])data).clone(); 1537 break; 1538 case TIFFTag.TIFF_ASCII: 1539 fieldData = ((String[])data).clone(); 1540 break; 1541 default: 1542 throw new ClassCastException(); // should never happen 1543 } 1544 1545 field.tag = tag; 1546 field.tagNumber = tagNumber; 1547 field.type = type; 1548 field.count = count; 1549 field.data = fieldData; 1550 field.dir = dir != null ? dir.clone() : null; 1551 1552 return field; 1553 } 1554 }