1 18 package org.apache.batik.ext.awt.image.codec.tiff; 19 20 import java.io.IOException ; 21 import java.io.Serializable ; 22 import java.util.Iterator ; 23 import java.util.HashMap ; 24 import java.util.Map ; 25 import java.util.Vector ; 26 27 import org.apache.batik.ext.awt.image.codec.SeekableStream; 28 29 50 public class TIFFDirectory extends Object implements Serializable { 51 52 53 boolean isBigEndian; 54 55 56 int numEntries; 57 58 59 TIFFField[] fields; 60 61 62 Map fieldIndex = new HashMap (); 63 64 65 long IFDOffset = 8; 66 67 68 long nextIFDOffset = 0; 69 70 71 TIFFDirectory() {} 72 73 private static boolean isValidEndianTag(int endian) { 74 return ((endian == 0x4949) || (endian == 0x4d4d)); 75 } 76 77 87 public TIFFDirectory(SeekableStream stream, int directory) 88 throws IOException { 89 90 long global_save_offset = stream.getFilePointer(); 91 long ifd_offset; 92 93 stream.seek(0L); 95 int endian = stream.readUnsignedShort(); 96 if (!isValidEndianTag(endian)) { 97 throw new 98 IllegalArgumentException ("TIFFDirectory1"); 99 } 100 isBigEndian = (endian == 0x4d4d); 101 102 int magic = readUnsignedShort(stream); 103 if (magic != 42) { 104 throw new 105 IllegalArgumentException ("TIFFDirectory2"); 106 } 107 108 ifd_offset = readUnsignedInt(stream); 110 111 for (int i = 0; i < directory; i++) { 112 if (ifd_offset == 0L) { 113 throw new 114 IllegalArgumentException ("TIFFDirectory3"); 115 } 116 117 stream.seek(ifd_offset); 118 int entries = readUnsignedShort(stream); 119 stream.skip(12*entries); 120 121 ifd_offset = readUnsignedInt(stream); 122 } 123 124 stream.seek(ifd_offset); 125 initialize(stream); 126 stream.seek(global_save_offset); 127 } 128 129 142 public TIFFDirectory(SeekableStream stream, long ifd_offset, int directory) 143 throws IOException { 144 145 long global_save_offset = stream.getFilePointer(); 146 stream.seek(0L); 147 int endian = stream.readUnsignedShort(); 148 if (!isValidEndianTag(endian)) { 149 throw new 150 IllegalArgumentException ("TIFFDirectory1"); 151 } 152 isBigEndian = (endian == 0x4d4d); 153 154 stream.seek(ifd_offset); 156 157 int dirNum = 0; 159 while(dirNum < directory) { 160 int numEntries = readUnsignedShort(stream); 162 163 stream.seek(ifd_offset + 12*numEntries); 165 166 ifd_offset = readUnsignedInt(stream); 168 169 stream.seek(ifd_offset); 171 172 dirNum++; 174 } 175 176 initialize(stream); 177 stream.seek(global_save_offset); 178 } 179 180 private static final int[] sizeOfType = { 181 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }; 195 196 private void initialize(SeekableStream stream) throws IOException { 197 long nextTagOffset; 198 int i, j; 199 200 IFDOffset = stream.getFilePointer(); 201 202 numEntries = readUnsignedShort(stream); 203 fields = new TIFFField[numEntries]; 204 205 for (i = 0; i < numEntries; i++) { 206 int tag = readUnsignedShort(stream); 207 int type = readUnsignedShort(stream); 208 int count = (int)(readUnsignedInt(stream)); 209 int value = 0; 210 211 nextTagOffset = stream.getFilePointer() + 4; 213 214 try { 215 if (count*sizeOfType[type] > 4) { 218 value = (int)(readUnsignedInt(stream)); 219 stream.seek(value); 220 } 221 } catch (ArrayIndexOutOfBoundsException ae) { 222 223 System.err.println(tag + " " + "TIFFDirectory4"); 224 stream.seek(nextTagOffset); 226 continue; 227 } 228 229 fieldIndex.put(new Integer (tag), new Integer (i)); 230 Object obj = null; 231 232 switch (type) { 233 case TIFFField.TIFF_BYTE: 234 case TIFFField.TIFF_SBYTE: 235 case TIFFField.TIFF_UNDEFINED: 236 case TIFFField.TIFF_ASCII: 237 byte[] bvalues = new byte[count]; 238 stream.readFully(bvalues, 0, count); 239 240 if (type == TIFFField.TIFF_ASCII) { 241 242 int index = 0, prevIndex = 0; 244 Vector v = new Vector (); 245 246 while (index < count) { 247 248 while ((index < count) && (bvalues[index++] != 0)); 249 250 v.add(new String (bvalues, prevIndex, 252 (index - prevIndex)) ); 253 prevIndex = index; 254 } 255 256 count = v.size(); 257 String strings[] = new String [count]; 258 for (int c = 0 ; c < count; c++) { 259 strings[c] = (String )v.elementAt(c); 260 } 261 262 obj = strings; 263 } else { 264 obj = bvalues; 265 } 266 267 break; 268 269 case TIFFField.TIFF_SHORT: 270 char[] cvalues = new char[count]; 271 for (j = 0; j < count; j++) { 272 cvalues[j] = (char)(readUnsignedShort(stream)); 273 } 274 obj = cvalues; 275 break; 276 277 case TIFFField.TIFF_LONG: 278 long[] lvalues = new long[count]; 279 for (j = 0; j < count; j++) { 280 lvalues[j] = readUnsignedInt(stream); 281 } 282 obj = lvalues; 283 break; 284 285 case TIFFField.TIFF_RATIONAL: 286 long[][] llvalues = new long[count][2]; 287 for (j = 0; j < count; j++) { 288 llvalues[j][0] = readUnsignedInt(stream); 289 llvalues[j][1] = readUnsignedInt(stream); 290 } 291 obj = llvalues; 292 break; 293 294 case TIFFField.TIFF_SSHORT: 295 short[] svalues = new short[count]; 296 for (j = 0; j < count; j++) { 297 svalues[j] = readShort(stream); 298 } 299 obj = svalues; 300 break; 301 302 case TIFFField.TIFF_SLONG: 303 int[] ivalues = new int[count]; 304 for (j = 0; j < count; j++) { 305 ivalues[j] = readInt(stream); 306 } 307 obj = ivalues; 308 break; 309 310 case TIFFField.TIFF_SRATIONAL: 311 int[][] iivalues = new int[count][2]; 312 for (j = 0; j < count; j++) { 313 iivalues[j][0] = readInt(stream); 314 iivalues[j][1] = readInt(stream); 315 } 316 obj = iivalues; 317 break; 318 319 case TIFFField.TIFF_FLOAT: 320 float[] fvalues = new float[count]; 321 for (j = 0; j < count; j++) { 322 fvalues[j] = readFloat(stream); 323 } 324 obj = fvalues; 325 break; 326 327 case TIFFField.TIFF_DOUBLE: 328 double[] dvalues = new double[count]; 329 for (j = 0; j < count; j++) { 330 dvalues[j] = readDouble(stream); 331 } 332 obj = dvalues; 333 break; 334 335 default: 336 System.err.println("TIFFDirectory0"); 337 break; 338 } 339 340 fields[i] = new TIFFField(tag, type, count, obj); 341 stream.seek(nextTagOffset); 342 } 343 344 nextIFDOffset = readUnsignedInt(stream); 346 } 347 348 349 public int getNumEntries() { 350 return numEntries; 351 } 352 353 357 public TIFFField getField(int tag) { 358 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 359 if (i == null) { 360 return null; 361 } else { 362 return fields[i.intValue()]; 363 } 364 } 365 366 369 public boolean isTagPresent(int tag) { 370 return fieldIndex.containsKey(new Integer (tag)); 371 } 372 373 377 public int[] getTags() { 378 int[] tags = new int[fieldIndex.size()]; 379 Iterator iter = fieldIndex.keySet().iterator(); 380 int i = 0; 381 382 while (iter.hasNext()) { 383 tags[i++] = ((Integer )iter.next()).intValue(); 384 } 385 386 return tags; 387 } 388 389 393 public TIFFField[] getFields() { 394 return fields; 395 } 396 397 403 public byte getFieldAsByte(int tag, int index) { 404 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 405 byte [] b = (fields[i.intValue()]).getAsBytes(); 406 return b[index]; 407 } 408 409 415 public byte getFieldAsByte(int tag) { 416 return getFieldAsByte(tag, 0); 417 } 418 419 425 public long getFieldAsLong(int tag, int index) { 426 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 427 return (fields[i.intValue()]).getAsLong(index); 428 } 429 430 436 public long getFieldAsLong(int tag) { 437 return getFieldAsLong(tag, 0); 438 } 439 440 446 public float getFieldAsFloat(int tag, int index) { 447 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 448 return fields[i.intValue()].getAsFloat(index); 449 } 450 451 456 public float getFieldAsFloat(int tag) { 457 return getFieldAsFloat(tag, 0); 458 } 459 460 466 public double getFieldAsDouble(int tag, int index) { 467 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 468 return fields[i.intValue()].getAsDouble(index); 469 } 470 471 476 public double getFieldAsDouble(int tag) { 477 return getFieldAsDouble(tag, 0); 478 } 479 480 482 private short readShort(SeekableStream stream) 483 throws IOException { 484 if (isBigEndian) { 485 return stream.readShort(); 486 } else { 487 return stream.readShortLE(); 488 } 489 } 490 491 private int readUnsignedShort(SeekableStream stream) 492 throws IOException { 493 if (isBigEndian) { 494 return stream.readUnsignedShort(); 495 } else { 496 return stream.readUnsignedShortLE(); 497 } 498 } 499 500 private int readInt(SeekableStream stream) 501 throws IOException { 502 if (isBigEndian) { 503 return stream.readInt(); 504 } else { 505 return stream.readIntLE(); 506 } 507 } 508 509 private long readUnsignedInt(SeekableStream stream) 510 throws IOException { 511 if (isBigEndian) { 512 return stream.readUnsignedInt(); 513 } else { 514 return stream.readUnsignedIntLE(); 515 } 516 } 517 518 private long readLong(SeekableStream stream) 519 throws IOException { 520 if (isBigEndian) { 521 return stream.readLong(); 522 } else { 523 return stream.readLongLE(); 524 } 525 } 526 527 private float readFloat(SeekableStream stream) 528 throws IOException { 529 if (isBigEndian) { 530 return stream.readFloat(); 531 } else { 532 return stream.readFloatLE(); 533 } 534 } 535 536 private double readDouble(SeekableStream stream) 537 throws IOException { 538 if (isBigEndian) { 539 return stream.readDouble(); 540 } else { 541 return stream.readDoubleLE(); 542 } 543 } 544 545 private static int readUnsignedShort(SeekableStream stream, 546 boolean isBigEndian) 547 throws IOException { 548 if (isBigEndian) { 549 return stream.readUnsignedShort(); 550 } else { 551 return stream.readUnsignedShortLE(); 552 } 553 } 554 555 private static long readUnsignedInt(SeekableStream stream, 556 boolean isBigEndian) 557 throws IOException { 558 if (isBigEndian) { 559 return stream.readUnsignedInt(); 560 } else { 561 return stream.readUnsignedIntLE(); 562 } 563 } 564 565 567 571 public static int getNumDirectories(SeekableStream stream) 572 throws IOException { 573 long pointer = stream.getFilePointer(); 575 stream.seek(0L); 576 int endian = stream.readUnsignedShort(); 577 if (!isValidEndianTag(endian)) { 578 throw new 579 IllegalArgumentException ("TIFFDirectory1"); 580 } 581 boolean isBigEndian = (endian == 0x4d4d); 582 int magic = readUnsignedShort(stream, isBigEndian); 583 if (magic != 42) { 584 throw new 585 IllegalArgumentException ("TIFFDirectory2"); 586 } 587 588 stream.seek(4L); 589 long offset = readUnsignedInt(stream, isBigEndian); 590 591 int numDirectories = 0; 592 while (offset != 0L) { 593 ++numDirectories; 594 595 stream.seek(offset); 596 int entries = readUnsignedShort(stream, isBigEndian); 597 stream.skip(12*entries); 598 offset = readUnsignedInt(stream, isBigEndian); 599 } 600 601 stream.seek(pointer); return numDirectories; 603 } 604 605 610 public boolean isBigEndian() { 611 return isBigEndian; 612 } 613 614 618 public long getIFDOffset() { 619 return IFDOffset; 620 } 621 622 626 public long getNextIFDOffset() { 627 return nextIFDOffset; 628 } 629 } 630 | Popular Tags |