001/* 002 * $RCSfile: TIFFField.java,v $ 003 * 004 * 005 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved. 006 * 007 * Redistribution and use in source and binary forms, with or without 008 * modification, are permitted provided that the following conditions 009 * are met: 010 * 011 * - Redistribution of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * 014 * - Redistribution in binary form must reproduce the above copyright 015 * notice, this list of conditions and the following disclaimer in 016 * the documentation and/or other materials provided with the 017 * distribution. 018 * 019 * Neither the name of Sun Microsystems, Inc. or the names of 020 * contributors may be used to endorse or promote products derived 021 * from this software without specific prior written permission. 022 * 023 * This software is provided "AS IS," without a warranty of any 024 * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 025 * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, 026 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY 027 * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL 028 * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF 029 * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS 030 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR 031 * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, 032 * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND 033 * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR 034 * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE 035 * POSSIBILITY OF SUCH DAMAGES. 036 * 037 * You acknowledge that this software is not designed or intended for 038 * use in the design, construction, operation or maintenance of any 039 * nuclear facility. 040 * 041 * $Revision: 1.4 $ 042 * $Date: 2006/04/28 01:28:49 $ 043 * $State: Exp $ 044 */ 045package com.github.jaiimageio.plugins.tiff; 046 047import java.util.StringTokenizer; 048 049import org.w3c.dom.NamedNodeMap; 050import org.w3c.dom.Node; 051 052import com.github.jaiimageio.impl.plugins.tiff.TIFFFieldNode; 053 054/** 055 * A class representing a field in a TIFF 6.0 Image File Directory. 056 * 057 * <p> A field in a TIFF Image File Directory (IFD) is defined as a 058 * tag number accompanied by a sequence of values of identical data type. 059 * TIFF 6.0 defines 12 data types; a 13th type <code>IFD</code> is 060 * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These 061 * TIFF data types are referred to by Java constants and mapped internally 062 * onto Java language data types and type names as follows: 063 * 064 * <br> 065 * <br> 066 * <table border="1"> 067 * 068 * <tr> 069 * <th> 070 * <b>TIFF Data Type</b> 071 * </th> 072 * <th> 073 * <b>Java Constant</b> 074 * </th> 075 * <th> 076 * <b>Java Data Type</b> 077 * </th> 078 * <th> 079 * <b>Java Type Name</b> 080 * </th> 081 * </tr> 082 * 083 * <tr> 084 * <td> 085 * <tt>BYTE</tt> 086 * </td> 087 * <td> 088 * {@link TIFFTag#TIFF_BYTE} 089 * </td> 090 * <td> 091 * <code>byte</code> 092 * </td> 093 * <td> 094 * <code>"Byte"</code> 095 * </td> 096 * </tr> 097 * 098 * <tr> 099 * <td> 100 * <tt>ASCII</tt> 101 * </td> 102 * <td> 103 * {@link TIFFTag#TIFF_ASCII} 104 * </td> 105 * <td> 106 * <code>String</code> 107 * </td> 108 * <td> 109 * <code>"Ascii"</code> 110 * </td> 111 * </tr> 112 * 113 * <tr> 114 * <td> 115 * <tt>SHORT</tt> 116 * </td> 117 * <td> 118 * {@link TIFFTag#TIFF_SHORT} 119 * </td> 120 * <td> 121 * <code>char</code> 122 * </td> 123 * <td> 124 * <code>"Short"</code> 125 * </td> 126 * </tr> 127 * 128 * <tr> 129 * <td> 130 * <tt>LONG</tt> 131 * </td> 132 * <td> 133 * {@link TIFFTag#TIFF_LONG} 134 * </td> 135 * <td> 136 * <code>long</code> 137 * </td> 138 * <td> 139 * <code>"Long"</code> 140 * </td> 141 * </tr> 142 * 143 * <tr> 144 * <td> 145 * <tt>RATIONAL</tt> 146 * </td> 147 * <td> 148 * {@link TIFFTag#TIFF_RATIONAL} 149 * </td> 150 * <td> 151 * <code>long[2]</code> {numerator, denominator} 152 * </td> 153 * <td> 154 * <code>"Rational"</code> 155 * </td> 156 * </tr> 157 * 158 * <tr> 159 * <td> 160 * <tt>SBYTE</tt> 161 * </td> 162 * <td> 163 * {@link TIFFTag#TIFF_SBYTE} 164 * </td> 165 * <td> 166 * <code>byte</code> 167 * </td> 168 * <td> 169 * <code>"SByte"</code> 170 * </td> 171 * </tr> 172 * 173 * <tr> 174 * <td> 175 * <tt>UNDEFINED</tt> 176 * </td> 177 * <td> 178 * {@link TIFFTag#TIFF_UNDEFINED} 179 * </td> 180 * <td> 181 * <code>byte</code> 182 * </td> 183 * <td> 184 * <code>"Undefined"</code> 185 * </td> 186 * </tr> 187 * 188 * <tr> 189 * <td> 190 * <tt>SSHORT</tt> 191 * </td> 192 * <td> 193 * {@link TIFFTag#TIFF_SSHORT} 194 * </td> 195 * <td> 196 * <code>short</code> 197 * </td> 198 * <td> 199 * <code>"SShort"</code> 200 * </td> 201 * </tr> 202 * 203 * <tr> 204 * <td> 205 * <tt>SLONG</tt> 206 * </td> 207 * <td> 208 * {@link TIFFTag#TIFF_SLONG} 209 * </td> 210 * <td> 211 * <code>int</code> 212 * </td> 213 * <td> 214 * <code>"SLong"</code> 215 * </td> 216 * </tr> 217 * 218 * <tr> 219 * <td> 220 * <tt>SRATIONAL</tt> 221 * </td> 222 * <td> 223 * {@link TIFFTag#TIFF_SRATIONAL} 224 * </td> 225 * <td> 226 * <code>int[2]</code> {numerator, denominator} 227 * </td> 228 * <td> 229 * <code>"SRational"</code> 230 * </td> 231 * </tr> 232 * 233 * <tr> 234 * <td> 235 * <tt>FLOAT</tt> 236 * </td> 237 * <td> 238 * {@link TIFFTag#TIFF_FLOAT} 239 * </td> 240 * <td> 241 * <code>float</code> 242 * </td> 243 * <td> 244 * <code>"Float"</code> 245 * </td> 246 * </tr> 247 * 248 * <tr> 249 * <td> 250 * <tt>DOUBLE</tt> 251 * </td> 252 * <td> 253 * {@link TIFFTag#TIFF_DOUBLE} 254 * </td> 255 * <td> 256 * <code>double</code> 257 * </td> 258 * <td> 259 * <code>"Double"</code> 260 * </td> 261 * </tr> 262 * 263 * <tr> 264 * <td> 265 * <tt>IFD</tt> 266 * </td> 267 * <td> 268 * {@link TIFFTag#TIFF_IFD_POINTER} 269 * </td> 270 * <td> 271 * <code>long</code> 272 * </td> 273 * <td> 274 * <code>"IFDPointer"</code> 275 * </td> 276 * </tr> 277 * 278 * </table> 279 * 280 * @see TIFFDirectory 281 * @see TIFFTag 282 */ 283public class TIFFField implements Comparable { 284 285 private static final String[] typeNames = { 286 null, 287 "Byte", "Ascii", "Short", "Long", "Rational", 288 "SByte", "Undefined", "SShort", "SLong", "SRational", 289 "Float", "Double", "IFDPointer" 290 }; 291 292 private static final boolean[] isIntegral = { 293 false, 294 true, false, true, true, false, 295 true, true, true, true, false, 296 false, false, false 297 }; 298 299 /** The tag. */ 300 private TIFFTag tag; 301 302 /** The tag number. */ 303 private int tagNumber; 304 305 /** The tag type. */ 306 private int type; 307 308 /** The number of data items present in the field. */ 309 private int count; 310 311 /** The field data. */ 312 private Object data; 313 314 /** The default constructor. */ 315 private TIFFField() {} 316 317 private static String getAttribute(Node node, String attrName) { 318 NamedNodeMap attrs = node.getAttributes(); 319 return attrs.getNamedItem(attrName).getNodeValue(); 320 } 321 322 private static void initData(Node node, 323 int[] otype, int[] ocount, Object[] odata) { 324 int type; 325 int count; 326 Object data = null; 327 328 String typeName = node.getNodeName(); 329 typeName = typeName.substring(4); 330 typeName = typeName.substring(0, typeName.length() - 1); 331 type = TIFFField.getTypeByName(typeName); 332 if (type == -1) { 333 throw new IllegalArgumentException("typeName = " + typeName); 334 } 335 336 Node child = node.getFirstChild(); 337 338 count = 0; 339 while (child != null) { 340 String childTypeName = child.getNodeName().substring(4); 341 if (!typeName.equals(childTypeName)) { 342 // warning 343 } 344 345 ++count; 346 child = child.getNextSibling(); 347 } 348 349 if (count > 0) { 350 data = createArrayForType(type, count); 351 child = node.getFirstChild(); 352 int idx = 0; 353 while (child != null) { 354 String value = getAttribute(child, "value"); 355 356 String numerator, denominator; 357 int slashPos; 358 359 switch (type) { 360 case TIFFTag.TIFF_ASCII: 361 ((String[])data)[idx] = value; 362 break; 363 case TIFFTag.TIFF_BYTE: 364 case TIFFTag.TIFF_SBYTE: 365 ((byte[])data)[idx] = 366 (byte)Integer.parseInt(value); 367 break; 368 case TIFFTag.TIFF_SHORT: 369 ((char[])data)[idx] = 370 (char)Integer.parseInt(value); 371 break; 372 case TIFFTag.TIFF_SSHORT: 373 ((short[])data)[idx] = 374 (short)Integer.parseInt(value); 375 break; 376 case TIFFTag.TIFF_SLONG: 377 ((int[])data)[idx] = 378 (int)Integer.parseInt(value); 379 break; 380 case TIFFTag.TIFF_LONG: 381 case TIFFTag.TIFF_IFD_POINTER: 382 ((long[])data)[idx] = 383 (long)Long.parseLong(value); 384 break; 385 case TIFFTag.TIFF_FLOAT: 386 ((float[])data)[idx] = 387 (float)Float.parseFloat(value); 388 break; 389 case TIFFTag.TIFF_DOUBLE: 390 ((double[])data)[idx] = 391 (double)Double.parseDouble(value); 392 break; 393 case TIFFTag.TIFF_SRATIONAL: 394 slashPos = value.indexOf("/"); 395 numerator = value.substring(0, slashPos); 396 denominator = value.substring(slashPos + 1); 397 398 ((int[][])data)[idx] = new int[2]; 399 ((int[][])data)[idx][0] = 400 Integer.parseInt(numerator); 401 ((int[][])data)[idx][1] = 402 Integer.parseInt(denominator); 403 break; 404 case TIFFTag.TIFF_RATIONAL: 405 slashPos = value.indexOf("/"); 406 numerator = value.substring(0, slashPos); 407 denominator = value.substring(slashPos + 1); 408 409 ((long[][])data)[idx] = new long[2]; 410 ((long[][])data)[idx][0] = 411 Long.parseLong(numerator); 412 ((long[][])data)[idx][1] = 413 Long.parseLong(denominator); 414 break; 415 default: 416 // error 417 } 418 419 idx++; 420 child = child.getNextSibling(); 421 } 422 } 423 424 otype[0] = type; 425 ocount[0] = count; 426 odata[0] = data; 427 } 428 429 /** 430 * Creates a <code>TIFFField</code> from a TIFF native image 431 * metadata node. If the value of the <tt>"tagNumber"</tt> attribute 432 * of the node is not found in <code>tagSet</code> then a new 433 * <code>TIFFTag</code> with name <code>"unknown"</code> will be 434 * created and assigned to the field. 435 * 436 * @param tagSet The <code>TIFFTagSet</code> to which the 437 * <code>TIFFTag</code> of the field belongs. 438 * @param node A native TIFF image metadata <code>TIFFField</code> node. 439 * @throws IllegalArgumentException if <code>node</code> is 440 * <code>null</code>. 441 * @throws IllegalArgumentException if the name of the node is not 442 * <code>"TIFFField"</code>. 443 */ 444 public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, 445 Node node) { 446 if (node == null) { 447 throw new IllegalArgumentException("node == null!"); 448 } 449 String name = node.getNodeName(); 450 if (!name.equals("TIFFField")) { 451 throw new IllegalArgumentException("!name.equals(\"TIFFField\")"); 452 } 453 454 int tagNumber = Integer.parseInt(getAttribute(node, "number")); 455 TIFFTag tag; 456 if (tagSet != null) { 457 tag = tagSet.getTag(tagNumber); 458 } else { 459 tag = new TIFFTag("unknown", tagNumber, 0, null); 460 } 461 462 int type = TIFFTag.TIFF_UNDEFINED; 463 int count = 0; 464 Object data = null; 465 466 Node child = node.getFirstChild(); 467 if (child != null) { 468 String typeName = child.getNodeName(); 469 if (typeName.equals("TIFFUndefined")) { 470 String values = getAttribute(child, "value"); 471 StringTokenizer st = new StringTokenizer(values, ","); 472 count = st.countTokens(); 473 474 byte[] bdata = new byte[count]; 475 for (int i = 0; i < count; i++) { 476 bdata[i] = (byte)Integer.parseInt(st.nextToken()); 477 } 478 479 type = TIFFTag.TIFF_UNDEFINED; 480 data = bdata; 481 } else { 482 int[] otype = new int[1]; 483 int[] ocount = new int[1]; 484 Object[] odata = new Object[1]; 485 486 initData(node.getFirstChild(), otype, ocount, odata); 487 type = otype[0]; 488 count = ocount[0]; 489 data = odata[0]; 490 } 491 } else { 492 int t = TIFFTag.MAX_DATATYPE; 493 while(t >= TIFFTag.MIN_DATATYPE && !tag.isDataTypeOK(t)) { 494 t--; 495 } 496 type = t; 497 } 498 499 return new TIFFField(tag, type, count, data); 500 } 501 502 /** 503 * Constructs a <code>TIFFField</code> with arbitrary data. The 504 * <code>type</code> parameter must be a value for which 505 * {@link TIFFTag#isDataTypeOK <code>tag.isDataTypeOK()</code>} 506 * returns <code>true</code>. The <code>data</code> parameter must 507 * be an array of a Java type appropriate for the type of the TIFF 508 * field unless {@link TIFFTag#isIFDPointer 509 * <code>tag.isIFDPointer()</code>} returns <code>true</code> in 510 * which case it must be a <code>TIFFDirectory</code> instance. 511 * 512 * <p><i>Neither the legality of <code>type</code> with respect to 513 * <code>tag</code> nor that or <code>data</code> with respect to 514 * <code>type</code> is verified by this constructor.</i> The methods 515 * {@link TIFFTag#isDataTypeOK <code>TIFFTag.isDataTypeOK()</code>} 516 * and {@link #createArrayForType <code>createArrayForType()</code>} 517 * should be used programmatically to ensure that subsequent errors 518 * such as <code>ClassCastException</code>s do not occur as a result 519 * of providing inconsitent parameters to this constructor.</p> 520 * 521 * <p>Note that the value (data) of the <code>TIFFField</code> 522 * will always be the actual field value regardless of the number of 523 * bytes required for that value. This is the case despite the fact 524 * that the TIFF <i>IFD Entry</i> corresponding to the field may 525 * actually contain the offset to the field's value rather than 526 * the value itself (the latter occurring if and only if the 527 * value fits into 4 bytes). In other words, the value of the 528 * field will already have been read from the TIFF stream. This 529 * subsumes the case where <code>tag.isIFDPointer()</code> returns 530 * <code>true</code> and the value will be a <code>TIFFDirectory</code> 531 * rather than an array.</p> 532 * 533 * @param tag The tag to associated with this field. 534 * @param type One of the <code>TIFFTag.TIFF_*</code> constants 535 * indicating the data type of the field as written to the TIFF stream. 536 * @param count The number of data values. 537 * @param data The actual data content of the field. 538 * 539 * @throws IllegalArgumentException if <code>tag == null</code>. 540 * @throws IllegalArgumentException if <code>dataType</code> is not 541 * one of the <code>TIFFTag.TIFF_*</code> data type constants. 542 * @throws IllegalArgumentException if <code>count < 0</code>. 543 */ 544 public TIFFField(TIFFTag tag, int type, int count, Object data) { 545 if(tag == null) { 546 throw new IllegalArgumentException("tag == null!"); 547 } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) { 548 throw new IllegalArgumentException("Unknown data type "+type); 549 } else if(count < 0) { 550 throw new IllegalArgumentException("count < 0!"); 551 } 552 this.tag = tag; 553 this.tagNumber = tag.getNumber(); 554 this.type = type; 555 this.count = count; 556 this.data = data; 557 } 558 559 /** 560 * Constructs a data array using {@link #createArrayForType 561 * <code>createArrayForType()</code>} and invokes 562 * {@link #TIFFField(TIFFTag,int,int,Object)} with the supplied 563 * parameters and the created array. 564 * 565 * @see #TIFFField(TIFFTag,int,int,Object) 566 */ 567 public TIFFField(TIFFTag tag, int type, int count) { 568 this(tag, type, count, createArrayForType(type, count)); 569 } 570 571 /** 572 * Constructs a <code>TIFFField</code> with a single integral value. 573 * The field will have type 574 * {@link TIFFTag#TIFF_SHORT <code>TIFF_SHORT</code>} if 575 * <code>val < 65536</code> and type 576 * {@link TIFFTag#TIFF_LONG <code>TIFF_LONG</code>} otherwise. 577 * <i>It is <b>not</b> verified whether the resulting type is 578 * legal for <code>tag</code>.</i> 579 * 580 * @param tag The tag to associate with this field. 581 * @param value The value to associate with this field. 582 * @throws IllegalArgumentException if <code>tag == null</code>. 583 * @throws IllegalArgumentException if <code>value < 0</code>. 584 */ 585 public TIFFField(TIFFTag tag, int value) { 586 if(tag == null) { 587 throw new IllegalArgumentException("tag == null!"); 588 } 589 if (value < 0) { 590 throw new IllegalArgumentException("value < 0!"); 591 } 592 593 this.tag = tag; 594 this.tagNumber = tag.getNumber(); 595 this.count = 1; 596 597 if (value < 65536) { 598 this.type = TIFFTag.TIFF_SHORT; 599 char[] cdata = new char[1]; 600 cdata[0] = (char)value; 601 this.data = cdata; 602 } else { 603 this.type = TIFFTag.TIFF_LONG; 604 long[] ldata = new long[1]; 605 ldata[0] = value; 606 this.data = ldata; 607 } 608 } 609 610 /** 611 * Retrieves the tag associated with this field. 612 * 613 * @return The associated <code>TIFFTag</code>. 614 */ 615 public TIFFTag getTag() { 616 return tag; 617 } 618 619 /** 620 * Retrieves the tag number in the range <code>[0, 65535]</code>. 621 * 622 * @return The tag number. 623 */ 624 public int getTagNumber() { 625 return tagNumber; 626 } 627 628 /** 629 * Returns the type of the data stored in the field. For a TIFF 6.0 630 * stream, the value will equal one of the <code>TIFFTag.TIFF_*</code> 631 * constants. For future revisions of TIFF, higher values are possible. 632 * 633 * @return The data type of the field value. 634 */ 635 public int getType() { 636 return type; 637 } 638 639 /** 640 * Returns the name of the supplied data type constant. 641 * 642 * @param dataType One of the <code>TIFFTag.TIFF_*</code> constants 643 * indicating the data type of the field as written to the TIFF stream. 644 * @return The type name corresponding to the supplied type constant. 645 * @throws IllegalArgumentException if <code>dataType</code> is not 646 * one of the <code>TIFFTag.TIFF_*</code> data type constants. 647 */ 648 public static String getTypeName(int dataType) { 649 if (dataType < TIFFTag.MIN_DATATYPE || 650 dataType > TIFFTag.MAX_DATATYPE) { 651 throw new IllegalArgumentException("Unknown data type "+dataType); 652 } 653 654 return typeNames[dataType]; 655 } 656 657 /** 658 * Returns the data type constant corresponding to the supplied data 659 * type name. If the name is unknown <code>-1</code> will be returned. 660 * 661 * @return One of the <code>TIFFTag.TIFF_*</code> constants or 662 * <code>-1</code> if the name is not recognized. 663 */ 664 public static int getTypeByName(String typeName) { 665 for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { 666 if (typeName.equals(typeNames[i])) { 667 return i; 668 } 669 } 670 671 return -1; 672 } 673 674 /** 675 * Creates an array appropriate for the indicated data type. 676 * 677 * @param dataType One of the <code>TIFFTag.TIFF_*</code> data type 678 * constants. 679 * @param count The number of values in the array. 680 * 681 * @throws IllegalArgumentException if <code>dataType</code> is not 682 * one of the <code>TIFFTag.TIFF_*</code> data type constants. 683 * @throws IllegalArgumentException if <code>count < 0</code>. 684 */ 685 public static Object createArrayForType(int dataType, int count) { 686 if(count < 0) { 687 throw new IllegalArgumentException("count < 0!"); 688 } 689 switch (dataType) { 690 case TIFFTag.TIFF_BYTE: 691 case TIFFTag.TIFF_SBYTE: 692 case TIFFTag.TIFF_UNDEFINED: 693 return new byte[count]; 694 case TIFFTag.TIFF_ASCII: 695 return new String[count]; 696 case TIFFTag.TIFF_SHORT: 697 return new char[count]; 698 case TIFFTag.TIFF_LONG: 699 case TIFFTag.TIFF_IFD_POINTER: 700 return new long[count]; 701 case TIFFTag.TIFF_RATIONAL: 702 return new long[count][2]; 703 case TIFFTag.TIFF_SSHORT: 704 return new short[count]; 705 case TIFFTag.TIFF_SLONG: 706 return new int[count]; 707 case TIFFTag.TIFF_SRATIONAL: 708 return new int[count][2]; 709 case TIFFTag.TIFF_FLOAT: 710 return new float[count]; 711 case TIFFTag.TIFF_DOUBLE: 712 return new double[count]; 713 default: 714 throw new IllegalArgumentException("Unknown data type "+dataType); 715 } 716 } 717 718 /** 719 * Returns the <code>TIFFField</code> as a node named either 720 * <tt>"TIFFField"</tt> or <tt>"TIFFIFD"</tt> as described in the 721 * TIFF native image metadata specification. The node will be named 722 * <tt>"TIFFIFD"</tt> if and only if the field's data object is an 723 * instance of {@link TIFFDirectory} or equivalently 724 * {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns 725 * <code>true</code>. 726 * 727 * @return a <code>Node</code> named <tt>"TIFFField"</tt> or 728 * <tt>"TIFFIFD"</tt>. 729 */ 730 public Node getAsNativeNode() { 731 return new TIFFFieldNode(this); 732 } 733 734 /** 735 * Indicates whether the value associated with the field is of 736 * integral data type. 737 * 738 * @return Whether the field type is integral. 739 */ 740 public boolean isIntegral() { 741 return isIntegral[type]; 742 } 743 744 /** 745 * Returns the number of data items present in the field. For 746 * <code>TIFFTag.TIFF_ASCII</code> fields, the value returned is the 747 * number of <code>String</code>s, not the total length of the 748 * data as in the file representation. 749 */ 750 public int getCount() { 751 return count; 752 } 753 754 /** 755 * Returns a reference to the data object associated with the field. 756 * 757 * @return The data object of the field. 758 */ 759 public Object getData() { 760 return data; 761 } 762 763 /** 764 * Returns the data as an uninterpreted array of 765 * <code>byte</code>s. The type of the field must be one of 766 * <code>TIFFTag.TIFF_BYTE</code>, <code>TIFF_SBYTE</code>, or 767 * <code>TIFF_UNDEFINED</code>. 768 * 769 * <p> For data in <code>TIFFTag.TIFF_BYTE</code> format, the application 770 * must take care when promoting the data to longer integral types 771 * to avoid sign extension. 772 * 773 * @throws ClassCastException if the field is not of type 774 * <code>TIFF_BYTE</code>, <code>TIFF_SBYTE</code>, or 775 * <code>TIFF_UNDEFINED</code>. 776 */ 777 public byte[] getAsBytes() { 778 return (byte[])data; 779 } 780 781 /** 782 * Returns <code>TIFFTag.TIFF_SHORT</code> data as an array of 783 * <code>char</code>s (unsigned 16-bit integers). 784 * 785 * @throws ClassCastException if the field is not of type 786 * <code>TIFF_SHORT</code>. 787 */ 788 public char[] getAsChars() { 789 return (char[])data; 790 } 791 792 /** 793 * Returns <code>TIFFTag.TIFF_SSHORT</code> data as an array of 794 * <code>short</code>s (signed 16-bit integers). 795 * 796 * @throws ClassCastException if the field is not of type 797 * <code>TIFF_SSHORT</code>. 798 */ 799 public short[] getAsShorts() { 800 return (short[])data; 801 } 802 803 /** 804 * Returns <code>TIFFTag.TIFF_SLONG</code> data as an array of 805 * <code>int</code>s (signed 32-bit integers). 806 * 807 * @throws ClassCastException if the field is not of type 808 * <code>TIFF_SHORT</code>, <code>TIFF_SSHORT</code>, or 809 * <code>TIFF_SLONG</code>. 810 */ 811 public int[] getAsInts() { 812 if (data instanceof int[]) { 813 return (int[])data; 814 } else if (data instanceof char[]){ 815 char[] cdata = (char[])data; 816 int[] idata = new int[cdata.length]; 817 for (int i = 0; i < cdata.length; i++) { 818 idata[i] = (int)(cdata[i] & 0xffff); 819 } 820 return idata; 821 } else if (data instanceof short[]){ 822 short[] sdata = (short[])data; 823 int[] idata = new int[sdata.length]; 824 for (int i = 0; i < sdata.length; i++) { 825 idata[i] = (int)sdata[i]; 826 } 827 return idata; 828 } else { 829 throw new ClassCastException( 830 "Data not char[], short[], or int[]!"); 831 } 832 } 833 834 /** 835 * Returns <code>TIFFTag.TIFF_LONG</code> or 836 * <code>TIFF_IFD_POINTER</code> data as an array of 837 * <code>long</code>s (signed 64-bit integers). 838 * 839 * @throws ClassCastException if the field is not of type 840 * <code>TIFF_LONG</code> or <code>TIFF_IFD_POINTER</code>. 841 */ 842 public long[] getAsLongs() { 843 return (long[])data; 844 } 845 846 /** 847 * Returns <code>TIFFTag.TIFF_FLOAT</code> data as an array of 848 * <code>float</code>s (32-bit floating-point values). 849 * 850 * @throws ClassCastException if the field is not of type 851 * <code>TIFF_FLOAT</code>. 852 */ 853 public float[] getAsFloats() { 854 return (float[])data; 855 } 856 857 /** 858 * Returns <code>TIFFTag.TIFF_DOUBLE</code> data as an array of 859 * <code>double</code>s (64-bit floating-point values). 860 * 861 * @throws ClassCastException if the field is not of type 862 * <code>TIFF_DOUBLE</code>. 863 */ 864 public double[] getAsDoubles() { 865 return (double[])data; 866 } 867 868 /** 869 * Returns <code>TIFFTag.TIFF_SRATIONAL</code> data as an array of 870 * 2-element arrays of <code>int</code>s. 871 * 872 * @throws ClassCastException if the field is not of type 873 * <code>TIFF_SRATIONAL</code>. 874 */ 875 public int[][] getAsSRationals() { 876 return (int[][])data; 877 } 878 879 /** 880 * Returns <code>TIFFTag.TIFF_RATIONAL</code> data as an array of 881 * 2-element arrays of <code>long</code>s. 882 * 883 * @throws ClassCastException if the field is not of type 884 * <code>TIFF_RATIONAL</code>. 885 */ 886 public long[][] getAsRationals() { 887 return (long[][])data; 888 } 889 890 /** 891 * Returns data in any format as an <code>int</code>. 892 * 893 * <p> <code>TIFFTag.TIFF_BYTE</code> values are treated as unsigned; that 894 * is, no sign extension will take place and the returned value 895 * will be in the range [0, 255]. <code>TIFF_SBYTE</code> data 896 * will be returned in the range [-128, 127]. 897 * 898 * <p> A <code>TIFF_UNDEFINED</code> value is treated as though 899 * it were a <code>TIFF_BYTE</code>. 900 * 901 * <p> Data in <code>TIFF_SLONG</code>, <code>TIFF_LONG</code>, 902 * <code>TIFF_FLOAT</code>, <code>TIFF_DOUBLE</code> or 903 * <code>TIFF_IFD_POINTER</code> format are simply cast to 904 * <code>int</code> and may suffer from truncation. 905 * 906 * <p> Data in <code>TIFF_SRATIONAL</code> or 907 * <code>TIFF_RATIONAL</code> format are evaluated by dividing the 908 * numerator into the denominator using double-precision 909 * arithmetic and then casting to <code>int</code>. Loss of 910 * precision and truncation may occur. 911 * 912 * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by 913 * the <code>Double.parseDouble</code> method, with the result 914 * case to <code>int</code>. 915 */ 916 public int getAsInt(int index) { 917 switch (type) { 918 case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: 919 return ((byte[])data)[index] & 0xff; 920 case TIFFTag.TIFF_SBYTE: 921 return ((byte[])data)[index]; 922 case TIFFTag.TIFF_SHORT: 923 return ((char[])data)[index] & 0xffff; 924 case TIFFTag.TIFF_SSHORT: 925 return ((short[])data)[index]; 926 case TIFFTag.TIFF_SLONG: 927 return ((int[])data)[index]; 928 case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: 929 return (int)((long[])data)[index]; 930 case TIFFTag.TIFF_FLOAT: 931 return (int)((float[])data)[index]; 932 case TIFFTag.TIFF_DOUBLE: 933 return (int)((double[])data)[index]; 934 case TIFFTag.TIFF_SRATIONAL: 935 int[] ivalue = getAsSRational(index); 936 return (int)((double)ivalue[0]/ivalue[1]); 937 case TIFFTag.TIFF_RATIONAL: 938 long[] lvalue = getAsRational(index); 939 return (int)((double)lvalue[0]/lvalue[1]); 940 case TIFFTag.TIFF_ASCII: 941 String s = ((String[])data)[index]; 942 return (int)Double.parseDouble(s); 943 default: 944 throw new ClassCastException(); 945 } 946 } 947 948 /** 949 * Returns data in any format as a <code>long</code>. 950 * 951 * <p> <code>TIFFTag.TIFF_BYTE</code> and <code>TIFF_UNDEFINED</code> data 952 * are treated as unsigned; that is, no sign extension will take 953 * place and the returned value will be in the range [0, 255]. 954 * <code>TIFF_SBYTE</code> data will be returned in the range 955 * [-128, 127]. 956 * 957 * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by 958 * the <code>Double.parseDouble</code> method, with the result 959 * cast to <code>long</code>. 960 */ 961 public long getAsLong(int index) { 962 switch (type) { 963 case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: 964 return ((byte[])data)[index] & 0xff; 965 case TIFFTag.TIFF_SBYTE: 966 return ((byte[])data)[index]; 967 case TIFFTag.TIFF_SHORT: 968 return ((char[])data)[index] & 0xffff; 969 case TIFFTag.TIFF_SSHORT: 970 return ((short[])data)[index]; 971 case TIFFTag.TIFF_SLONG: 972 return ((int[])data)[index]; 973 case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: 974 return ((long[])data)[index]; 975 case TIFFTag.TIFF_SRATIONAL: 976 int[] ivalue = getAsSRational(index); 977 return (long)((double)ivalue[0]/ivalue[1]); 978 case TIFFTag.TIFF_RATIONAL: 979 long[] lvalue = getAsRational(index); 980 return (long)((double)lvalue[0]/lvalue[1]); 981 case TIFFTag.TIFF_ASCII: 982 String s = ((String[])data)[index]; 983 return (long)Double.parseDouble(s); 984 default: 985 throw new ClassCastException(); 986 } 987 } 988 989 /** 990 * Returns data in any format as a <code>float</code>. 991 * 992 * <p> <code>TIFFTag.TIFF_BYTE</code> and <code>TIFF_UNDEFINED</code> data 993 * are treated as unsigned; that is, no sign extension will take 994 * place and the returned value will be in the range [0, 255]. 995 * <code>TIFF_SBYTE</code> data will be returned in the range 996 * [-128, 127]. 997 * 998 * <p> Data in <code>TIFF_SLONG</code>, <code>TIFF_LONG</code>, 999 * <code>TIFF_DOUBLE</code>, or <code>TIFF_IFD_POINTER</code> format are 1000 * simply cast to <code>float</code> and may suffer from 1001 * truncation. 1002 * 1003 * <p> Data in <code>TIFF_SRATIONAL</code> or 1004 * <code>TIFF_RATIONAL</code> format are evaluated by dividing the 1005 * numerator into the denominator using double-precision 1006 * arithmetic and then casting to <code>float</code>. 1007 * 1008 * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by 1009 * the <code>Double.parseDouble</code> method, with the result 1010 * cast to <code>float</code>. 1011 */ 1012 public float getAsFloat(int index) { 1013 switch (type) { 1014 case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: 1015 return ((byte[])data)[index] & 0xff; 1016 case TIFFTag.TIFF_SBYTE: 1017 return ((byte[])data)[index]; 1018 case TIFFTag.TIFF_SHORT: 1019 return ((char[])data)[index] & 0xffff; 1020 case TIFFTag.TIFF_SSHORT: 1021 return ((short[])data)[index]; 1022 case TIFFTag.TIFF_SLONG: 1023 return ((int[])data)[index]; 1024 case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: 1025 return ((long[])data)[index]; 1026 case TIFFTag.TIFF_FLOAT: 1027 return ((float[])data)[index]; 1028 case TIFFTag.TIFF_DOUBLE: 1029 return (float)((double[])data)[index]; 1030 case TIFFTag.TIFF_SRATIONAL: 1031 int[] ivalue = getAsSRational(index); 1032 return (float)((double)ivalue[0]/ivalue[1]); 1033 case TIFFTag.TIFF_RATIONAL: 1034 long[] lvalue = getAsRational(index); 1035 return (float)((double)lvalue[0]/lvalue[1]); 1036 case TIFFTag.TIFF_ASCII: 1037 String s = ((String[])data)[index]; 1038 return (float)Double.parseDouble(s); 1039 default: 1040 throw new ClassCastException(); 1041 } 1042 } 1043 1044 /** 1045 * Returns data in any format as a <code>double</code>. 1046 * 1047 * <p> <code>TIFFTag.TIFF_BYTE</code> and <code>TIFF_UNDEFINED</code> data 1048 * are treated as unsigned; that is, no sign extension will take 1049 * place and the returned value will be in the range [0, 255]. 1050 * <code>TIFF_SBYTE</code> data will be returned in the range 1051 * [-128, 127]. 1052 * 1053 * <p> Data in <code>TIFF_SRATIONAL</code> or 1054 * <code>TIFF_RATIONAL</code> format are evaluated by dividing the 1055 * numerator into the denominator using double-precision 1056 * arithmetic. 1057 * 1058 * <p> Data in <code>TIFF_ASCII</code> format will be parsed as by 1059 * the <code>Double.parseDouble</code> method. 1060 */ 1061 public double getAsDouble(int index) { 1062 switch (type) { 1063 case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: 1064 return ((byte[])data)[index] & 0xff; 1065 case TIFFTag.TIFF_SBYTE: 1066 return ((byte[])data)[index]; 1067 case TIFFTag.TIFF_SHORT: 1068 return ((char[])data)[index] & 0xffff; 1069 case TIFFTag.TIFF_SSHORT: 1070 return ((short[])data)[index]; 1071 case TIFFTag.TIFF_SLONG: 1072 return ((int[])data)[index]; 1073 case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: 1074 return ((long[])data)[index]; 1075 case TIFFTag.TIFF_FLOAT: 1076 return ((float[])data)[index]; 1077 case TIFFTag.TIFF_DOUBLE: 1078 return ((double[])data)[index]; 1079 case TIFFTag.TIFF_SRATIONAL: 1080 int[] ivalue = getAsSRational(index); 1081 return (double)ivalue[0]/ivalue[1]; 1082 case TIFFTag.TIFF_RATIONAL: 1083 long[] lvalue = getAsRational(index); 1084 return (double)lvalue[0]/lvalue[1]; 1085 case TIFFTag.TIFF_ASCII: 1086 String s = ((String[])data)[index]; 1087 return Double.parseDouble(s); 1088 default: 1089 throw new ClassCastException(); 1090 } 1091 } 1092 1093 /** 1094 * Returns a <code>TIFFTag.TIFF_ASCII</code> value as a 1095 * <code>String</code>. 1096 * 1097 * @throws ClassCastException if the field is not of type 1098 * <code>TIFF_ASCII</code>. 1099 */ 1100 public String getAsString(int index) { 1101 return ((String[])data)[index]; 1102 } 1103 1104 /** 1105 * Returns a <code>TIFFTag.TIFF_SRATIONAL</code> data item as a 1106 * two-element array of <code>int</code>s. 1107 * 1108 * @throws ClassCastException if the field is not of type 1109 * <code>TIFF_SRATIONAL</code>. 1110 */ 1111 public int[] getAsSRational(int index) { 1112 return ((int[][])data)[index]; 1113 } 1114 1115 /** 1116 * Returns a TIFFTag.TIFF_RATIONAL data item as a two-element array 1117 * of ints. 1118 * 1119 * @throws ClassCastException if the field is not of type 1120 * <code>TIFF_RATIONAL</code>. 1121 */ 1122 public long[] getAsRational(int index) { 1123 return ((long[][])data)[index]; 1124 } 1125 1126 1127 /** 1128 * Returns a <code>String</code> containing a human-readable 1129 * version of the data item. Data of type 1130 * <code>TIFFTag.TIFF_RATIONAL</code> or <code>TIFF_SRATIONAL</code> are 1131 * represented as a pair of integers separated by a 1132 * <code>'/'</code> character. 1133 * 1134 * @throws ClassCastException if the field is not of one of the 1135 * legal field types. 1136 */ 1137 public String getValueAsString(int index) { 1138 switch (type) { 1139 case TIFFTag.TIFF_ASCII: 1140 return ((String[])data)[index]; 1141 case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_UNDEFINED: 1142 return Integer.toString(((byte[])data)[index] & 0xff); 1143 case TIFFTag.TIFF_SBYTE: 1144 return Integer.toString(((byte[])data)[index]); 1145 case TIFFTag.TIFF_SHORT: 1146 return Integer.toString(((char[])data)[index] & 0xffff); 1147 case TIFFTag.TIFF_SSHORT: 1148 return Integer.toString(((short[])data)[index]); 1149 case TIFFTag.TIFF_SLONG: 1150 return Integer.toString(((int[])data)[index]); 1151 case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: 1152 return Long.toString(((long[])data)[index]); 1153 case TIFFTag.TIFF_FLOAT: 1154 return Float.toString(((float[])data)[index]); 1155 case TIFFTag.TIFF_DOUBLE: 1156 return Double.toString(((double[])data)[index]); 1157 case TIFFTag.TIFF_SRATIONAL: 1158 int[] ivalue = getAsSRational(index); 1159 String srationalString; 1160 if(ivalue[1] != 0 && ivalue[0] % ivalue[1] == 0) { 1161 // If the denominator is a non-zero integral divisor 1162 // of the numerator then convert the fraction to be 1163 // with respect to a unity denominator. 1164 srationalString = 1165 Integer.toString(ivalue[0] / ivalue[1]) + "/1"; 1166 } else { 1167 // Use the values directly. 1168 srationalString = 1169 Integer.toString(ivalue[0]) + 1170 "/" + 1171 Integer.toString(ivalue[1]); 1172 } 1173 return srationalString; 1174 case TIFFTag.TIFF_RATIONAL: 1175 long[] lvalue = getAsRational(index); 1176 String rationalString; 1177 if(lvalue[1] != 0L && lvalue[0] % lvalue[1] == 0) { 1178 // If the denominator is a non-zero integral divisor 1179 // of the numerator then convert the fraction to be 1180 // with respect to a unity denominator. 1181 rationalString = 1182 Long.toString(lvalue[0] / lvalue[1]) + "/1"; 1183 } else { 1184 // Use the values directly. 1185 rationalString = 1186 Long.toString(lvalue[0]) + 1187 "/" + 1188 Long.toString(lvalue[1]); 1189 } 1190 return rationalString; 1191 default: 1192 throw new ClassCastException(); 1193 } 1194 } 1195 1196 /** 1197 * Compares this <code>TIFFField</code> with another 1198 * <code>TIFFField</code> by comparing the tags. 1199 * 1200 * <p><b>Note: this class has a natural ordering that is inconsistent 1201 * with <code>equals()</code>.</b> 1202 * 1203 * @throws IllegalArgumentException if the parameter is <code>null</code>. 1204 * @throws ClassCastException if the parameter is not a 1205 * <code>TIFFField</code>. 1206 */ 1207 public int compareTo(Object o) { 1208 if (o == null) { 1209 throw new IllegalArgumentException(); 1210 } 1211 1212 int oTagNumber = ((TIFFField)o).getTagNumber(); 1213 if (tagNumber < oTagNumber) { 1214 return -1; 1215 } else if (tagNumber > oTagNumber) { 1216 return 1; 1217 } else { 1218 return 0; 1219 } 1220 } 1221}