Changeset 4083


Ignore:
Timestamp:
05/30/08 12:30:25 (12 years ago)
Author:
melissa
Message:

Use JPEG2000Codec instead of manually calling the JAI library. Somehow this fixed a JP2K channel separation bug.

File:
1 edited

Legend:

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

    r4061 r4083  
    2828import java.util.*; 
    2929import java.util.zip.*; 
    30 import javax.imageio.spi.IIORegistry; 
    31 import javax.imageio.spi.ServiceRegistry; 
    32 import javax.imageio.stream.MemoryCacheImageInputStream; 
    3330import javax.xml.parsers.*; 
    3431import loci.formats.*; 
     32import loci.formats.codec.JPEG2000Codec; 
    3533import loci.formats.meta.FilterMetadata; 
    3634import loci.formats.meta.MetadataStore; 
     
    6159  // -- Constants -- 
    6260 
    63   private static final String NO_J2K_MSG = 
    64     "The JAI Image I/O Tools are required to read ND2 files. Please " + 
    65     "obtain jai_imageio.jar from http://loci.wisc.edu/ome/formats.html"; 
    66  
    67   private static final String J2K_READER = 
    68     "com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageReader"; 
    69  
    7061  /** Factory for generating SAX parsers. */ 
    7162  public static final SAXParserFactory SAX_FACTORY = 
    7263    SAXParserFactory.newInstance(); 
    73  
    74   // -- Static fields -- 
    75  
    76   private static boolean noJ2k = false; 
    77   private static ReflectedUniverse r = createReflectedUniverse(); 
    78  
    79   private static ReflectedUniverse createReflectedUniverse() { 
    80     // NB: ImageJ does not access the jai_imageio classes with the normal 
    81     // class loading scheme, and thus the necessary service provider stuff is 
    82     // not automatically registered. Instead, we register the J2KImageReader 
    83     // with the IIORegistry manually, merely so that we can obtain a 
    84     // J2KImageReaderSpi object from the IIORegistry's service provider 
    85     // lookup function, then use it to construct a J2KImageReader object 
    86     // directly, which we can use to process ND2 files one plane at a time. 
    87  
    88     ReflectedUniverse ru = null; 
    89     try { 
    90       // register J2KImageReader with IIORegistry 
    91       String j2kReaderSpi = J2K_READER + "Spi"; 
    92       Class j2kSpiClass = null; 
    93       try { 
    94         j2kSpiClass = Class.forName(j2kReaderSpi); 
    95       } 
    96       catch (ClassNotFoundException exc) { 
    97         if (debug) LogTools.trace(exc); 
    98         noJ2k = true; 
    99       } 
    100       catch (NoClassDefFoundError err) { 
    101         if (debug) LogTools.trace(err); 
    102         noJ2k = true; 
    103       } 
    104       catch (RuntimeException exc) { 
    105         // HACK: workaround for bug in Apache Axis2 
    106         String msg = exc.getMessage(); 
    107         if (msg != null && msg.indexOf("ClassNotFound") < 0) throw exc; 
    108         if (debug) LogTools.trace(exc); 
    109         noJ2k = true; 
    110       } 
    111       IIORegistry registry = IIORegistry.getDefaultInstance(); 
    112       if (j2kSpiClass != null) { 
    113         Iterator providers = ServiceRegistry.lookupProviders(j2kSpiClass); 
    114         registry.registerServiceProviders(providers); 
    115       } 
    116  
    117       // obtain J2KImageReaderSpi instance from IIORegistry 
    118       Object j2kSpi = registry.getServiceProviderByClass(j2kSpiClass); 
    119  
    120       ru = new ReflectedUniverse(); 
    121  
    122       // for computing offsets in initFile 
    123       ru.exec("import jj2000.j2k.fileformat.reader.FileFormatReader"); 
    124       ru.exec("import jj2000.j2k.io.BEBufferedRandomAccessFile"); 
    125       ru.exec("import jj2000.j2k.util.ISRandomAccessIO"); 
    126  
    127       // for reading pixel data in openImage 
    128       ru.exec("import " + J2K_READER); 
    129       ru.setVar("j2kSpi", j2kSpi); 
    130       ru.exec("j2kReader = new J2KImageReader(j2kSpi)"); 
    131     } 
    132     catch (Throwable t) { 
    133       noJ2k = true; 
    134       if (debug) LogTools.trace(t); 
    135     } 
    136     return ru; 
    137   } 
    13864 
    13965  // -- Fields -- 
     
    203129 
    204130    if (isJPEG) { 
    205       // plane is compressed using JPEG 2000 
    206       BufferedImage b = openImage(no, x, y, w, h); 
    207       byte[][] pixels = ImageTools.getPixelBytes(b, false); 
    208       for (int i=0; i<getRGBChannelCount(); i++) { 
    209         byte[] p = ImageTools.splitChannels(pixels[series], i, 
    210           getRGBChannelCount(), bpp, false, !core.interleaved[series]); 
    211         System.arraycopy(p, 0, buf, i*p.length, p.length); 
    212       } 
    213       pixels = null; 
     131      in.seek(offsets[series][no]); 
     132      buf = new JPEG2000Codec().decompress(in, new Boolean[] { 
     133        new Boolean(core.littleEndian[series]), 
     134        new Boolean(core.interleaved[series])}); 
    214135    } 
    215136    else if (isLossless) { 
     
    256177  } 
    257178 
    258   /* @see loci.formats.IFormatReader#openImage(int, int, int, int, int) */ 
    259   public BufferedImage openImage(int no, int x, int y, int w, int h) 
    260     throws FormatException, IOException 
    261   { 
    262     if (legacy) return openImage(no, x, y, w, h); 
    263     if (!isJPEG) { 
    264       return ImageTools.makeImage(openBytes(no, x, y, w, h), core.sizeX[series], 
    265         core.sizeY[series], getRGBChannelCount(), core.interleaved[series], 
    266         FormatTools.getBytesPerPixel(core.pixelType[series]), 
    267         core.littleEndian[series]); 
    268     } 
    269  
    270     FormatTools.assertId(currentId, true, 1); 
    271     FormatTools.checkPlaneNumber(this, no); 
    272  
    273     in.seek(offsets[series][no]); 
    274  
    275     long len = no < core.imageCount[series] - 1 ? offsets[series][no + 1] - 
    276       offsets[series][no] : in.length() - offsets[series][no]; 
    277  
    278     byte[] b = new byte[(int) len]; 
    279     in.readFully(b); 
    280  
    281     ByteArrayInputStream bis = new ByteArrayInputStream(b); 
    282     // NB: Even after registering J2KImageReader with 
    283     // IIORegistry manually, the following still does not work: 
    284     //BufferedImage img = ImageIO.read(bis); 
    285     MemoryCacheImageInputStream mciis = new MemoryCacheImageInputStream(bis); 
    286     BufferedImage img = null; 
    287     try { 
    288       r.setVar("mciis", mciis); 
    289       r.exec("j2kReader.setInput(mciis)"); 
    290       r.setVar("zero", 0); 
    291       r.setVar("param", null); 
    292       img = (BufferedImage) r.exec("j2kReader.read(zero, param)"); 
    293     } 
    294     catch (ReflectException exc) { 
    295       throw new FormatException(exc); 
    296     } 
    297     bis.close(); 
    298     mciis.close(); 
    299     b = null; 
    300  
    301     return img.getSubimage(x, y, w, h); 
    302   } 
    303  
    304179  /* @see loci.formats.IFormatReader#setNormalized(boolean) */ 
    305180  public void setNormalized(boolean normalize) { 
     
    354229  protected void initFile(String id) throws FormatException, IOException { 
    355230    if (debug) debug("ND2Reader.initFile(" + id + ")"); 
    356     if (noJ2k) throw new FormatException(NO_J2K_MSG); 
    357231    super.initFile(id); 
    358232 
     
    647521    // assemble offsets to each plane 
    648522 
     523    int x = 0, y = 0, c = 0, type = 0; 
     524 
    649525    while (!lastBoxFound) { 
    650526      pos = in.getFilePointer(); 
     
    658534        vs.add(new Long(pos)); 
    659535      } 
    660       if (!lastBoxFound) in.skipBytes(length); 
     536      else if (box == 0x6a703268) { 
     537        in.skipBytes(4); 
     538        String s = in.readString(4); 
     539        if (s.equals("ihdr")) { 
     540          y = in.readInt(); 
     541          x = in.readInt(); 
     542          c = in.readShort(); 
     543          type = in.readInt(); 
     544          if (type == 0xf070100) type = FormatTools.UINT16; 
     545          else type = FormatTools.UINT8; 
     546        } 
     547      } 
     548      if (!lastBoxFound && box != 0x6a703268) in.skipBytes(length); 
    661549    } 
    662550 
     
    724612      int len = b.length; 
    725613      for (int i=0; i<len; i++) { 
    726         char c = (char) b[i]; 
    727         if (offset == 0 && c == '!') offset = i + 1; 
    728  
    729         if (Character.isISOControl(c) || !Character.isDefined(c)) { 
     614        char ch = (char) b[i]; 
     615        if (offset == 0 && ch == '!') offset = i + 1; 
     616 
     617        if (Character.isISOControl(ch) || !Character.isDefined(ch)) { 
    730618          b[i] = (byte) ' '; 
    731619        } 
     
    794682    in.seek(offsets[0][0]); 
    795683 
    796     long len = 0 < core.imageCount[0] - 1 ? offsets[0][1] - 
    797       offsets[0][0] : in.length() - offsets[0][0]; 
    798  
    799     byte[] b = new byte[(int) len]; 
    800     in.readFully(b); 
    801  
    802     ByteArrayInputStream bis = new ByteArrayInputStream(b); 
    803     // NB: Even after registering J2KImageReader with 
    804     // IIORegistry manually, the following still does not work: 
    805     //BufferedImage img = ImageIO.read(bis); 
    806     MemoryCacheImageInputStream mciis = new MemoryCacheImageInputStream(bis); 
    807     BufferedImage img = null; 
    808     try { 
    809       r.setVar("mciis", mciis); 
    810       r.exec("j2kReader.setInput(mciis)"); 
    811       r.setVar("zero", 0); 
    812       r.setVar("param", null); 
    813       img = (BufferedImage) r.exec("j2kReader.read(zero, param)"); 
    814     } 
    815     catch (ReflectException exc) { 
    816       throw new FormatException(exc); 
    817     } 
    818     bis.close(); 
    819     mciis.close(); 
    820     b = null; 
    821  
    822     Arrays.fill(core.sizeX, img.getWidth()); 
    823     Arrays.fill(core.sizeY, img.getHeight()); 
     684    Arrays.fill(core.sizeX, x); 
     685    Arrays.fill(core.sizeY, y); 
    824686    if (core.sizeC[0] == 0) core.sizeC[0] = 1; 
    825     int numBands = img.getRaster().getNumBands(); 
    826     int c = numBands > 1 ? numBands : core.sizeC[0]; 
     687    int numBands = c; 
     688    c = numBands > 1 ? numBands : core.sizeC[0]; 
    827689    if (numBands == 1 && core.imageCount[0] == 1) c = 1; 
    828690    Arrays.fill(core.sizeC, c); 
    829691    Arrays.fill(core.rgb, numBands > 1); 
    830     Arrays.fill(core.pixelType, ImageTools.getPixelType(img)); 
     692    Arrays.fill(core.pixelType, type); 
    831693 
    832694    if (core.rgb[0] && core.imageCount[0] > core.sizeZ[0] * core.sizeT[0]) { 
Note: See TracChangeset for help on using the changeset viewer.