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