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 String[] typeNames = {
267 null,
268 "Byte", "Ascii", "Short", "Long", "Rational",
269 "SByte", "Undefined", "SShort", "SLong", "SRational",
270 "Float", "Double", "IFDPointer"
271 };
272
273 private static final boolean[] isIntegral = {
274 false,
275 true, false, true, true, false,
276 true, true, true, true, false,
277 false, false, false
278 };
279
280 /** The tag. */
281 private TIFFTag tag;
282
283 /** The tag number. */
284 private int tagNumber;
285
286 /** The tag type. */
287 private int type;
288
289 /** The number of data items present in the field. */
290 private int count;
291
292 /** The field data. */
293 private Object data;
527 * @param type One of the {@code TIFFTag.TIFF_*} constants
528 * indicating the data type of the field as written to the TIFF stream.
529 * @param count The number of data values.
530 * @param data The actual data content of the field.
531 *
532 * @throws NullPointerException if {@code tag == null}.
533 * @throws IllegalArgumentException if {@code type} is not
534 * one of the {@code TIFFTag.TIFF_*} data type constants.
535 * @throws IllegalArgumentException if {@code type} is an unacceptable
536 * data type for the supplied {@code TIFFTag}.
537 * @throws IllegalArgumentException if {@code count < 0}.
538 * @throws IllegalArgumentException if {@code count < 1}
539 * and {@code type} is {@code TIFF_RATIONAL} or
540 * {@code TIFF_SRATIONAL}.
541 * @throws IllegalArgumentException if {@code count != 1}
542 * and {@code type} is {@code TIFF_IFD_POINTER}.
543 * @throws NullPointerException if {@code data == null}.
544 * @throws IllegalArgumentException if {@code data} is an instance of
545 * a class incompatible with the specified type.
546 * @throws IllegalArgumentException if the size of the data array is wrong.
547 */
548 public TIFFField(TIFFTag tag, int type, int count, Object data) {
549 if(tag == null) {
550 throw new NullPointerException("tag == null!");
551 } else if(type < TIFFTag.MIN_DATATYPE || type > TIFFTag.MAX_DATATYPE) {
552 throw new IllegalArgumentException("Unknown data type "+type);
553 } else if(!tag.isDataTypeOK(type)) {
554 throw new IllegalArgumentException("Illegal data type " + type
555 + " for " + tag.getName() + " tag");
556 } else if(count < 0) {
557 throw new IllegalArgumentException("count < 0!");
558 } else if((type == TIFFTag.TIFF_RATIONAL
559 || type == TIFFTag.TIFF_SRATIONAL)
560 && count < 1) {
561 throw new IllegalArgumentException
562 ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1");
563 } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) {
564 throw new IllegalArgumentException
565 ("Type is TIFF_IFD_POINTER count != 1");
566 } else if(data == null) {
570 boolean isDataArrayCorrect = false;
571
572 switch (type) {
573 case TIFFTag.TIFF_BYTE:
574 case TIFFTag.TIFF_SBYTE:
575 case TIFFTag.TIFF_UNDEFINED:
576 isDataArrayCorrect = data instanceof byte[]
577 && ((byte[])data).length == count;
578 break;
579 case TIFFTag.TIFF_ASCII:
580 isDataArrayCorrect = data instanceof String[]
581 && ((String[])data).length == count;
582 break;
583 case TIFFTag.TIFF_SHORT:
584 isDataArrayCorrect = data instanceof char[]
585 && ((char[])data).length == count;
586 break;
587 case TIFFTag.TIFF_LONG:
588 isDataArrayCorrect = data instanceof long[]
589 && ((long[])data).length == count;
590 break;
591 case TIFFTag.TIFF_IFD_POINTER:
592 isDataArrayCorrect = data instanceof long[]
593 && ((long[])data).length == 1;
594 break;
595 case TIFFTag.TIFF_RATIONAL:
596 isDataArrayCorrect = data instanceof long[][]
597 && ((long[][])data).length == count
598 && ((long[][])data)[0].length == 2;
599 break;
600 case TIFFTag.TIFF_SSHORT:
601 isDataArrayCorrect = data instanceof short[]
602 && ((short[])data).length == count;
603 break;
604 case TIFFTag.TIFF_SLONG:
605 isDataArrayCorrect = data instanceof int[]
606 && ((int[])data).length == count;
607 break;
608 case TIFFTag.TIFF_SRATIONAL:
609 isDataArrayCorrect = data instanceof int[][]
610 && ((int[][])data).length == count
611 && ((int[][])data)[0].length == 2;
612 break;
613 case TIFFTag.TIFF_FLOAT:
614 isDataArrayCorrect = data instanceof float[]
615 && ((float[])data).length == count;
616 break;
617 case TIFFTag.TIFF_DOUBLE:
618 isDataArrayCorrect = data instanceof double[]
619 && ((double[])data).length == count;
620 break;
621 default:
622 throw new IllegalArgumentException("Unknown data type "+type);
623 }
624
625 if (!isDataArrayCorrect) {
626 throw new IllegalArgumentException
627 ("Illegal class or length for data array");
628 }
629
630 this.tag = tag;
631 this.tagNumber = tag.getNumber();
664 * {@code [0x10000,0xffffffff]}. The count of the field will be unity.
665 *
666 * @param tag The tag to associate with this field.
667 * @param value The value to associate with this field.
668 * @throws NullPointerException if {@code tag == null}.
669 * @throws IllegalArgumentException if {@code value} is not in
670 * {@code [0,0xffffffff]}.
671 * @throws IllegalArgumentException if {@code value} is in
672 * {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type
673 * for the {@code TIFFTag}, or if {@code value} is in
674 * {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable
675 * type for the {@code TIFFTag}.
676 */
677 public TIFFField(TIFFTag tag, long value) {
678 if(tag == null) {
679 throw new NullPointerException("tag == null!");
680 }
681 if (value < 0) {
682 throw new IllegalArgumentException("value < 0!");
683 }
684 if (value > 0xffffffffL) {
685 throw new IllegalArgumentException("value > 0xffffffff!");
686 }
687
688 this.tag = tag;
689 this.tagNumber = tag.getNumber();
690 this.count = 1;
691
692 if (value < 65536) {
693 if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) {
694 throw new IllegalArgumentException("Illegal data type "
695 + getTypeName(TIFFTag.TIFF_SHORT) + " for tag "
696 + "\"" + tag.getName() + "\"");
697 }
698 this.type = TIFFTag.TIFF_SHORT;
699 char[] cdata = new char[1];
700 cdata[0] = (char)value;
701 this.data = cdata;
702 } else {
703 if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) {
704 throw new IllegalArgumentException("Illegal data type "
789 */
790 public int getType() {
791 return type;
792 }
793
794 /**
795 * Returns the name of the supplied data type constant.
796 *
797 * @param dataType One of the {@code TIFFTag.TIFF_*} constants
798 * indicating the data type of the field as written to the TIFF stream.
799 * @return The type name corresponding to the supplied type constant.
800 * @throws IllegalArgumentException if {@code dataType} is not
801 * one of the {@code TIFFTag.TIFF_*} data type constants.
802 */
803 public static String getTypeName(int dataType) {
804 if (dataType < TIFFTag.MIN_DATATYPE ||
805 dataType > TIFFTag.MAX_DATATYPE) {
806 throw new IllegalArgumentException("Unknown data type "+dataType);
807 }
808
809 return typeNames[dataType];
810 }
811
812 /**
813 * Returns the data type constant corresponding to the supplied data
814 * type name. If the name is unknown {@code -1} will be returned.
815 *
816 * @param typeName The type name.
817 * @return One of the {@code TIFFTag.TIFF_*} constants or
818 * {@code -1} if the name is not recognized.
819 */
820 public static int getTypeByName(String typeName) {
821 for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
822 if (typeName.equals(typeNames[i])) {
823 return i;
824 }
825 }
826
827 return -1;
828 }
829
830 /**
831 * Creates an array appropriate for the indicated data type.
832 *
833 * @param dataType One of the {@code TIFFTag.TIFF_*} data type
834 * constants.
835 * @param count The number of values in the array.
836 * @return An array appropriate for the specified data type.
837 *
838 * @throws IllegalArgumentException if {@code dataType} is not
839 * one of the {@code TIFFTag.TIFF_*} data type constants.
840 * @throws IllegalArgumentException if {@code count < 0}.
841 */
842 public static Object createArrayForType(int dataType, int count) {
877 * <tt>"TIFFField"</tt> or <tt>"TIFFIFD"</tt> as described in the
878 * TIFF native image metadata specification. The node will be named
879 * <tt>"TIFFIFD"</tt> if and only if {@link #hasDirectory()} returns
880 * {@code true} and the field's type is either {@link TIFFTag#TIFF_LONG}
881 * or {@link TIFFTag#TIFF_IFD_POINTER}.
882 *
883 * @return a {@code Node} named <tt>"TIFFField"</tt> or
884 * <tt>"TIFFIFD"</tt>.
885 */
886 public Node getAsNativeNode() {
887 return new TIFFFieldNode(this);
888 }
889
890 /**
891 * Indicates whether the value associated with the field is of
892 * integral data type.
893 *
894 * @return Whether the field type is integral.
895 */
896 public boolean isIntegral() {
897 return isIntegral[type];
898 }
899
900 /**
901 * Returns the number of data items present in the field. For
902 * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the
903 * number of {@code String}s, not the total length of the
904 * data as in the file representation.
905 *
906 * @return The number of data items present in the field.
907 */
908 public int getCount() {
909 return count;
910 }
911
912 /**
913 * Returns a reference to the data object associated with the field.
914 *
915 * @return The data object of the field.
916 */
917 public Object getData() {
|
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;
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 count != 1");
571 } else if(data == null) {
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();
711 * {@code [0x10000,0xffffffff]}. The count of the field will be unity.
712 *
713 * @param tag The tag to associate with this field.
714 * @param value The value to associate with this field.
715 * @throws NullPointerException if {@code tag == null}.
716 * @throws IllegalArgumentException if {@code value} is not in
717 * {@code [0,0xffffffff]}.
718 * @throws IllegalArgumentException if {@code value} is in
719 * {@code [0,0xffff]} and {@code TIFF_SHORT} is an unacceptable type
720 * for the {@code TIFFTag}, or if {@code value} is in
721 * {@code [0x10000,0xffffffff]} and {@code TIFF_LONG} is an unacceptable
722 * type for the {@code TIFFTag}.
723 */
724 public TIFFField(TIFFTag tag, long value) {
725 if(tag == null) {
726 throw new NullPointerException("tag == null!");
727 }
728 if (value < 0) {
729 throw new IllegalArgumentException("value < 0!");
730 }
731 if (value > MAX_UINT32) {
732 throw new IllegalArgumentException("value > 0xffffffff!");
733 }
734
735 this.tag = tag;
736 this.tagNumber = tag.getNumber();
737 this.count = 1;
738
739 if (value < 65536) {
740 if (!tag.isDataTypeOK(TIFFTag.TIFF_SHORT)) {
741 throw new IllegalArgumentException("Illegal data type "
742 + getTypeName(TIFFTag.TIFF_SHORT) + " for tag "
743 + "\"" + tag.getName() + "\"");
744 }
745 this.type = TIFFTag.TIFF_SHORT;
746 char[] cdata = new char[1];
747 cdata[0] = (char)value;
748 this.data = cdata;
749 } else {
750 if (!tag.isDataTypeOK(TIFFTag.TIFF_LONG)) {
751 throw new IllegalArgumentException("Illegal data type "
836 */
837 public int getType() {
838 return type;
839 }
840
841 /**
842 * Returns the name of the supplied data type constant.
843 *
844 * @param dataType One of the {@code TIFFTag.TIFF_*} constants
845 * indicating the data type of the field as written to the TIFF stream.
846 * @return The type name corresponding to the supplied type constant.
847 * @throws IllegalArgumentException if {@code dataType} is not
848 * one of the {@code TIFFTag.TIFF_*} data type constants.
849 */
850 public static String getTypeName(int dataType) {
851 if (dataType < TIFFTag.MIN_DATATYPE ||
852 dataType > TIFFTag.MAX_DATATYPE) {
853 throw new IllegalArgumentException("Unknown data type "+dataType);
854 }
855
856 return TYPE_NAMES[dataType];
857 }
858
859 /**
860 * Returns the data type constant corresponding to the supplied data
861 * type name. If the name is unknown {@code -1} will be returned.
862 *
863 * @param typeName The type name.
864 * @return One of the {@code TIFFTag.TIFF_*} constants or
865 * {@code -1} if the name is not recognized.
866 */
867 public static int getTypeByName(String typeName) {
868 for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) {
869 if (typeName.equals(TYPE_NAMES[i])) {
870 return i;
871 }
872 }
873
874 return -1;
875 }
876
877 /**
878 * Creates an array appropriate for the indicated data type.
879 *
880 * @param dataType One of the {@code TIFFTag.TIFF_*} data type
881 * constants.
882 * @param count The number of values in the array.
883 * @return An array appropriate for the specified data type.
884 *
885 * @throws IllegalArgumentException if {@code dataType} is not
886 * one of the {@code TIFFTag.TIFF_*} data type constants.
887 * @throws IllegalArgumentException if {@code count < 0}.
888 */
889 public static Object createArrayForType(int dataType, int count) {
924 * <tt>"TIFFField"</tt> or <tt>"TIFFIFD"</tt> as described in the
925 * TIFF native image metadata specification. The node will be named
926 * <tt>"TIFFIFD"</tt> if and only if {@link #hasDirectory()} returns
927 * {@code true} and the field's type is either {@link TIFFTag#TIFF_LONG}
928 * or {@link TIFFTag#TIFF_IFD_POINTER}.
929 *
930 * @return a {@code Node} named <tt>"TIFFField"</tt> or
931 * <tt>"TIFFIFD"</tt>.
932 */
933 public Node getAsNativeNode() {
934 return new TIFFFieldNode(this);
935 }
936
937 /**
938 * Indicates whether the value associated with the field is of
939 * integral data type.
940 *
941 * @return Whether the field type is integral.
942 */
943 public boolean isIntegral() {
944 return IS_INTEGRAL[type];
945 }
946
947 /**
948 * Returns the number of data items present in the field. For
949 * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the
950 * number of {@code String}s, not the total length of the
951 * data as in the file representation.
952 *
953 * @return The number of data items present in the field.
954 */
955 public int getCount() {
956 return count;
957 }
958
959 /**
960 * Returns a reference to the data object associated with the field.
961 *
962 * @return The data object of the field.
963 */
964 public Object getData() {
|