< prev index next >

src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java

Print this page




 397     // Class to represent an IFD entry where the actual content is at an offset
 398     // in the stream somewhere outside the IFD itself. This occurs when the
 399     // value cannot be contained within four bytes. Seeking is required to read
 400     // such field values.
 401     //
 402     private static class TIFFIFDEntry {
 403         public final TIFFTag tag;
 404         public final int type;
 405         public final int count;
 406         public final long offset;
 407 
 408         TIFFIFDEntry(TIFFTag tag, int type, int count, long offset) {
 409             this.tag = tag;
 410             this.type = type;
 411             this.count = count;
 412             this.offset = offset;
 413         }
 414     }
 415 
 416     //































































































































 417     // Verify that data pointed to outside of the IFD itself are within the
 418     // stream. To be called after all fields have been read and populated.
 419     //
 420     private void checkFieldOffsets(long streamLength) throws IIOException {
 421         if (streamLength < 0) {
 422             return;
 423         }
 424 
 425         // StripOffsets
 426         List<TIFFField> offsets = new ArrayList<>();
 427         TIFFField f = getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
 428         int count = 0;
 429         if (f != null) {
 430             count = f.getCount();
 431             offsets.add(f);
 432         }
 433 
 434         // TileOffsets
 435         f = getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS);
 436         if (f != null) {


 485             }
 486         }
 487 
 488         // JPEGInterchangeFormat and JPEGInterchangeFormatLength
 489         TIFFField jpegOffset =
 490             getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT);
 491         if (jpegOffset != null) {
 492             TIFFField jpegLength =
 493                 getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
 494             if (jpegLength != null) {
 495                 if (jpegOffset.getAsLong(0) + jpegLength.getAsLong(0)
 496                     > streamLength) {
 497                     throw new IIOException
 498                         ("JPEGInterchangeFormat data out of stream");
 499                 }
 500             }
 501         }
 502 
 503         // Ensure there is at least a data pointer for JPEG interchange format or
 504         // both data offsets and byte counts for other compression types.
 505         if (jpegOffset == null && (offsets.size() == 0 || byteCounts.size() == 0)) {
 506             throw new IIOException("Insufficient data offsets or byte counts");











 507         }
 508 
 509         // JPEGQTables - one 64-byte table for each offset.
 510         f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES);
 511         if (f != null) {
 512             long[] tableOffsets = f.getAsLongs();
 513             for (long off : tableOffsets) {
 514                 if (off + 64 > streamLength) {
 515                     throw new IIOException("JPEGQTables data out of stream");
 516                 }
 517             }
 518         }
 519 
 520         // JPEGDCTables
 521         f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_DC_TABLES);
 522         if (f != null) {
 523             long[] tableOffsets = f.getAsLongs();
 524             for (long off : tableOffsets) {
 525                 if (off + 16 > streamLength) {
 526                     throw new IIOException("JPEGDCTables data out of stream");




 397     // Class to represent an IFD entry where the actual content is at an offset
 398     // in the stream somewhere outside the IFD itself. This occurs when the
 399     // value cannot be contained within four bytes. Seeking is required to read
 400     // such field values.
 401     //
 402     private static class TIFFIFDEntry {
 403         public final TIFFTag tag;
 404         public final int type;
 405         public final int count;
 406         public final long offset;
 407 
 408         TIFFIFDEntry(TIFFTag tag, int type, int count, long offset) {
 409             this.tag = tag;
 410             this.type = type;
 411             this.count = count;
 412             this.offset = offset;
 413         }
 414     }
 415 
 416     //
 417     // Retrieve the value of a baseline field as a long.
 418     //
 419     private long getFieldAsLong(int tagNumber) {
 420         TIFFField f = getTIFFField(tagNumber);
 421         return f == null ? -1 : f.getAsLong(0);
 422     }
 423 
 424     //
 425     // Retrieve the value of a baseline field as an int.
 426     //
 427     private int getFieldAsInt(int tagNumber) {
 428         TIFFField f = getTIFFField(tagNumber);
 429         return f == null ? -1 : f.getAsInt(0);
 430     }
 431 
 432     //
 433     // Calculate the number of bytes in each strip or tile. This method
 434     // is to be used if and only if no fields exist which provide this
 435     // information. The parameter must be empty and if the method succeeds
 436     // will contain a single element.
 437     //
 438     private boolean calculateByteCounts(int expectedSize,
 439         List<TIFFField> byteCounts) {
 440         if (!byteCounts.isEmpty()) {
 441             throw new IllegalArgumentException("byteCounts is not empty");
 442         }
 443 
 444         // must be interleaved
 445         if (getFieldAsInt(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION) ==
 446             BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) {
 447             return false;
 448         }
 449 
 450         // must be uncompressed
 451         if (getFieldAsInt(BaselineTIFFTagSet.TAG_COMPRESSION) !=
 452             BaselineTIFFTagSet.COMPRESSION_NONE) {
 453             return false;
 454         }
 455 
 456         // must have image dimensions
 457         long w = getFieldAsLong(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
 458         if (w < 0) {
 459             return false;
 460         }
 461         long h = getFieldAsLong(BaselineTIFFTagSet.TAG_IMAGE_LENGTH);
 462         if (h < 0) {
 463             return false;
 464         }
 465 
 466         long tw = getFieldAsLong(BaselineTIFFTagSet.TAG_TILE_WIDTH);
 467         if (tw < 0) {
 468             tw = w;
 469         }
 470         long th = getFieldAsLong(BaselineTIFFTagSet.TAG_TILE_LENGTH);
 471         if (th < 0) {
 472             th = getFieldAsLong(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
 473             if (th < 0) {
 474                 th = h;
 475             }
 476         }
 477 
 478         int[] bitsPerSample = null;
 479         TIFFField f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
 480         if (f != null) {
 481             bitsPerSample = f.getAsInts();
 482         } else {
 483             int samplesPerPixel =
 484                 getFieldAsInt(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
 485             if (samplesPerPixel < 0) {
 486                 samplesPerPixel = 1;
 487             }
 488             bitsPerSample = new int[samplesPerPixel];
 489             Arrays.fill(bitsPerSample, 8);
 490         }
 491 
 492         int bitsPerPixel = 0;
 493         for (int bps : bitsPerSample) {
 494             bitsPerPixel += bps;
 495         }
 496 
 497         int bytesPerRow = (int)(tw*bitsPerPixel + 7)/8;
 498         int bytesPerPacket = (int)th*bytesPerRow;
 499 
 500         long nx = (w + tw - 1)/tw;
 501         long ny = (h + th - 1)/th;
 502 
 503         if (nx*ny != expectedSize) {
 504             return false;
 505         }
 506 
 507         boolean isTiled =
 508             getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS) != null;
 509 
 510         int tagNumber;
 511         if (isTiled) {
 512             tagNumber = BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS;
 513         } else {
 514             tagNumber = BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS;
 515         }
 516 
 517         TIFFTag t = BaselineTIFFTagSet.getInstance().getTag(tagNumber);
 518         f = getTIFFField(tagNumber);
 519         if (f != null) {
 520             removeTIFFField(tagNumber);
 521         }
 522 
 523         int numPackets = (int)(nx*ny);
 524         long[] packetByteCounts = new long[numPackets];
 525         Arrays.fill(packetByteCounts, bytesPerPacket);
 526 
 527         // if the strip or tile width does not exceed the image width and the
 528         // image height is not a multiple of the strip or tile height, then
 529         // truncate the estimate of the byte count of the last strip to avoid
 530         // reading past the end of the data
 531         if (tw <= w && h % th != 0) {
 532             int numRowsInLastStrip = (int)(h - (ny - 1)*th);
 533             packetByteCounts[numPackets - 1] = numRowsInLastStrip*bytesPerRow;
 534         }
 535 
 536         f = new TIFFField(t, TIFFTag.TIFF_LONG, numPackets, packetByteCounts);
 537         addTIFFField(f);
 538         byteCounts.add(f);
 539         
 540         return true;
 541     }
 542 
 543     //
 544     // Verify that data pointed to outside of the IFD itself are within the
 545     // stream. To be called after all fields have been read and populated.
 546     //
 547     private void checkFieldOffsets(long streamLength) throws IIOException {
 548         if (streamLength < 0) {
 549             return;
 550         }
 551 
 552         // StripOffsets
 553         List<TIFFField> offsets = new ArrayList<>();
 554         TIFFField f = getTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
 555         int count = 0;
 556         if (f != null) {
 557             count = f.getCount();
 558             offsets.add(f);
 559         }
 560 
 561         // TileOffsets
 562         f = getTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS);
 563         if (f != null) {


 612             }
 613         }
 614 
 615         // JPEGInterchangeFormat and JPEGInterchangeFormatLength
 616         TIFFField jpegOffset =
 617             getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT);
 618         if (jpegOffset != null) {
 619             TIFFField jpegLength =
 620                 getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
 621             if (jpegLength != null) {
 622                 if (jpegOffset.getAsLong(0) + jpegLength.getAsLong(0)
 623                     > streamLength) {
 624                     throw new IIOException
 625                         ("JPEGInterchangeFormat data out of stream");
 626                 }
 627             }
 628         }
 629 
 630         // Ensure there is at least a data pointer for JPEG interchange format or
 631         // both data offsets and byte counts for other compression types.
 632         if (jpegOffset == null
 633             && (offsets.size() == 0 || byteCounts.size() == 0)) {
 634             boolean throwException = true;
 635             if (offsets.size() != 0 && byteCounts.size() == 0) {
 636                 // Attempt to calculate missing byte counts
 637                 int expectedSize = offsets.get(0).getCount();
 638                 throwException =
 639                     !calculateByteCounts(expectedSize, byteCounts);
 640             }
 641             if (throwException) {
 642                 throw new IIOException
 643                     ("Insufficient data offsets or byte counts");
 644             }
 645         }
 646 
 647         // JPEGQTables - one 64-byte table for each offset.
 648         f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_Q_TABLES);
 649         if (f != null) {
 650             long[] tableOffsets = f.getAsLongs();
 651             for (long off : tableOffsets) {
 652                 if (off + 64 > streamLength) {
 653                     throw new IIOException("JPEGQTables data out of stream");
 654                 }
 655             }
 656         }
 657 
 658         // JPEGDCTables
 659         f = getTIFFField(BaselineTIFFTagSet.TAG_JPEG_DC_TABLES);
 660         if (f != null) {
 661             long[] tableOffsets = f.getAsLongs();
 662             for (long off : tableOffsets) {
 663                 if (off + 16 > streamLength) {
 664                     throw new IIOException("JPEGDCTables data out of stream");


< prev index next >