Changeset 6020 for branches/cleanup


Ignore:
Timestamp:
03/11/10 10:34:51 (10 years ago)
Author:
melissa
Message:

Improved TiffSaver functionality and removed loci.formats.gui.AWTTiffTools. See #466.

Location:
branches/cleanup/components
Files:
1 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • branches/cleanup/components/bio-formats/src/loci/formats/out/OMETiffWriter.java

    r5938 r6020  
    3030 
    3131import loci.common.Location; 
     32import loci.common.RandomAccessInputStream; 
    3233import loci.common.services.DependencyException; 
    3334import loci.common.services.ServiceException; 
     
    7778  /* @see loci.formats.IFormatHandler#close() */ 
    7879  public void close() throws IOException { 
    79     if (out != null) out.close(); 
    80     out = null; 
    8180    if (currentId != null) { 
    8281      if (!wroteLast) { 
     
    8887      // extract OME-XML string from metadata object 
    8988      MetadataRetrieve retrieve = getMetadataRetrieve(); 
    90        
     89 
    9190      OMEXMLMetadata omexmlMeta; 
    9291      OMEXMLService service; 
     
    197196      // write OME-XML to the first IFD's comment 
    198197      try { 
    199         TiffSaver.overwriteComment(currentId, xml); 
     198        TiffSaver saver = new TiffSaver(out); 
     199        RandomAccessInputStream in = new RandomAccessInputStream(currentId); 
     200        saver.overwriteComment(in, xml); 
     201        in.close(); 
    200202      } 
    201203      catch (FormatException exc) { 
     
    208210    seriesMap = null; 
    209211    wroteLast = false; 
     212    if (out != null) out.close(); 
     213    out = null; 
    210214  } 
    211215 
  • branches/cleanup/components/bio-formats/src/loci/formats/out/TiffWriter.java

    r6018 r6020  
    3434import loci.formats.ImageTools; 
    3535import loci.formats.MetadataTools; 
    36 import loci.formats.gui.AWTTiffTools; 
    3736import loci.formats.meta.MetadataRetrieve; 
    3837import loci.formats.tiff.IFD; 
     
    6059  // -- Fields -- 
    6160 
    62   /** The last offset written to. */ 
    63   protected long lastOffset; 
    64  
    6561  /** Current output stream. */ 
    6662  protected RandomAccessOutputStream out; 
    6763 
    68   /** Image counts for each open series. */ 
    69   protected Vector imageCounts; 
    70  
    7164  /** Whether or not the output file is a BigTIFF file. */ 
    7265  protected boolean isBigTiff; 
    7366 
     67  /** The TiffSaver that will do most of the writing. */ 
     68  protected TiffSaver tiffSaver; 
     69 
    7470  // -- Constructors -- 
    7571 
     
    8076  public TiffWriter(String format, String[] exts) { 
    8177    super(format, exts); 
    82     lastOffset = 0; 
    8378    compressionTypes = new String[] { 
    8479      COMPRESSION_UNCOMPRESSED, 
     
    122117 
    123118    if (!initialized) { 
    124       imageCounts = new Vector(); 
    125119      initialized = true; 
    126120      out = new RandomAccessOutputStream(currentId); 
    127121 
    128122      RandomAccessInputStream tmp = new RandomAccessInputStream(currentId); 
     123 
     124      tiffSaver = new TiffSaver(out); 
     125      tiffSaver.setLittleEndian(littleEndian); 
     126      tiffSaver.setBigTiff(isBigTiff); 
     127 
    129128      if (tmp.length() == 0) { 
    130129        // write TIFF header 
    131         TiffSaver tiffSaver = new TiffSaver(out); 
    132         tiffSaver.writeHeader(littleEndian, isBigTiff); 
    133         lastOffset = isBigTiff ? 16 : 8; 
     130        tiffSaver.writeHeader(); 
    134131      } 
    135       else { 
    136         // compute the offset to the last IFD 
    137         TiffParser tiffParser = new TiffParser(tmp); 
    138         long offset = tiffParser.getFirstOffset(); 
    139         long ifdMax = (tmp.length() - 8) / 18; 
    140  
    141         for (long ifdNum=0; ifdNum<ifdMax; ifdNum++) { 
    142           tiffParser.getIFD(offset); 
    143           offset = tmp.readInt(); 
    144           if (offset <= 0 || offset >= tmp.length()) break; 
    145         } 
    146         lastOffset = offset; 
    147       } 
    148       tmp.close(); 
    149132    } 
    150133 
     
    182165 
    183166    if (!isBigTiff) { 
    184       RandomAccessInputStream tmp = new RandomAccessInputStream(currentId); 
    185       isBigTiff = (tmp.length() + 2 * plane) >= 4294967296L; 
     167      isBigTiff = (out.length() + 2 * plane) >= 4294967296L; 
    186168      if (isBigTiff) { 
    187169        throw new FormatException("File is too large; call setBigTiff(true)"); 
    188170      } 
    189       tmp.close(); 
    190171    } 
    191172 
     
    193174    ifd.put(new Integer(IFD.LITTLE_ENDIAN), new Boolean(littleEndian)); 
    194175    out.seek(out.length()); 
    195     lastOffset += AWTTiffTools.writeImage(buf, ifd, out, lastOffset, last, 
    196       isBigTiff, getColorModel(), type, interleaved); 
     176 
     177    ifd.putIFDValue(IFD.PLANAR_CONFIGURATION, interleaved ? 1 : 2); 
     178 
     179    tiffSaver.writeImage(buf, ifd, last, type); 
     180 
    197181    if (last) close(); 
    198182  } 
     
    219203      compressType = TiffCompression.JPEG; 
    220204    } 
    221     h.put(new Integer(IFD.COMPRESSION), compressType); 
     205    h.put(new Integer(IFD.COMPRESSION), compressType.getCode()); 
    222206    saveBytes(buf, h, series, lastInSeries, last); 
    223207  } 
     
    242226    currentId = null; 
    243227    initialized = false; 
    244     lastOffset = 0; 
    245     imageCounts = null; 
    246228  } 
    247229 
  • branches/cleanup/components/bio-formats/src/loci/formats/tiff/IFD.java

    r5988 r6020  
    257257      } 
    258258      else { 
     259        try { 
     260          value = Array.get(value, 0); 
     261          if (checkClass.isInstance(value)) return value; 
     262        } 
     263        catch (IllegalArgumentException exc) { } 
     264 
    259265        throw new FormatException(getIFDTagName(tag) + 
    260266          " directory entry is the wrong type (got " + 
     
    659665    Object photo = getIFDValue(PHOTOMETRIC_INTERPRETATION); 
    660666    if (photo instanceof PhotoInterp) return (PhotoInterp) photo; 
    661     return PhotoInterp.get(((Number) photo).intValue()); 
     667    int pi = photo instanceof Number ? ((Number) photo).intValue() : 
     668      ((int[]) photo)[0]; 
     669    return PhotoInterp.get(pi); 
    662670  } 
    663671 
     
    774782   */ 
    775783  public long[] getRowsPerStrip() throws FormatException { 
    776     if (isTiled()) { 
    777       return new long[] {getImageLength()}; 
    778     } 
    779784    long[] rowsPerStrip = getIFDLongArray(ROWS_PER_STRIP); 
    780785    if (rowsPerStrip == null) { 
  • branches/cleanup/components/bio-formats/src/loci/formats/tiff/TiffSaver.java

    r6003 r6020  
    2424package loci.formats.tiff; 
    2525 
     26import java.io.ByteArrayOutputStream; 
     27import java.io.DataOutputStream; 
    2628import java.io.IOException; 
     29import java.util.Arrays; 
     30import java.util.TreeSet; 
    2731 
    2832import loci.common.ByteArrayHandle; 
     
    3034import loci.common.RandomAccessOutputStream; 
    3135import loci.formats.FormatException; 
     36import loci.formats.FormatTools; 
     37import loci.formats.codec.CodecOptions; 
    3238 
    3339import org.slf4j.Logger; 
     
    5763  protected RandomAccessOutputStream out; 
    5864 
     65  /** Whether or not to write BigTIFF data. */ 
     66  private boolean bigTiff = false; 
     67 
    5968  // -- Constructors -- 
    6069 
     
    6877  } 
    6978 
     79  public TiffSaver(String filename) throws IOException { 
     80    this(new RandomAccessOutputStream(filename)); 
     81  } 
     82 
    7083  // -- TiffSaver methods -- 
    7184 
     
    7588  } 
    7689 
     90  /** Sets whether or not little-endian data should be written. */ 
     91  public void setLittleEndian(boolean littleEndian) { 
     92    out.order(littleEndian); 
     93  } 
     94 
     95  /** Sets whether or not BigTIFF data should be written. */ 
     96  public void setBigTiff(boolean bigTiff) { 
     97    this.bigTiff = bigTiff; 
     98  } 
     99 
     100  /** Returns whether or not we are writing little-endian data. */ 
     101  public boolean isLittleEndian() { 
     102    return out.isLittleEndian(); 
     103  } 
     104 
     105  /** Returns whether or not we are writing BigTIFF data. */ 
     106  public boolean isBigTiff() { return bigTiff; } 
     107 
    77108  /** Writes the TIFF file header. */ 
    78   public void writeHeader(boolean littleEndian, boolean bigTiff) 
    79     throws IOException 
    80   { 
    81     out.order(littleEndian); 
     109  public void writeHeader() throws IOException { 
    82110    // write endianness indicator 
    83     if (littleEndian) { 
     111    if (isLittleEndian()) { 
    84112      out.writeByte(TiffConstants.LITTLE); 
    85113      out.writeByte(TiffConstants.LITTLE); 
     
    106134  } 
    107135 
    108   // -- Utility methods -- 
     136  /** 
     137   */ 
     138  public void writeImage(byte[][] buf, IFDList ifds, int pixelType) 
     139    throws FormatException, IOException 
     140  { 
     141    for (int i=0; i<ifds.size(); i++) { 
     142      if (i < buf.length) { 
     143        writeImage(buf[i], ifds.get(i), i == ifds.size() - 1, pixelType); 
     144      } 
     145    } 
     146  } 
     147 
     148  /** 
     149   */ 
     150  public void writeImage(byte[] buf, IFD ifd, boolean last, int pixelType) 
     151    throws FormatException, IOException 
     152  { 
     153    if (buf == null) { 
     154      throw new FormatException("Image data cannot be null"); 
     155    } 
     156 
     157    if (ifd == null) { 
     158      throw new FormatException("IFD cannot be null"); 
     159    } 
     160 
     161    int width = (int) ifd.getImageWidth(); 
     162    int height = (int) ifd.getImageLength(); 
     163    int bytesPerPixel = FormatTools.getBytesPerPixel(pixelType); 
     164    int plane = (int) (width * height * bytesPerPixel); 
     165    int nChannels = buf.length / plane; 
     166    boolean interleaved = ifd.getPlanarConfiguration() == 1; 
     167 
     168    boolean indexed = ifd.getIFDValue(IFD.COLOR_MAP) != null; 
     169 
     170    makeValidIFD(ifd, pixelType, nChannels); 
     171 
     172    // create pixel output buffers 
     173 
     174    TiffCompression compression = ifd.getCompression(); 
     175    boolean compressFullImage = compression == TiffCompression.JPEG_2000 || 
     176      compression == TiffCompression.JPEG_2000_LOSSY || 
     177      compression == TiffCompression.JPEG || 
     178      compression == TiffCompression.ALT_JPEG; 
     179 
     180    int pixels = width; 
     181    if (compressFullImage) pixels *= height; 
     182 
     183    int rowsPerStrip = (int) ifd.getRowsPerStrip()[0]; 
     184    int stripSize = rowsPerStrip * width * bytesPerPixel; 
     185    int nStrips = (height + rowsPerStrip - 1) / rowsPerStrip; 
     186    if (interleaved) stripSize *= nChannels; 
     187    else nStrips *= nChannels; 
     188 
     189    ByteArrayOutputStream[] stripBuf = new ByteArrayOutputStream[nStrips]; 
     190    DataOutputStream[] stripOut = new DataOutputStream[nStrips]; 
     191    for (int strip=0; strip<nStrips; strip++) { 
     192      stripBuf[strip] = new ByteArrayOutputStream(stripSize); 
     193      stripOut[strip] = new DataOutputStream(stripBuf[strip]); 
     194    } 
     195 
     196    int[] bps = ifd.getBitsPerSample(); 
     197 
     198    // write pixel strips to output buffers 
     199    for (int y=0; y<height; y++) { 
     200      int strip = y / rowsPerStrip; 
     201      for (int x=0; x<width; x++) { 
     202        int ndx = y * width * bytesPerPixel + x * bytesPerPixel; 
     203        for (int c=0; c<nChannels; c++) { 
     204          for (int n=0; n<bps[c]/8; n++) { 
     205            if (interleaved) { 
     206              int off = ndx * nChannels + c * bytesPerPixel + n; 
     207              stripOut[strip].writeByte(buf[off]); 
     208            } 
     209            else { 
     210              int off = c * plane + ndx + n; 
     211              stripOut[c * (nStrips / nChannels) + strip].writeByte(buf[off]); 
     212            } 
     213          } 
     214        } 
     215      } 
     216    } 
     217 
     218    // compress strips according to given differencing and compression schemes 
     219 
     220    byte[][] strips = new byte[nStrips][]; 
     221    for (int strip=0; strip<nStrips; strip++) { 
     222      strips[strip] = stripBuf[strip].toByteArray(); 
     223      TiffCompression.difference(strips[strip], ifd); 
     224      CodecOptions options = compression.getCompressionCodecOptions(ifd); 
     225      strips[strip] = compression.compress(strips[strip], options); 
     226    } 
     227 
     228    // record strip byte counts and offsets 
     229 
     230    long[] stripByteCounts = new long[nStrips]; 
     231    long[] stripOffsets = new long[nStrips]; 
     232 
     233    for (int i=0; i<nStrips; i++) { 
     234      stripByteCounts[i] = strips[i].length; 
     235    } 
     236 
     237    ifd.putIFDValue(IFD.STRIP_BYTE_COUNTS, stripByteCounts); 
     238    ifd.putIFDValue(IFD.STRIP_OFFSETS, stripOffsets); 
     239 
     240    long fp = out.getFilePointer(); 
     241    writeIFD(ifd, 0); 
     242 
     243    for (int i=0; i<strips.length; i++) { 
     244      stripOffsets[i] = out.getFilePointer(); 
     245      out.write(strips[i]); 
     246    } 
     247    long endFP = out.getFilePointer(); 
     248 
     249    out.seek(fp); 
     250    writeIFD(ifd, endFP); 
     251  } 
     252 
     253  public void writeIFD(IFD ifd, long nextOffset) 
     254    throws FormatException, IOException 
     255  { 
     256    TreeSet<Integer> keys = new TreeSet<Integer>(ifd.keySet()); 
     257    int keyCount = keys.size(); 
     258 
     259    if (ifd.containsKey(new Integer(IFD.LITTLE_ENDIAN))) keyCount--; 
     260    if (ifd.containsKey(new Integer(IFD.BIG_TIFF))) keyCount--; 
     261 
     262    long fp = out.getFilePointer(); 
     263    int bytesPerEntry = bigTiff ? TiffConstants.BIG_TIFF_BYTES_PER_ENTRY : 
     264      TiffConstants.BYTES_PER_ENTRY; 
     265    int ifdBytes = (bigTiff ? 16 : 6) + bytesPerEntry * keyCount; 
     266 
     267    if (bigTiff) out.writeLong(keyCount); 
     268    else out.writeShort(keyCount); 
     269 
     270    ByteArrayHandle extra = new ByteArrayHandle(); 
     271    RandomAccessOutputStream extraStream = new RandomAccessOutputStream(extra); 
     272 
     273    for (Integer key : keys) { 
     274      if (key.equals(IFD.LITTLE_ENDIAN) || key.equals(IFD.BIG_TIFF)) continue; 
     275 
     276      Object value = ifd.get(key); 
     277      writeIFDValue(extraStream, ifdBytes + fp, key.intValue(), value); 
     278    } 
     279    writeIntValue(out, nextOffset); 
     280    out.write(extra.getBytes()); 
     281  } 
    109282 
    110283  /** 
    111284   * Writes the given IFD value to the given output object. 
    112    * @param ifdOut output object for writing IFD stream 
    113285   * @param extraOut buffer to which "extra" IFD information should be written 
    114286   * @param offset global offset to use for IFD offset values 
    115287   * @param tag IFD tag to write 
    116288   * @param value IFD value to write 
    117    * @param bigTiff Whether or not this is a big TIFF. 
    118289   */ 
    119   public static void writeIFDValue(RandomAccessOutputStream ifdOut, 
    120     RandomAccessOutputStream extraOut, long offset, int tag, Object value, 
    121     boolean bigTiff) throws FormatException, IOException 
     290  public void writeIFDValue(RandomAccessOutputStream extraOut, long offset, 
     291    int tag, Object value) 
     292    throws FormatException, IOException 
    122293  { 
    123294    // convert singleton objects into arrays, for simplicity 
     
    144315 
    145316    // write directory entry to output buffers 
    146     ifdOut.writeShort(tag); // tag 
     317    out.writeShort(tag); // tag 
    147318    if (value instanceof short[]) { 
    148319      short[] q = (short[]) value; 
    149       ifdOut.writeShort(IFDType.BYTE.getCode()); 
    150       writeIntValue(ifdOut, q.length, bigTiff); 
     320      out.writeShort(IFDType.BYTE.getCode()); 
     321      writeIntValue(out, q.length); 
    151322      if (q.length <= dataLength) { 
    152         for (int i=0; i<q.length; i++) ifdOut.writeByte(q[i]); 
    153         for (int i=q.length; i<dataLength; i++) ifdOut.writeByte(0); 
     323        for (int i=0; i<q.length; i++) out.writeByte(q[i]); 
     324        for (int i=q.length; i<dataLength; i++) out.writeByte(0); 
    154325      } 
    155326      else { 
    156         writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     327        writeIntValue(out, offset + extraOut.length()); 
    157328        for (int i=0; i<q.length; i++) extraOut.writeByte(q[i]); 
    158329      } 
     
    160331    else if (value instanceof String) { // ASCII 
    161332      char[] q = ((String) value).toCharArray(); 
    162       ifdOut.writeShort(IFDType.ASCII.getCode()); // type 
    163       writeIntValue(ifdOut, q.length + 1, bigTiff); 
     333      out.writeShort(IFDType.ASCII.getCode()); // type 
     334      writeIntValue(out, q.length + 1); 
    164335      if (q.length < dataLength) { 
    165         for (int i=0; i<q.length; i++) ifdOut.writeByte(q[i]); // value(s) 
    166         for (int i=q.length; i<dataLength; i++) ifdOut.writeByte(0); // padding 
     336        for (int i=0; i<q.length; i++) out.writeByte(q[i]); // value(s) 
     337        for (int i=q.length; i<dataLength; i++) out.writeByte(0); // padding 
    167338      } 
    168339      else { 
    169         writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     340        writeIntValue(out, offset + extraOut.length()); 
    170341        for (int i=0; i<q.length; i++) extraOut.writeByte(q[i]); // values 
    171342        extraOut.writeByte(0); // concluding NULL byte 
     
    174345    else if (value instanceof int[]) { // SHORT 
    175346      int[] q = (int[]) value; 
    176       ifdOut.writeShort(IFDType.SHORT.getCode()); // type 
    177       writeIntValue(ifdOut, q.length + 1, bigTiff); 
     347      out.writeShort(IFDType.SHORT.getCode()); // type 
     348      writeIntValue(out, q.length); 
    178349      if (q.length <= dataLength / 2) { 
    179350        for (int i=0; i<q.length; i++) { 
    180           ifdOut.writeShort(q[i]); // value(s) 
     351          out.writeShort(q[i]); // value(s) 
    181352        } 
    182353        for (int i=q.length; i<dataLength / 2; i++) { 
    183           ifdOut.writeShort(0); // padding 
     354          out.writeShort(0); // padding 
    184355        } 
    185356      } 
    186357      else { 
    187         writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     358        writeIntValue(out, offset + extraOut.length()); 
    188359        for (int i=0; i<q.length; i++) { 
    189360          extraOut.writeShort(q[i]); // values 
     
    195366 
    196367      int type = bigTiff ? IFDType.LONG8.getCode() : IFDType.LONG.getCode(); 
    197       ifdOut.writeShort(type); 
    198       writeIntValue(ifdOut, q.length, bigTiff); 
     368      out.writeShort(type); 
     369      writeIntValue(out, q.length); 
    199370 
    200371      if (q.length <= dataLength / 4) { 
    201372        for (int i=0; i<q.length; i++) { 
    202           writeIntValue(ifdOut, q[0], bigTiff); 
     373          writeIntValue(out, q[0]); 
    203374        } 
    204375        for (int i=q.length; i<dataLength / 4; i++) { 
    205           writeIntValue(ifdOut, 0, bigTiff); 
     376          writeIntValue(out, 0); 
    206377        } 
    207378      } 
    208379      else { 
    209         writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     380        writeIntValue(out, offset + extraOut.length()); 
    210381        for (int i=0; i<q.length; i++) { 
    211           writeIntValue(extraOut, q[i], bigTiff); 
     382          writeIntValue(extraOut, q[i]); 
    212383        } 
    213384      } 
     
    215386    else if (value instanceof TiffRational[]) { // RATIONAL 
    216387      TiffRational[] q = (TiffRational[]) value; 
    217       ifdOut.writeShort(IFDType.RATIONAL.getCode()); // type 
    218       writeIntValue(ifdOut, q.length, bigTiff); 
     388      out.writeShort(IFDType.RATIONAL.getCode()); // type 
     389      writeIntValue(out, q.length); 
    219390      if (bigTiff && q.length == 1) { 
    220         ifdOut.writeInt((int) q[0].getNumerator()); 
    221         ifdOut.writeInt((int) q[0].getDenominator()); 
     391        out.writeInt((int) q[0].getNumerator()); 
     392        out.writeInt((int) q[0].getDenominator()); 
    222393      } 
    223394      else { 
    224         writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     395        writeIntValue(out, offset + extraOut.length()); 
    225396        for (int i=0; i<q.length; i++) { 
    226397          extraOut.writeInt((int) q[i].getNumerator()); 
     
    231402    else if (value instanceof float[]) { // FLOAT 
    232403      float[] q = (float[]) value; 
    233       ifdOut.writeShort(IFDType.FLOAT.getCode()); // type 
    234       writeIntValue(ifdOut, q.length, bigTiff); 
     404      out.writeShort(IFDType.FLOAT.getCode()); // type 
     405      writeIntValue(out, q.length); 
    235406      if (q.length <= dataLength / 4) { 
    236407        for (int i=0; i<q.length; i++) { 
    237           ifdOut.writeFloat(q[0]); // value 
     408          out.writeFloat(q[0]); // value 
    238409        } 
    239410        for (int i=q.length; i<dataLength / 4; i++) { 
    240           ifdOut.writeInt(0); // padding 
     411          out.writeInt(0); // padding 
    241412        } 
    242413      } 
    243414      else { 
    244         writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     415        writeIntValue(out, offset + extraOut.length()); 
    245416        for (int i=0; i<q.length; i++) { 
    246417          extraOut.writeFloat(q[i]); // values 
     
    250421    else if (value instanceof double[]) { // DOUBLE 
    251422      double[] q = (double[]) value; 
    252       ifdOut.writeShort(IFDType.DOUBLE.getCode()); // type 
    253       writeIntValue(ifdOut, q.length, bigTiff); 
    254       writeIntValue(ifdOut, offset + extraOut.length(), bigTiff); 
     423      out.writeShort(IFDType.DOUBLE.getCode()); // type 
     424      writeIntValue(out, q.length); 
     425      writeIntValue(out, offset + extraOut.length()); 
    255426      for (int i=0; i<q.length; i++) { 
    256427        extraOut.writeDouble(q[i]); // values 
     
    272443   * data in place. 
    273444   */ 
    274   public static void overwriteIFDValue(String file, 
     445  public void overwriteIFDValue(RandomAccessInputStream raf, 
    275446    int ifd, int tag, Object value) throws FormatException, IOException 
    276447  { 
     
    278449      new Object[] {ifd, tag, value}); 
    279450 
    280     RandomAccessInputStream raf = new RandomAccessInputStream(file); 
    281451    raf.seek(0); 
    282452    TiffParser parser = new TiffParser(raf); 
     
    289459    boolean bigTiff = parser.isBigTiff(); 
    290460 
     461    setLittleEndian(little); 
     462    setBigTiff(bigTiff); 
     463 
    291464    long offset = bigTiff ? 8 : 4; // offset to the IFD 
    292465    long num = 0; // number of directory entries 
    293466 
    294     int baseOffset = bigTiff ? 8 : 2; 
    295467    int bytesPerEntry = bigTiff ? 
    296468      TiffConstants.BIG_TIFF_BYTES_PER_ENTRY : TiffConstants.BYTES_PER_ENTRY; 
    297469 
    298470    raf.seek(offset); 
    299     raf.order(little); 
    300471 
    301472    // skip to the correct IFD 
     
    309480    // search directory entries for proper tag 
    310481    for (int i=0; i<num; i++) { 
    311       int oldTag = raf.readUnsignedShort(); 
    312       IFDType oldType = IFDType.get(raf.readUnsignedShort()); 
    313       int oldCount = 
    314         bigTiff ? (int) (raf.readLong() & 0xffffffff) : raf.readInt(); 
    315       long oldOffset = bigTiff ? raf.readLong() : raf.readInt(); 
    316       if (oldTag == tag) { 
     482      TiffIFDEntry entry = parser.readTiffIFDEntry(); 
     483      if (entry.getTag() == tag) { 
    317484        // write new value to buffers 
    318485        ByteArrayHandle ifdBuf = new ByteArrayHandle(bytesPerEntry); 
    319         RandomAccessOutputStream ifdOut = new RandomAccessOutputStream(ifdBuf); 
    320         ifdOut.order(little); 
    321486        ByteArrayHandle extraBuf = new ByteArrayHandle(); 
    322487        RandomAccessOutputStream extraOut = 
    323488          new RandomAccessOutputStream(extraBuf); 
    324489        extraOut.order(little); 
    325         writeIFDValue(ifdOut, extraOut, oldOffset, tag, value, bigTiff); 
     490        writeIFDValue(extraOut, entry.getValueOffset(), tag, value); 
    326491        ifdBuf.seek(0); 
    327492        extraBuf.seek(0); 
     
    341506        } 
    342507        LOGGER.debug("overwriteIFDValue:"); 
    343         LOGGER.debug("\told: (tag={}; type={}; count={}; offset={});", 
    344           new Object[] {oldTag, oldType, oldCount, oldOffset}); 
     508        LOGGER.debug("\told ({});", entry); 
    345509        LOGGER.debug("\tnew: (tag={}; type={}; count={}; offset={})", 
    346510          new Object[] {newTag, newType, newCount, newOffset}); 
     
    352516          LOGGER.debug("overwriteIFDValue: new entry is inline"); 
    353517        } 
    354         else if (oldOffset + 
    355           oldCount * oldType.getBytesPerElement() == raf.length()) 
     518        else if (entry.getValueOffset() + entry.getValueCount() * 
     519          entry.getType().getBytesPerElement() == raf.length()) 
    356520        { 
    357521          // old entry was already at EOF; overwrite it 
    358           newOffset = oldOffset; 
     522          newOffset = entry.getValueOffset(); 
    359523          LOGGER.debug("overwriteIFDValue: old entry is at EOF"); 
    360524        } 
    361         else if (newCount <= oldCount) { 
     525        else if (newCount <= entry.getValueCount()) { 
    362526          // new entry is as small or smaller than old entry; overwrite it 
    363           newOffset = oldOffset; 
     527          newOffset = entry.getValueOffset(); 
    364528          LOGGER.debug("overwriteIFDValue: new entry is <= old entry"); 
    365529        } 
     
    373537        raf.close(); 
    374538 
    375         RandomAccessOutputStream out = new RandomAccessOutputStream(file); 
    376         out.order(little); 
    377  
    378539        // overwrite old entry 
    379540        out.seek(filePointer - (bigTiff ? 18 : 10)); // jump back 
    380541        out.writeShort(newType); 
    381         writeIntValue(out, newCount, bigTiff); 
    382         writeIntValue(out, newOffset, bigTiff); 
     542        writeIntValue(out, newCount); 
     543        writeIntValue(out, newOffset); 
    383544        if (extraBuf.length() > 0) { 
    384545          out.seek(newOffset); 
     
    393554 
    394555  /** Convenience method for overwriting a file's first ImageDescription. */ 
    395   public static void overwriteComment(String id, Object value) 
     556  public void overwriteComment(RandomAccessInputStream in, Object value) 
    396557    throws FormatException, IOException 
    397558  { 
    398     overwriteIFDValue(id, 0, IFD.IMAGE_DESCRIPTION, value); 
     559    overwriteIFDValue(in, 0, IFD.IMAGE_DESCRIPTION, value); 
    399560  } 
    400561 
     
    406567   * long; otherwise, it will be written as a 4 byte integer. 
    407568   */ 
    408   private static void writeIntValue(RandomAccessOutputStream out, long offset, 
    409     boolean bigTiff) throws IOException 
     569  private void writeIntValue(RandomAccessOutputStream out, long offset) 
     570    throws IOException 
    410571  { 
    411572    if (bigTiff) { 
     
    417578  } 
    418579 
     580  private void makeValidIFD(IFD ifd, int pixelType, int nChannels) { 
     581    int bytesPerPixel = FormatTools.getBytesPerPixel(pixelType); 
     582    int bps = 8 * bytesPerPixel; 
     583    int[] bpsArray = new int[nChannels]; 
     584    Arrays.fill(bpsArray, bps); 
     585    ifd.putIFDValue(IFD.BITS_PER_SAMPLE, bpsArray); 
     586 
     587    if (FormatTools.isFloatingPoint(pixelType)) { 
     588      ifd.putIFDValue(IFD.SAMPLE_FORMAT, 3); 
     589    } 
     590    if (ifd.getIFDValue(IFD.COMPRESSION) == null) { 
     591      ifd.putIFDValue(IFD.COMPRESSION, TiffCompression.UNCOMPRESSED.getCode()); 
     592    } 
     593 
     594    boolean indexed = nChannels == 1 && ifd.getIFDValue(IFD.COLOR_MAP) != null; 
     595    PhotoInterp pi = indexed ? PhotoInterp.RGB_PALETTE : 
     596      nChannels == 1 ? PhotoInterp.BLACK_IS_ZERO : PhotoInterp.RGB; 
     597    ifd.putIFDValue(IFD.PHOTOMETRIC_INTERPRETATION, pi.getCode()); 
     598 
     599    ifd.putIFDValue(IFD.SAMPLES_PER_PIXEL, nChannels); 
     600 
     601    if (ifd.get(IFD.X_RESOLUTION) == null) { 
     602      ifd.putIFDValue(IFD.X_RESOLUTION, new TiffRational(1, 1)); 
     603    } 
     604    if (ifd.get(IFD.Y_RESOLUTION) == null) { 
     605      ifd.putIFDValue(IFD.Y_RESOLUTION, new TiffRational(1, 1)); 
     606    } 
     607    if (ifd.get(IFD.SOFTWARE) == null) { 
     608      ifd.putIFDValue(IFD.SOFTWARE, "LOCI Bio-Formats"); 
     609    } 
     610    if (ifd.get(IFD.ROWS_PER_STRIP) == null) { 
     611      ifd.putIFDValue(IFD.ROWS_PER_STRIP, new long[] {1}); 
     612    } 
     613  } 
     614 
    419615} 
  • branches/cleanup/components/bio-formats/src/loci/formats/tools/EditTiffG.java

    r5953 r6020  
    4141import javax.swing.JTextArea; 
    4242 
     43import loci.common.RandomAccessInputStream; 
     44import loci.common.RandomAccessOutputStream; 
    4345import loci.formats.FormatException; 
    4446import loci.formats.tiff.TiffParser; 
     
    146148    try { 
    147149      String xml = getXML(); 
    148       TiffSaver.overwriteComment(f.getAbsolutePath(), xml); 
     150      String path = f.getAbsolutePath(); 
     151      RandomAccessInputStream in = new RandomAccessInputStream(path); 
     152      RandomAccessOutputStream out = new RandomAccessOutputStream(path); 
     153      TiffSaver saver = new TiffSaver(out); 
     154      saver.overwriteComment(in, xml); 
     155      in.close(); 
     156      out.close(); 
    149157    } 
    150158    catch (FormatException exc) { 
  • branches/cleanup/components/bio-formats/test/loci/formats/utests/tiff/TiffPixelsTest.java

    r6012 r6020  
    3333import loci.formats.FormatException; 
    3434import loci.formats.FormatTools; 
    35 import loci.formats.gui.AWTTiffTools; 
    3635import loci.formats.tiff.IFD; 
    3736import loci.formats.tiff.TiffCompression; 
    3837import loci.formats.tiff.TiffParser; 
     38import loci.formats.tiff.TiffSaver; 
    3939 
    4040import org.testng.annotations.BeforeMethod; 
     
    154154    ByteArrayHandle savedData = new ByteArrayHandle(); 
    155155    RandomAccessOutputStream out = new RandomAccessOutputStream(savedData); 
    156     AWTTiffTools.writeImage(data, ifd, out, 0, false, false, null, 
    157       FormatTools.UINT16, false); 
     156    TiffSaver saver = new TiffSaver(out); 
     157    saver.writeImage(data, ifd, false, FormatTools.UINT16); 
    158158    out.close(); 
    159159    RandomAccessInputStream in = new RandomAccessInputStream(savedData); 
  • branches/cleanup/components/bio-formats/test/loci/formats/utests/tiff/TiffSaverTest.java

    r6003 r6020  
    7070  @Test(expectedExceptions={ IllegalArgumentException.class }) 
    7171  public void testNullOutputStream() throws IOException { 
    72     tiffSaver = new TiffSaver(null); 
    73     tiffSaver.writeHeader(false, false); 
     72    tiffSaver = new TiffSaver((RandomAccessOutputStream) null); 
     73    tiffSaver.writeHeader(); 
    7474  } 
    7575 
    7676  @Test 
    7777  public void testWriteHeaderBigEndianRegularTiff() throws IOException { 
    78     tiffSaver.writeHeader(false, false); 
     78    tiffSaver.writeHeader(); 
    7979    assertTrue(tiffParser.isValidHeader()); 
    8080    assertFalse(tiffParser.checkHeader()); 
     
    8484  @Test 
    8585  public void testWriteHeaderLittleEndianRegularTiff() throws IOException { 
    86     tiffSaver.writeHeader(true, false); 
     86    tiffSaver.setLittleEndian(true); 
     87    tiffSaver.writeHeader(); 
    8788    assertTrue(tiffParser.isValidHeader()); 
    8889    assertTrue(tiffParser.checkHeader()); 
     
    9293  @Test 
    9394  public void testWriteHeaderBigEndianBigTiff() throws IOException { 
    94     tiffSaver.writeHeader(false, true); 
     95    tiffSaver.setLittleEndian(false); 
     96    tiffSaver.setBigTiff(true); 
     97    tiffSaver.writeHeader(); 
    9598    assertTrue(tiffParser.isValidHeader()); 
    9699    assertFalse(tiffParser.checkHeader()); 
     
    100103  @Test 
    101104  public void testWriteHeaderLittleEndianBigTiff() throws IOException { 
    102     tiffSaver.writeHeader(true, true); 
     105    tiffSaver.setLittleEndian(true); 
     106    tiffSaver.setBigTiff(true); 
     107    tiffSaver.writeHeader(); 
    103108    assertTrue(tiffParser.isValidHeader()); 
    104109    assertTrue(tiffParser.checkHeader()); 
  • branches/cleanup/components/legacy/ome-editor/src/loci/ome/editor/MetadataPane.java

    r5953 r6020  
    402402          //just rewrite image description of original file. 
    403403          xml = addTiffData(xml, file); 
    404           TiffSaver.overwriteComment(file.getAbsolutePath(), xml); 
     404          String path = file.getAbsolutePath(); 
     405          TiffSaver saver = new TiffSaver(path); 
     406          RandomAccessInputStream in = new RandomAccessInputStream(path); 
     407          saver.overwriteComment(in, xml); 
     408          in.close(); 
    405409        } 
    406410        else { 
Note: See TracChangeset for help on using the changeset viewer.