1 33 package com.lowagie.text.pdf.codec; 34 import java.io.EOFException ; 35 import java.io.IOException ; 36 import java.io.Serializable ; 37 import java.util.ArrayList ; 38 import java.util.Enumeration ; 39 import java.util.Hashtable ; 40 41 import com.lowagie.text.pdf.RandomAccessFileOrArray; 42 43 64 public class TIFFDirectory extends Object implements Serializable { 65 66 private static final long serialVersionUID = -168636766193675380L; 67 68 69 boolean isBigEndian; 70 71 72 int numEntries; 73 74 75 TIFFField[] fields; 76 77 78 Hashtable fieldIndex = new Hashtable (); 79 80 81 long IFDOffset = 8; 82 83 84 long nextIFDOffset = 0; 85 86 87 TIFFDirectory() {} 88 89 private static boolean isValidEndianTag(int endian) { 90 return ((endian == 0x4949) || (endian == 0x4d4d)); 91 } 92 93 103 public TIFFDirectory(RandomAccessFileOrArray stream, int directory) 104 throws IOException { 105 106 long global_save_offset = stream.getFilePointer(); 107 long ifd_offset; 108 109 stream.seek(0L); 111 int endian = stream.readUnsignedShort(); 112 if (!isValidEndianTag(endian)) { 113 throw new 114 IllegalArgumentException ("Bad endianness tag (not 0x4949 or 0x4d4d)."); 115 } 116 isBigEndian = (endian == 0x4d4d); 117 118 int magic = readUnsignedShort(stream); 119 if (magic != 42) { 120 throw new 121 IllegalArgumentException ("Bad magic number, should be 42."); 122 } 123 124 ifd_offset = readUnsignedInt(stream); 126 127 for (int i = 0; i < directory; i++) { 128 if (ifd_offset == 0L) { 129 throw new 130 IllegalArgumentException ("Directory number too large."); 131 } 132 133 stream.seek(ifd_offset); 134 int entries = readUnsignedShort(stream); 135 stream.skip(12*entries); 136 137 ifd_offset = readUnsignedInt(stream); 138 } 139 140 stream.seek(ifd_offset); 141 initialize(stream); 142 stream.seek(global_save_offset); 143 } 144 145 158 public TIFFDirectory(RandomAccessFileOrArray stream, long ifd_offset, int directory) 159 throws IOException { 160 161 long global_save_offset = stream.getFilePointer(); 162 stream.seek(0L); 163 int endian = stream.readUnsignedShort(); 164 if (!isValidEndianTag(endian)) { 165 throw new 166 IllegalArgumentException ("Bad endianness tag (not 0x4949 or 0x4d4d)."); 167 } 168 isBigEndian = (endian == 0x4d4d); 169 170 stream.seek(ifd_offset); 172 173 int dirNum = 0; 175 while(dirNum < directory) { 176 int numEntries = readUnsignedShort(stream); 178 179 stream.seek(ifd_offset + 12*numEntries); 181 182 ifd_offset = readUnsignedInt(stream); 184 185 stream.seek(ifd_offset); 187 188 dirNum++; 190 } 191 192 initialize(stream); 193 stream.seek(global_save_offset); 194 } 195 196 private static final int[] sizeOfType = { 197 0, 1, 1, 2, 4, 8, 1, 1, 2, 4, 8, 4, 8 }; 211 212 private void initialize(RandomAccessFileOrArray stream) throws IOException { 213 long nextTagOffset = 0L; 214 long maxOffset = stream.length(); 215 int i, j; 216 217 IFDOffset = stream.getFilePointer(); 218 219 numEntries = readUnsignedShort(stream); 220 fields = new TIFFField[numEntries]; 221 222 for (i = 0; (i < numEntries) && (nextTagOffset < maxOffset); i++) { 223 int tag = readUnsignedShort(stream); 224 int type = readUnsignedShort(stream); 225 int count = (int)(readUnsignedInt(stream)); 226 boolean processTag = true; 227 228 nextTagOffset = stream.getFilePointer() + 4; 230 231 try { 232 if (count*sizeOfType[type] > 4) { 235 long valueOffset = readUnsignedInt(stream); 236 237 if (valueOffset < maxOffset) { 239 stream.seek(valueOffset); 240 } 241 else { 242 processTag = false; 244 } 245 } 246 } catch (ArrayIndexOutOfBoundsException ae) { 247 processTag = false; 249 } 250 251 if (processTag) { 252 fieldIndex.put(new Integer (tag), new Integer (i)); 253 Object obj = null; 254 255 switch (type) { 256 case TIFFField.TIFF_BYTE: 257 case TIFFField.TIFF_SBYTE: 258 case TIFFField.TIFF_UNDEFINED: 259 case TIFFField.TIFF_ASCII: 260 byte[] bvalues = new byte[count]; 261 stream.readFully(bvalues, 0, count); 262 263 if (type == TIFFField.TIFF_ASCII) { 264 265 int index = 0, prevIndex = 0; 267 ArrayList v = new ArrayList (); 268 269 while (index < count) { 270 271 while ((index < count) && (bvalues[index++] != 0)); 272 273 v.add(new String (bvalues, prevIndex, 275 (index - prevIndex)) ); 276 prevIndex = index; 277 } 278 279 count = v.size(); 280 String strings[] = new String [count]; 281 for (int c = 0 ; c < count; c++) { 282 strings[c] = (String )v.get(c); 283 } 284 285 obj = strings; 286 } else { 287 obj = bvalues; 288 } 289 290 break; 291 292 case TIFFField.TIFF_SHORT: 293 char[] cvalues = new char[count]; 294 for (j = 0; j < count; j++) { 295 cvalues[j] = (char)(readUnsignedShort(stream)); 296 } 297 obj = cvalues; 298 break; 299 300 case TIFFField.TIFF_LONG: 301 long[] lvalues = new long[count]; 302 for (j = 0; j < count; j++) { 303 lvalues[j] = readUnsignedInt(stream); 304 } 305 obj = lvalues; 306 break; 307 308 case TIFFField.TIFF_RATIONAL: 309 long[][] llvalues = new long[count][2]; 310 for (j = 0; j < count; j++) { 311 llvalues[j][0] = readUnsignedInt(stream); 312 llvalues[j][1] = readUnsignedInt(stream); 313 } 314 obj = llvalues; 315 break; 316 317 case TIFFField.TIFF_SSHORT: 318 short[] svalues = new short[count]; 319 for (j = 0; j < count; j++) { 320 svalues[j] = readShort(stream); 321 } 322 obj = svalues; 323 break; 324 325 case TIFFField.TIFF_SLONG: 326 int[] ivalues = new int[count]; 327 for (j = 0; j < count; j++) { 328 ivalues[j] = readInt(stream); 329 } 330 obj = ivalues; 331 break; 332 333 case TIFFField.TIFF_SRATIONAL: 334 int[][] iivalues = new int[count][2]; 335 for (j = 0; j < count; j++) { 336 iivalues[j][0] = readInt(stream); 337 iivalues[j][1] = readInt(stream); 338 } 339 obj = iivalues; 340 break; 341 342 case TIFFField.TIFF_FLOAT: 343 float[] fvalues = new float[count]; 344 for (j = 0; j < count; j++) { 345 fvalues[j] = readFloat(stream); 346 } 347 obj = fvalues; 348 break; 349 350 case TIFFField.TIFF_DOUBLE: 351 double[] dvalues = new double[count]; 352 for (j = 0; j < count; j++) { 353 dvalues[j] = readDouble(stream); 354 } 355 obj = dvalues; 356 break; 357 358 default: 359 break; 360 } 361 362 fields[i] = new TIFFField(tag, type, count, obj); 363 } 364 365 stream.seek(nextTagOffset); 366 } 367 368 try { 370 nextIFDOffset = readUnsignedInt(stream); 371 } 372 catch (Exception e) { 373 nextIFDOffset = 0; 375 } 376 } 377 378 379 public int getNumEntries() { 380 return numEntries; 381 } 382 383 387 public TIFFField getField(int tag) { 388 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 389 if (i == null) { 390 return null; 391 } else { 392 return fields[i.intValue()]; 393 } 394 } 395 396 399 public boolean isTagPresent(int tag) { 400 return fieldIndex.containsKey(new Integer (tag)); 401 } 402 403 407 public int[] getTags() { 408 int[] tags = new int[fieldIndex.size()]; 409 Enumeration e = fieldIndex.keys(); 410 int i = 0; 411 412 while (e.hasMoreElements()) { 413 tags[i++] = ((Integer )e.nextElement()).intValue(); 414 } 415 416 return tags; 417 } 418 419 423 public TIFFField[] getFields() { 424 return fields; 425 } 426 427 433 public byte getFieldAsByte(int tag, int index) { 434 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 435 byte [] b = (fields[i.intValue()]).getAsBytes(); 436 return b[index]; 437 } 438 439 445 public byte getFieldAsByte(int tag) { 446 return getFieldAsByte(tag, 0); 447 } 448 449 455 public long getFieldAsLong(int tag, int index) { 456 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 457 return fields[i.intValue()].getAsLong(index); 458 } 459 460 466 public long getFieldAsLong(int tag) { 467 return getFieldAsLong(tag, 0); 468 } 469 470 476 public float getFieldAsFloat(int tag, int index) { 477 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 478 return fields[i.intValue()].getAsFloat(index); 479 } 480 481 486 public float getFieldAsFloat(int tag) { 487 return getFieldAsFloat(tag, 0); 488 } 489 490 496 public double getFieldAsDouble(int tag, int index) { 497 Integer i = (Integer )fieldIndex.get(new Integer (tag)); 498 return fields[i.intValue()].getAsDouble(index); 499 } 500 501 506 public double getFieldAsDouble(int tag) { 507 return getFieldAsDouble(tag, 0); 508 } 509 510 512 private short readShort(RandomAccessFileOrArray stream) 513 throws IOException { 514 if (isBigEndian) { 515 return stream.readShort(); 516 } else { 517 return stream.readShortLE(); 518 } 519 } 520 521 private int readUnsignedShort(RandomAccessFileOrArray stream) 522 throws IOException { 523 if (isBigEndian) { 524 return stream.readUnsignedShort(); 525 } else { 526 return stream.readUnsignedShortLE(); 527 } 528 } 529 530 private int readInt(RandomAccessFileOrArray stream) 531 throws IOException { 532 if (isBigEndian) { 533 return stream.readInt(); 534 } else { 535 return stream.readIntLE(); 536 } 537 } 538 539 private long readUnsignedInt(RandomAccessFileOrArray stream) 540 throws IOException { 541 if (isBigEndian) { 542 return stream.readUnsignedInt(); 543 } else { 544 return stream.readUnsignedIntLE(); 545 } 546 } 547 548 private long readLong(RandomAccessFileOrArray stream) 549 throws IOException { 550 if (isBigEndian) { 551 return stream.readLong(); 552 } else { 553 return stream.readLongLE(); 554 } 555 } 556 557 private float readFloat(RandomAccessFileOrArray stream) 558 throws IOException { 559 if (isBigEndian) { 560 return stream.readFloat(); 561 } else { 562 return stream.readFloatLE(); 563 } 564 } 565 566 private double readDouble(RandomAccessFileOrArray stream) 567 throws IOException { 568 if (isBigEndian) { 569 return stream.readDouble(); 570 } else { 571 return stream.readDoubleLE(); 572 } 573 } 574 575 private static int readUnsignedShort(RandomAccessFileOrArray stream, 576 boolean isBigEndian) 577 throws IOException { 578 if (isBigEndian) { 579 return stream.readUnsignedShort(); 580 } else { 581 return stream.readUnsignedShortLE(); 582 } 583 } 584 585 private static long readUnsignedInt(RandomAccessFileOrArray stream, 586 boolean isBigEndian) 587 throws IOException { 588 if (isBigEndian) { 589 return stream.readUnsignedInt(); 590 } else { 591 return stream.readUnsignedIntLE(); 592 } 593 } 594 595 597 601 public static int getNumDirectories(RandomAccessFileOrArray stream) 602 throws IOException { 603 long pointer = stream.getFilePointer(); 605 stream.seek(0L); 606 int endian = stream.readUnsignedShort(); 607 if (!isValidEndianTag(endian)) { 608 throw new 609 IllegalArgumentException ("Bad endianness tag (not 0x4949 or 0x4d4d)."); 610 } 611 boolean isBigEndian = (endian == 0x4d4d); 612 int magic = readUnsignedShort(stream, isBigEndian); 613 if (magic != 42) { 614 throw new 615 IllegalArgumentException ("Bad magic number, should be 42."); 616 } 617 618 stream.seek(4L); 619 long offset = readUnsignedInt(stream, isBigEndian); 620 621 int numDirectories = 0; 622 while (offset != 0L) { 623 ++numDirectories; 624 625 try { 627 stream.seek(offset); 628 int entries = readUnsignedShort(stream, isBigEndian); 629 stream.skip(12*entries); 630 offset = readUnsignedInt(stream, isBigEndian); 631 } catch(EOFException eof) { 632 numDirectories--; 633 break; 634 } 635 } 636 637 stream.seek(pointer); return numDirectories; 639 } 640 641 646 public boolean isBigEndian() { 647 return isBigEndian; 648 } 649 650 654 public long getIFDOffset() { 655 return IFDOffset; 656 } 657 658 662 public long getNextIFDOffset() { 663 return nextIFDOffset; 664 } 665 } 666 | Popular Tags |