Changeset 3796


Ignore:
Timestamp:
03/08/08 23:19:18 (12 years ago)
Author:
melissa
Message:

Added support for exporting to BigTIFF. You can test this from the command line using 'bfconvert -bigtiff infile outfile'.

Location:
trunk/loci/formats
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/TiffTools.java

    r3785 r3796  
    290290      if (ifd == null || ifd.size() <= 1) break; 
    291291      v.add(ifd); 
    292       offset = bigTiff ? in.readLong() : in.readInt(); 
     292      offset = bigTiff ? in.readLong() : (long) (in.readInt() & 0xffffffffL); 
    293293      if (offset <= 0 || offset >= in.length()) break; 
    294294    } 
     
    461461        // 8-bit unsigned integer 
    462462        if (count > threshhold) { 
    463           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     463          long pointer = bigTiff ? in.readLong() : 
     464            (long) (in.readInt() & 0xffffffffL); 
    464465          in.seek(pointer); 
    465466        } 
     
    479480        byte[] ascii = new byte[count]; 
    480481        if (count > threshhold) { 
    481           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     482          long pointer = bigTiff ? in.readLong() : 
     483            (long) (in.readInt() & 0xffffffffL); 
    482484          in.seek(pointer); 
    483485        } 
     
    511513        // 16-bit (2-byte) unsigned integer 
    512514        if (count > threshhold / 2) { 
    513           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     515          long pointer = bigTiff ? in.readLong() : 
     516            (long) (in.readInt() & 0xffffffffL); 
    514517          in.seek(pointer); 
    515518        } 
     
    526529        // 32-bit (4-byte) unsigned integer 
    527530        if (count > threshhold / 4) { 
    528           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     531          long pointer = bigTiff ? in.readLong() : 
     532            (long) (in.readInt() & 0xffffffffL); 
    529533          in.seek(pointer); 
    530534        } 
     
    538542      else if (type == LONG8 || type == SLONG8 || type == IFD8) { 
    539543        if (count > threshhold / 8) { 
    540           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     544          long pointer = bigTiff ? in.readLong() : 
     545            (long) (in.readInt() & 0xffffffffL); 
    541546          in.seek(pointer); 
    542547        } 
     
    553558        // Two SLONG's: the first represents the numerator of a fraction, 
    554559        // the second the denominator 
    555         long pointer = bigTiff ? in.readLong() : in.readInt(); 
     560        long pointer = bigTiff ? in.readLong() : 
     561          (long) (in.readInt() & 0xffffffffL); 
    556562        if (count > threshhold / 8) in.seek(pointer); 
    557563        if (count == 1) value = new TiffRational(in.readInt(), in.readInt()); 
     
    569575        // depending on the definition of the field 
    570576        if (count > threshhold) { 
    571           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     577          long pointer = bigTiff ? in.readLong() : 
     578            (long) (in.readInt() & 0xffffffffL); 
    572579          in.seek(pointer); 
    573580        } 
     
    582589        // A 16-bit (2-byte) signed (twos-complement) integer 
    583590        if (count > threshhold / 2) { 
    584           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     591          long pointer = bigTiff ? in.readLong() : 
     592            (long) (in.readInt() & 0xffffffffL); 
    585593          in.seek(pointer); 
    586594        } 
     
    595603        // A 32-bit (4-byte) signed (twos-complement) integer 
    596604        if (count > threshhold / 4) { 
    597           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     605          long pointer = bigTiff ? in.readLong() : 
     606            (long) (in.readInt() & 0xffffffffL); 
    598607          in.seek(pointer); 
    599608        } 
     
    608617        // Single precision (4-byte) IEEE format 
    609618        if (count > threshhold / 4) { 
    610           long pointer = bigTiff ? in.readLong() : in.readInt(); 
     619          long pointer = bigTiff ? in.readLong() : 
     620            (long) (in.readInt() & 0xffffffffL); 
    611621          in.seek(pointer); 
    612622        } 
     
    620630      else if (type == DOUBLE) { 
    621631        // Double precision (8-byte) IEEE format 
    622         long pointer = bigTiff ? in.readLong() : in.readInt(); 
     632        long pointer = bigTiff ? in.readLong() : 
     633          (long) (in.readInt() & 0xffffffffL); 
    623634        in.seek(pointer); 
    624635        if (count == 1) value = new Double(in.readDouble()); 
     
    13921403 
    13931404          if (DEBUG) debug("reading image strip #" + strip); 
    1394           stripOffsets[strip] = (long) (stripOffsets[strip] & 0xffffffffL); 
     1405          if (stripOffsets[strip] < 0) { 
     1406            stripOffsets[strip] = (long) (stripOffsets[strip] & 0xffffffffL); 
     1407          } 
    13951408          in.seek(stripOffsets[strip]); 
    13961409 
     
    20652078   */ 
    20662079  public static void writeIFDValue(DataOutput ifdOut, 
    2067     ByteArrayOutputStream extraBuf, DataOutputStream extraOut, int offset, 
    2068     int tag, Object value) throws FormatException, IOException 
     2080    ByteArrayOutputStream extraBuf, DataOutputStream extraOut, long offset, 
     2081    int tag, Object value, boolean bigTiff) throws FormatException, IOException 
    20692082  { 
    20702083    // convert singleton objects into arrays, for simplicity 
     
    20872100      value = new double[] {((Double) value).doubleValue()}; 
    20882101    } 
     2102 
     2103    int dataLength = bigTiff ? 8 : 4; 
    20892104 
    20902105    // write directory entry to output buffers 
     
    20932108      short[] q = (short[]) value; 
    20942109      ifdOut.writeShort(BYTE); // type 
    2095       ifdOut.writeInt(q.length); // count 
    2096       if (q.length <= 4) { 
     2110      if (bigTiff) ifdOut.writeLong(q.length); 
     2111      else ifdOut.writeInt(q.length); 
     2112      if (q.length <= dataLength) { 
    20972113        for (int i=0; i<q.length; i++) ifdOut.writeByte(q[i]); // value(s) 
    2098         for (int i=q.length; i<4; i++) ifdOut.writeByte(0); // padding 
     2114        for (int i=q.length; i<dataLength; i++) ifdOut.writeByte(0); // padding 
    20992115      } 
    21002116      else { 
    2101         ifdOut.writeInt(offset + extraBuf.size()); // offset 
     2117        if (bigTiff) ifdOut.writeLong(offset + extraBuf.size()); 
     2118        else ifdOut.writeInt((int) (offset + extraBuf.size())); // offset 
    21022119        for (int i=0; i<q.length; i++) extraOut.writeByte(q[i]); // values 
    21032120      } 
     
    21062123      char[] q = ((String) value).toCharArray(); 
    21072124      ifdOut.writeShort(ASCII); // type 
    2108       ifdOut.writeInt(q.length + 1); // count 
    2109       if (q.length < 4) { 
     2125      if (bigTiff) ifdOut.writeLong(q.length + 1); 
     2126      else ifdOut.writeInt(q.length + 1); 
     2127      if (q.length < dataLength) { 
    21102128        for (int i=0; i<q.length; i++) ifdOut.writeByte(q[i]); // value(s) 
    2111         for (int i=q.length; i<4; i++) ifdOut.writeByte(0); // padding 
     2129        for (int i=q.length; i<dataLength; i++) ifdOut.writeByte(0); // padding 
    21122130      } 
    21132131      else { 
    2114         ifdOut.writeInt(offset + extraBuf.size()); // offset 
     2132        if (bigTiff) ifdOut.writeLong(offset + extraBuf.size()); 
     2133        else ifdOut.writeInt((int) (offset + extraBuf.size())); // offset 
    21152134        for (int i=0; i<q.length; i++) extraOut.writeByte(q[i]); // values 
    21162135        extraOut.writeByte(0); // concluding NULL byte 
     
    21202139      int[] q = (int[]) value; 
    21212140      ifdOut.writeShort(SHORT); // type 
    2122       ifdOut.writeInt(q.length); // count 
    2123       if (q.length <= 2) { 
     2141      if (bigTiff) ifdOut.writeLong(q.length); 
     2142      else ifdOut.writeInt(q.length); 
     2143      if (q.length <= dataLength / 2) { 
    21242144        for (int i=0; i<q.length; i++) ifdOut.writeShort(q[i]); // value(s) 
    2125         for (int i=q.length; i<2; i++) ifdOut.writeShort(0); // padding 
     2145        for (int i=q.length; i<dataLength / 2; i++) { 
     2146          ifdOut.writeShort(0); // padding 
     2147        } 
    21262148      } 
    21272149      else { 
    2128         ifdOut.writeInt(offset + extraBuf.size()); // offset 
     2150        if (bigTiff) ifdOut.writeLong(offset + extraBuf.size()); 
     2151        else ifdOut.writeInt((int) (offset + extraBuf.size())); // offset 
    21292152        for (int i=0; i<q.length; i++) extraOut.writeShort(q[i]); // values 
    21302153      } 
     
    21322155    else if (value instanceof long[]) { // LONG 
    21332156      long[] q = (long[]) value; 
    2134       ifdOut.writeShort(LONG); // type 
    2135       ifdOut.writeInt(q.length); // count 
    2136       if (q.length <= 1) { 
    2137         if (q.length == 1) ifdOut.writeInt((int) q[0]); // value 
    2138         else ifdOut.writeInt(0); // padding 
     2157 
     2158      if (bigTiff) { 
     2159        ifdOut.writeShort(LONG8); 
     2160        ifdOut.writeLong(q.length); 
     2161 
     2162        if (q.length <= dataLength / 4) { 
     2163          for (int i=0; i<q.length; i++) ifdOut.writeLong(q[0]); 
     2164          for (int i=q.length; i<dataLength / 4; i++) { 
     2165            ifdOut.writeLong(0); 
     2166          } 
     2167        } 
     2168        else { 
     2169          ifdOut.writeLong(offset + extraBuf.size()); 
     2170          for (int i=0; i<q.length; i++) { 
     2171            extraOut.writeLong(q[i]); 
     2172          } 
     2173        } 
    21392174      } 
    21402175      else { 
    2141         ifdOut.writeInt(offset + extraBuf.size()); // offset 
    2142         for (int i=0; i<q.length; i++) { 
    2143           extraOut.writeInt((int) q[i]); // values 
     2176        ifdOut.writeShort(LONG); 
     2177        ifdOut.writeInt(q.length); 
     2178        if (q.length <= dataLength / 4) { 
     2179          for (int i=0; i<q.length; i++) ifdOut.writeInt((int) q[0]); 
     2180          for (int i=q.length; i<dataLength / 4; i++) { 
     2181            ifdOut.writeInt(0); // padding 
     2182          } 
     2183        } 
     2184        else { 
     2185          ifdOut.writeInt((int) (offset + extraBuf.size())); 
     2186          for (int i=0; i<q.length; i++) { 
     2187            extraOut.writeInt((int) q[i]); 
     2188          } 
    21442189        } 
    21452190      } 
     
    21482193      TiffRational[] q = (TiffRational[]) value; 
    21492194      ifdOut.writeShort(RATIONAL); // type 
    2150       ifdOut.writeInt(q.length); // count 
    2151       ifdOut.writeInt(offset + extraBuf.size()); // offset 
    2152       for (int i=0; i<q.length; i++) { 
    2153         extraOut.writeInt((int) q[i].getNumerator()); // values 
    2154         extraOut.writeInt((int) q[i].getDenominator()); // values 
     2195      if (bigTiff) ifdOut.writeLong(q.length); 
     2196      else ifdOut.writeInt(q.length); 
     2197      if (bigTiff && q.length == 1) { 
     2198        ifdOut.writeInt((int) q[0].getNumerator()); 
     2199        ifdOut.writeInt((int) q[0].getDenominator()); 
     2200      } 
     2201      else { 
     2202        if (bigTiff) ifdOut.writeLong(offset + extraBuf.size()); 
     2203        else ifdOut.writeInt((int) (offset + extraBuf.size())); // offset 
     2204        for (int i=0; i<q.length; i++) { 
     2205          extraOut.writeInt((int) q[i].getNumerator()); // values 
     2206          extraOut.writeInt((int) q[i].getDenominator()); // values 
     2207        } 
    21552208      } 
    21562209    } 
     
    21582211      float[] q = (float[]) value; 
    21592212      ifdOut.writeShort(FLOAT); // type 
    2160       ifdOut.writeInt(q.length); // count 
    2161       if (q.length <= 1) { 
    2162         if (q.length == 1) ifdOut.writeFloat(q[0]); // value 
    2163         else ifdOut.writeInt(0); // padding 
     2213      if (bigTiff) ifdOut.writeLong(q.length); 
     2214      else ifdOut.writeInt(q.length); 
     2215      if (q.length <= dataLength / 4) { 
     2216        for (int i=0; i<q.length; i++) ifdOut.writeFloat(q[0]); // value 
     2217        for (int i=q.length; i<dataLength / 4; i++) { 
     2218          ifdOut.writeInt(0); // padding 
     2219        } 
    21642220      } 
    21652221      else { 
    2166         ifdOut.writeInt(offset + extraBuf.size()); // offset 
     2222        if (bigTiff) ifdOut.writeLong(offset + extraBuf.size()); 
     2223        else ifdOut.writeInt((int) (offset + extraBuf.size())); // offset 
    21672224        for (int i=0; i<q.length; i++) extraOut.writeFloat(q[i]); // values 
    21682225      } 
     
    21712228      double[] q = (double[]) value; 
    21722229      ifdOut.writeShort(DOUBLE); // type 
    2173       ifdOut.writeInt(q.length); // count 
    2174       ifdOut.writeInt(offset + extraBuf.size()); // offset 
     2230      if (bigTiff) ifdOut.writeLong(q.length); 
     2231      else ifdOut.writeInt(q.length); 
     2232      if (bigTiff) ifdOut.writeLong(offset + extraBuf.size()); 
     2233      else ifdOut.writeInt((int) (offset + extraBuf.size())); // offset 
    21752234      for (int i=0; i<q.length; i++) extraOut.writeDouble(q[i]); // values 
    21762235    } 
     
    22302289        ByteArrayOutputStream extraBuf = new ByteArrayOutputStream(); 
    22312290        DataOutputStream extraOut = new DataOutputStream(extraBuf); 
    2232         writeIFDValue(ifdOut, extraBuf, extraOut, oldOffset, tag, value); 
     2291        writeIFDValue(ifdOut, extraBuf, extraOut, oldOffset, tag, value, 
     2292          header[2] == 0x2b); 
    22332293        byte[] bytes = ifdBuf.toByteArray(); 
    22342294        byte[] extra = extraBuf.toByteArray(); 
     
    23092369   * @param offset The value to use for specifying byte offsets 
    23102370   * @param last Whether this image is the final IFD entry of the TIFF data 
     2371   * @param bigTiff Whether this image should be written as BigTIFF 
    23112372   * @return total number of bytes written 
    23122373   */ 
    23132374  public static long writeImage(BufferedImage img, Hashtable ifd, 
    2314     OutputStream out, int offset, boolean last) 
     2375    OutputStream out, long offset, boolean last, boolean bigTiff) 
    23152376    throws FormatException, IOException 
    23162377  { 
     
    24322493    Object[] keys = ifd.keySet().toArray(); 
    24332494    Arrays.sort(keys); // sort IFD tags in ascending order 
    2434     int ifdBytes = 2 + BYTES_PER_ENTRY * keys.length + 4; 
     2495 
     2496    int keyCount = keys.length; 
     2497    if (ifd.containsKey(new Integer(LITTLE_ENDIAN))) keyCount--; 
     2498    if (ifd.containsKey(new Integer(BIG_TIFF))) keyCount--; 
     2499 
     2500    int ifdBytes = (bigTiff ? 16 : 6) + (bigTiff ? 20 : 12) * keyCount; 
    24352501    long pixelBytes = 0; 
    24362502    for (int i=0; i<stripsPerImage; i++) { 
     
    24492515 
    24502516    // write IFD to output buffers 
    2451     ifdOut.writeShort(keys.length); // number of directory entries 
     2517 
     2518    // number of directory entries 
     2519    if (bigTiff) ifdOut.writeLong(keyCount); 
     2520    else ifdOut.writeShort(keyCount); 
    24522521    for (int k=0; k<keys.length; k++) { 
    24532522      Object key = keys[k]; 
     
    24562525      } 
    24572526      if (((Integer) key).intValue() == LITTLE_ENDIAN) continue; 
     2527      if (((Integer) key).intValue() == BIG_TIFF) continue; 
    24582528      Object value = ifd.get(key); 
    24592529      if (DEBUG) { 
     
    24642534      } 
    24652535      writeIFDValue(ifdOut, extraBuf, extraOut, offset, 
    2466         ((Integer) key).intValue(), value); 
    2467     } 
    2468     ifdOut.writeInt(last ? 0 : offset + extraBuf.size()); // offset to next IFD 
     2536        ((Integer) key).intValue(), value, bigTiff); 
     2537    } 
     2538    // offset to next IFD 
     2539    if (bigTiff) ifdOut.writeLong(last ? 0 : offset + extraBuf.size()); 
     2540    else ifdOut.writeInt(last ? 0 : (int) (offset + extraBuf.size())); 
    24692541 
    24702542    // flush buffers to output stream 
  • trunk/loci/formats/out/TiffWriter.java

    r3692 r3796  
    4343 
    4444  /** The last offset written to. */ 
    45   protected int lastOffset; 
     45  protected long lastOffset; 
    4646 
    4747  /** Current output stream. */ 
     
    5050  /** Image counts for each open series. */ 
    5151  protected Vector imageCounts; 
     52 
     53  /** Whether or not the output file is a BigTIFF file. */ 
     54  protected boolean isBigTiff; 
    5255 
    5356  // -- Constructors -- 
     
    6164    lastOffset = 0; 
    6265    compressionTypes = new String[] {"Uncompressed", "LZW"}; 
     66    isBigTiff = false; 
    6367  } 
    6468 
     
    98102        dataOut.writeByte(TiffTools.BIG); 
    99103        dataOut.writeByte(TiffTools.BIG); 
    100         dataOut.writeShort(TiffTools.MAGIC_NUMBER); 
     104        if (isBigTiff) dataOut.writeShort(TiffTools.BIG_TIFF_MAGIC_NUMBER); 
     105        else dataOut.writeShort(TiffTools.MAGIC_NUMBER); 
    101106        dataOut.writeInt(8); // offset to first IFD 
    102107        lastOffset = 8; 
     108        if (isBigTiff) { 
     109          dataOut.writeLong(16); 
     110          lastOffset = 16; 
     111        } 
    103112      } 
    104113      else { 
     
    113122          if (offset <= 0 || offset >= tmp.length()) break; 
    114123        } 
    115         lastOffset = (int) offset; 
     124        lastOffset = offset; 
    116125      } 
    117126      tmp.close(); 
     
    121130      ImageTools.makeBuffered(image) : ImageTools.makeBuffered(image, cm); 
    122131 
    123     lastOffset += TiffTools.writeImage(img, ifd, out, lastOffset, last); 
     132    int plane = img.getWidth() * img.getHeight() * 
     133      img.getRaster().getNumBands() * 
     134      FormatTools.getBytesPerPixel(ImageTools.getPixelType(img)); 
     135 
     136    if (!isBigTiff) { 
     137      RandomAccessStream tmp = new RandomAccessStream(currentId); 
     138      isBigTiff = (tmp.length() + 2 * plane) >= 4294967296L; 
     139      if (isBigTiff) { 
     140        throw new FormatException("File is to large.  Call setBigTiff(true)"); 
     141      } 
     142      tmp.close(); 
     143    } 
     144 
     145    // write the image 
     146 
     147    lastOffset += 
     148      TiffTools.writeImage(img, ifd, out, lastOffset, last, isBigTiff); 
    124149    if (last) close(); 
    125150  } 
     
    159184  } 
    160185 
     186  // -- TiffWriter API methods -- 
     187 
     188  public void setBigTiff(boolean bigTiff) { 
     189    FormatTools.assertId(currentId, false, 1); 
     190    isBigTiff = bigTiff; 
     191  } 
     192 
    161193} 
  • trunk/loci/formats/tools/ImageConverter.java

    r3760 r3796  
    3030import loci.formats.meta.MetadataRetrieve; 
    3131import loci.formats.meta.MetadataStore; 
     32import loci.formats.out.TiffWriter; 
    3233 
    3334/** 
     
    5253    String in = null, out = null; 
    5354    boolean stitch = false, separate = false, merge = false, fill = false; 
     55    boolean bigtiff = false; 
    5456    int series = -1; 
    5557    if (args != null) { 
     
    6163          else if (args[i].equals("-merge")) merge = true; 
    6264          else if (args[i].equals("-fill")) fill = true; 
     65          else if (args[i].equals("-bigtiff")) bigtiff = true; 
    6366          else if (args[i].equals("-series")) { 
    6467            try { 
     
    110113    } 
    111114 
     115    if (writer instanceof TiffWriter) { 
     116      ((TiffWriter) writer).setBigTiff(bigtiff); 
     117    } 
     118    else if (writer instanceof ImageWriter) { 
     119      IFormatWriter w = ((ImageWriter) writer).getWriter(out); 
     120      if (w instanceof TiffWriter) { 
     121        ((TiffWriter) w).setBigTiff(bigtiff); 
     122      } 
     123    } 
    112124    writer.setId(out); 
     125 
    113126    LogTools.print("[" + writer.getFormat() + "] "); 
    114127    long mid = System.currentTimeMillis(); 
Note: See TracChangeset for help on using the changeset viewer.