Changeset 2878


Ignore:
Timestamp:
06/18/07 08:50:44 (12 years ago)
Author:
melissa
Message:

Added support for new version of ND2.

Location:
trunk/loci/formats
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/loci/formats/in/ND2Reader.java

    r2861 r2878  
    3131import javax.imageio.spi.ServiceRegistry; 
    3232import javax.imageio.stream.MemoryCacheImageInputStream; 
     33import javax.xml.parsers.*; 
    3334import loci.formats.*; 
     35import org.xml.sax.Attributes; 
     36import org.xml.sax.SAXException; 
     37import org.xml.sax.helpers.DefaultHandler; 
    3438 
    3539/** 
     
    5256    "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReader"; 
    5357 
     58  /** Factory for generating SAX parsers. */ 
     59  public static final SAXParserFactory SAX_FACTORY =  
     60    SAXParserFactory.newInstance(); 
     61 
    5462  // -- Static fields -- 
    5563 
     
    118126  private int[] validBits; 
    119127 
     128  /** Whether or not the pixel data is compressed using JPEG 2000. */ 
     129  private boolean isJPEG; 
     130 
    120131  private Vector zs = new Vector(); 
    121132  private Vector ts = new Vector(); 
     
    137148  /* @see loci.formats.IFormatReader#openBytes(int) */ 
    138149  public byte[] openBytes(int no) throws FormatException, IOException { 
     150    byte[] b = new byte[core.sizeX[0] * core.sizeY[0] * core.sizeC[0] * 
     151      FormatTools.getBytesPerPixel(core.pixelType[0])]; 
     152    return openBytes(no, b); 
     153  } 
     154 
     155  /* @see loci.formats.IFormatReader#openBytes(int, byte[]) */ 
     156  public byte[] openBytes(int no, byte[] buf)  
     157    throws FormatException, IOException 
     158  { 
     159    FormatTools.assertId(currentId, true, 1); 
     160    if (no < 0 || no >= core.imageCount[0]) { 
     161      throw new FormatException("Invalid image number: " + no); 
     162    }  
     163    if (buf.length < core.sizeX[0] * core.sizeY[0] * core.sizeC[0] * 
     164      FormatTools.getBytesPerPixel(core.pixelType[0])) 
     165    { 
     166      throw new FormatException("Buffer too small."); 
     167    } 
     168    
     169    in.seek(offsets[no]); 
     170 
     171    if (isJPEG) { 
     172      byte[][] pixels = ImageTools.getPixelBytes(openImage(no), false); 
     173 
     174      for (int i=0; i<core.sizeC[0]; i++) { 
     175        System.arraycopy(pixels[i], 0, buf, i*pixels[i].length,  
     176          pixels[i].length); 
     177      } 
     178    } 
     179    else { 
     180      in.read(buf); 
     181    } 
     182  
     183    return buf; 
     184  } 
     185 
     186  /* @see loci.formats.IFormatReader#openImage(int) */ 
     187  public BufferedImage openImage(int no) throws FormatException, IOException { 
     188    if (!isJPEG) { 
     189      return ImageTools.makeImage(openBytes(no), core.sizeX[0], core.sizeY[0], 
     190        core.sizeC[0], core.interleaved[0],  
     191        FormatTools.getBytesPerPixel(core.pixelType[0]), core.littleEndian[0]); 
     192    } 
     193     
    139194    FormatTools.assertId(currentId, true, 1); 
    140195    if (no < 0 || no >= getImageCount()) { 
     
    142197    } 
    143198 
    144     byte[][] pixels = ImageTools.getPixelBytes(openImage(no), false); 
    145  
    146     if (pixels.length == 1 || core.sizeC[0] == 1) { 
    147       return pixels[0]; 
    148     } 
    149  
    150     byte[] b = new byte[core.sizeC[0] * pixels[0].length]; 
    151     for (int i=0; i<core.sizeC[0]; i++) { 
    152       System.arraycopy(pixels[i], 0, b, i*pixels[0].length, pixels[i].length); 
    153     } 
    154     return b; 
    155   } 
    156  
    157   /* @see loci.formats.IFormatReader#openImage(int) */ 
    158   public BufferedImage openImage(int no) throws FormatException, IOException { 
    159     FormatTools.assertId(currentId, true, 1); 
    160     if (no < 0 || no >= getImageCount()) { 
    161       throw new FormatException("Invalid image number: " + no); 
    162     } 
    163  
    164199    in.seek(offsets[no]); 
    165  
     200     
    166201    long len = no < core.imageCount[0] - 1 ? offsets[no + 1] - offsets[no] : 
    167202      in.length() - offsets[no]; 
     
    202237 
    203238    in = new RandomAccessStream(id); 
     239 
     240    if (in.read() == -38 && in.read() == -50) { 
     241      // newer version of ND2 - doesn't use JPEG2000 
     242 
     243      isJPEG = false; 
     244      in.seek(0); 
     245      in.order(true); 
     246 
     247      while (in.getFilePointer() < in.length()) { 
     248        if (in.read() == -38 && in.read() == -50 && in.read() == -66 && 
     249          in.read() == 10) 
     250        { 
     251          // found a data chunk 
     252          int len = in.readInt() + in.readInt(); 
     253          in.skipBytes(4); 
     254 
     255          byte[] b = new byte[len]; 
     256          in.read(b); 
     257 
     258          String s = new String(b); 
     259 
     260          if (s.startsWith("ImageDataSeq")) { 
     261            // found pixel data 
     262            int ndx = Integer.parseInt(s.substring(13, s.indexOf("!"))); 
     263            offsets[ndx] = in.getFilePointer() - len + s.indexOf("!") + 9;  
     264          } 
     265          else if (s.startsWith("Image")) { 
     266            // XML metadata 
     267             
     268            ND2Handler handler = new ND2Handler(); 
     269 
     270            s = s.substring(s.indexOf("!") + 1); 
     271 
     272            // strip out invalid characters 
     273            for (int i=0; i<s.length(); i++) { 
     274              char c = s.charAt(i); 
     275              if (Character.isISOControl(c) || !Character.isDefined(c)) { 
     276                s = s.replace(c, ' '); 
     277              }  
     278            } 
     279           
     280            try { 
     281              SAXParser parser = SAX_FACTORY.newSAXParser(); 
     282              parser.parse(new ByteArrayInputStream(s.getBytes()), handler); 
     283            } 
     284            catch (ParserConfigurationException exc) { 
     285              throw new FormatException(exc); 
     286            }  
     287            catch (SAXException exc) { 
     288              throw new FormatException(exc); 
     289            } 
     290          } 
     291 
     292          if (core.imageCount[0] > 0 && offsets == null) { 
     293            offsets = new long[core.imageCount[0]]; 
     294          } 
     295 
     296          if (in.getFilePointer() < in.length() - 1) { 
     297            if (in.read() != -38) in.skipBytes(15); 
     298            else in.seek(in.getFilePointer() - 1); 
     299          }  
     300        } 
     301      } 
     302 
     303      core.sizeC[0] = 1; 
     304      core.currentOrder[0] = "XYCZT"; 
     305      core.rgb[0] = false; 
     306      core.littleEndian[0] = true; 
     307 
     308      return;  
     309    } 
     310    else in.seek(0); 
     311 
     312    isJPEG = true; 
    204313 
    205314    status("Calculating image offsets"); 
     
    557666  } 
    558667 
     668  // -- Helper class -- 
     669 
     670  /** SAX handler for parsing XML. */ 
     671  class ND2Handler extends DefaultHandler { 
     672    public void startElement(String uri, String localName, String qName, 
     673      Attributes attributes) 
     674    { 
     675      if (qName.equals("uiWidth")) { 
     676        core.sizeX[0] = Integer.parseInt(attributes.getValue("value")); 
     677      } 
     678      else if (qName.equals("uiWidthBytes")) { 
     679        int bytes =  
     680          Integer.parseInt(attributes.getValue("value")) / core.sizeX[0]; 
     681        switch (bytes) { 
     682          case 2: 
     683            core.pixelType[0] = FormatTools.UINT16; 
     684            break; 
     685          case 4: 
     686            core.pixelType[0] = FormatTools.UINT32; 
     687            break;  
     688          default: core.pixelType[0] = FormatTools.UINT8; 
     689        } 
     690      }  
     691      else if (qName.equals("uiHeight")) { 
     692        core.sizeY[0] = Integer.parseInt(attributes.getValue("value")); 
     693      } 
     694      else if (qName.equals("uiCount")) { 
     695        int n = Integer.parseInt(attributes.getValue("value"));  
     696        if (core.imageCount[0] == 0) { 
     697          core.imageCount[0] = n; 
     698          core.sizeZ[0] = n; 
     699        }  
     700        core.sizeT[0] = 1; 
     701      } 
     702      else { 
     703        addMeta(qName, attributes.getValue("value")); 
     704      } 
     705    } 
     706  } 
     707 
    559708} 
  • trunk/loci/formats/whats-new.txt

    r2876 r2878  
    22* Fixed issues with ICS, ND2, MicroManager, Leica LEI, and FV1000 OIF 
    33* Added support for large (> 2 GB) ND2 files 
     4* Added support for new version of ND2 
    45* Minor enhancements to ImageJ importer 
    56* Implemented more flexible logging 
Note: See TracChangeset for help on using the changeset viewer.