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