Changeset 4148


Ignore:
Timestamp:
07/01/08 12:10:51 (12 years ago)
Author:
melissa
Message:

Some ND2 cleanup - non-JPEG files should initialize slightly faster now.

File:
1 edited

Legend:

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

    r4139 r4148  
    2424package loci.formats.in; 
    2525 
     26import java.awt.Point; 
    2627import java.io.*; 
    2728import java.util.*; 
     
    2930import javax.xml.parsers.*; 
    3031import loci.formats.*; 
     32import loci.formats.codec.ByteVector; 
    3133import loci.formats.codec.JPEG2000Codec; 
    3234import loci.formats.meta.FilterMetadata; 
     
    168170      in.skipBytes(y * core.sizeX[series] * pixel); 
    169171      if (core.sizeX[series] == w) { 
    170  
     172        in.read(buf); 
    171173      } 
    172174      else { 
     
    252254      in.order(true); 
    253255 
    254       byte[] b = new byte[1024 * 1024]; 
    255       int numValidPlanes = 0; 
    256       while (in.getFilePointer() < in.length()) { 
    257         if (in.read() == -38 && in.read() == -50 && in.read() == -66 && 
    258           in.read() == 10) 
     256      // assemble offsets to each block 
     257 
     258      Vector imageOffsets = new Vector(); 
     259      Vector imageLengths = new Vector(); 
     260      Vector xmlOffsets = new Vector(); 
     261      Vector xmlLengths = new Vector(); 
     262      Vector customDataOffsets = new Vector(); 
     263      Vector customDataLengths = new Vector(); 
     264 
     265      while (in.getFilePointer() < in.length() && in.getFilePointer() >= 0) { 
     266        while (in.read() != -38); 
     267        in.skipBytes(3); 
     268 
     269        int lenOne = in.readInt(); 
     270        int lenTwo = in.readInt(); 
     271        int len = lenOne + lenTwo; 
     272        in.skipBytes(4); 
     273 
     274        String blockType = in.readString(12); 
     275        long fp = in.getFilePointer() - 12; 
     276        in.skipBytes(len - 12); 
     277 
     278        if (blockType.startsWith("ImageDataSeq")) { 
     279          imageOffsets.add(new Long(fp)); 
     280          imageLengths.add(new Point(lenOne, lenTwo)); 
     281        } 
     282        else if (blockType.startsWith("Image")) { 
     283          xmlOffsets.add(new Long(fp)); 
     284          xmlLengths.add(new Point(lenOne, lenTwo)); 
     285        } 
     286        else if (blockType.startsWith("CustomData|A")) { 
     287          customDataOffsets.add(new Long(fp)); 
     288          customDataLengths.add(new Point(lenOne, lenTwo)); 
     289        } 
     290      } 
     291 
     292      // parse XML blocks 
     293 
     294      ND2Handler handler = new ND2Handler(); 
     295      ByteVector xml = new ByteVector(); 
     296 
     297      for (int i=0; i<xmlOffsets.size(); i++) { 
     298        long offset = ((Long) xmlOffsets.get(i)).longValue(); 
     299        Point p = (Point) xmlLengths.get(i); 
     300        int length = (int) (p.x + p.y); 
     301 
     302        byte[] b = new byte[length]; 
     303        in.seek(offset); 
     304        in.read(b); 
     305 
     306        // strip out invalid characters 
     307        int off = 0; 
     308        for (int j=0; j<length; j++) { 
     309          char c = (char) b[j]; 
     310          if ((off == 0 && c == '!') || c == 0) off = j + 1; 
     311          if (Character.isISOControl(c) || !Character.isDefined(c)) { 
     312            b[j] = (byte) ' '; 
     313          } 
     314        } 
     315 
     316        if (length - off >= 5 && b[off] == '<' && b[off + 1] == '?' && 
     317          b[off + 2] == 'x' && b[off + 3] == 'm' && b[off + 4] == 'l') 
    259318        { 
    260           // found a data chunk 
    261           int lenOne = in.readInt(); 
    262           int lenTwo = in.readInt(); 
    263           int len = lenOne + lenTwo; 
    264           if (len > b.length) { 
    265             // make sure size at least doubles, for efficiency 
    266             int size = b.length + b.length; 
    267             if (size < len) size = len; 
    268             b = new byte[size]; 
    269           } 
    270           in.skipBytes(4); 
    271  
    272           if (debug) { 
    273             debug("Reading chunk of size " + len + 
    274               " at position " + in.getFilePointer()); 
    275           } 
    276           int n = in.read(b, 0, len); 
    277           if (n < len) break; 
    278  
    279           if (len >= 12 && b[0] == 'I' && b[1] == 'm' && b[2] == 'a' && 
    280             b[3] == 'g' && b[4] == 'e' && b[5] == 'D' && b[6] == 'a' && 
    281             b[7] == 't' && b[8] == 'a' && b[9] == 'S' && b[10] == 'e' && 
    282             b[11] == 'q') // b.startsWith("ImageDataSeq") 
    283           { 
    284             // found pixel data 
    285  
    286             StringBuffer sb = new StringBuffer(); 
    287             int pt = 13; 
    288             while (b[pt] != '!') { 
    289               sb.append((char) b[pt]); 
    290               pt++; 
    291             } 
    292             int ndx = Integer.parseInt(sb.toString()); 
    293             if (core.sizeC[0] == 0 && core.sizeX[0] != 0 && core.sizeY[0] != 0) 
    294             { 
    295               Arrays.fill(core.sizeC, len / (core.sizeX[0] * core.sizeY[0] * 
    296                 FormatTools.getBytesPerPixel(core.pixelType[0]))); 
    297             } 
    298             int seriesNdx = ndx / (core.sizeT[0] * core.sizeZ[0]); 
    299             int plane = ndx % (core.sizeT[0] * core.sizeZ[0]); 
    300             if (seriesNdx >= offsets.length) { 
    301               long[][] tmpOffsets = offsets; 
    302               offsets = new long[seriesNdx + 1][tmpOffsets[0].length]; 
    303               for (int i=0; i<tmpOffsets.length; i++) { 
    304                 System.arraycopy(tmpOffsets[i], 0, offsets[i], 0, 
    305                   offsets[i].length); 
    306               } 
    307             } 
    308             offsets[seriesNdx][plane] = in.getFilePointer() - lenTwo + 8; 
    309             numValidPlanes++; 
    310           } 
    311           else if (len >= 5 && b[0] == 'I' && b[1] == 'm' && b[2] == 'a' && 
    312             b[3] == 'g' && b[4] == 'e') // b.startsWith("Image") 
    313           { 
    314             // XML metadata 
    315  
    316             ND2Handler handler = new ND2Handler(); 
    317  
    318             // strip out invalid characters 
    319             int off = 0; 
    320             for (int i=0; i<len; i++) { 
    321               char c = (char) b[i]; 
    322               if ((off == 0 && c == '!') || c == 0) off = i + 1; 
    323  
    324               if (Character.isISOControl(c) || !Character.isDefined(c)) { 
    325                 b[i] = (byte) ' '; 
    326               } 
    327             } 
    328  
    329             if (len - off >= 5 && b[off] == '<' && b[off + 1] == '?' && 
    330               b[off + 2] == 'x' && b[off + 3] == 'm' && 
    331               b[off + 4] == 'l') // b.substring(off, off + 5).equals("<?xml") 
    332             { 
    333               ByteArrayInputStream s = 
    334                 new ByteArrayInputStream(b, off, len - off); 
    335  
    336               try { 
    337                 SAXParser parser = SAX_FACTORY.newSAXParser(); 
    338                 parser.parse(s, handler); 
    339               } 
    340               catch (ParserConfigurationException exc) { 
    341                 throw new FormatException(exc); 
    342               } 
    343               catch (SAXException exc) { 
    344                 throw new FormatException(exc); 
    345               } 
    346  
    347               s.close(); 
    348  
    349               // adjust SizeT, if necessary 
    350               long planeSize = core.sizeX[0] * core.sizeY[0] * 
    351                 FormatTools.getBytesPerPixel(core.pixelType[0]) * core.sizeC[0]; 
    352               if (planeSize*core.imageCount[0]*core.imageCount.length >= 
    353                 in.length() && !isLossless) 
    354               { 
    355                 int approxPlanes = (int) (in.length() / planeSize); 
    356                 core.sizeT[0] = approxPlanes / core.imageCount.length; 
    357                 if (core.sizeT[0] * core.imageCount.length < approxPlanes) { 
    358                   core.sizeT[0]++; 
    359                 } 
    360                 core.imageCount[0] = core.sizeT[0]; 
    361                 core.sizeZ[0] = 1; 
    362               } 
     319          boolean endBracketFound = false; 
     320          while (!endBracketFound) { 
     321            if (b[off++] == '>') { 
     322              endBracketFound = true; 
    363323            } 
    364324          } 
    365           else if (len >= 12 && b[0] == 'C' && b[1] == 'u' && b[2] == 's' && 
    366             b[3] == 't' && b[4] == 'o' && b[5] == 'm' && b[6] == 'D' && 
    367             b[7] == 'a' && b[8] == 't' && b[9] == 'a'&&b[10]=='|'&&b[11]=='A') 
    368             // b.startsWith("CustomData|A") 
    369           { 
    370             // the acqtimecache is a undeliniated stream of doubles 
    371             int off = 0; 
    372             for (int i=0; i<len; i++) { 
    373               char c = (char) b[i]; 
    374               if ((off == 0 && c == '!')) off = i + 1; 
    375             } 
    376             for (int j = off; j<len; j+=8) { 
    377               double s = DataTools.bytesToDouble(b, j, 8, true); 
    378               tsT.add(new Double(s)); 
    379               addMeta("timestamp " + (tsT.size() - 1), String.valueOf(s)); 
    380             } 
    381           } 
    382  
    383           if (core.imageCount[0] > 0 && offsets == null) { 
    384             if (numSeries == 0) numSeries = 1; 
    385             offsets = new long[numSeries][core.imageCount[0]]; 
    386             if (numSeries > 1) { 
    387               int x = core.sizeX[0]; 
    388               int y = core.sizeY[0]; 
    389               int z = core.sizeZ[0]; 
    390               int c = core.sizeC[0]; 
    391               int t = core.sizeT[0]; 
    392               int count = core.imageCount[0]; 
    393               int pixelType = core.pixelType[0]; 
    394               core = new CoreMetadata(numSeries); 
    395               Arrays.fill(core.sizeX, x); 
    396               Arrays.fill(core.sizeY, y); 
    397               Arrays.fill(core.sizeZ, z); 
    398               Arrays.fill(core.sizeC, c); 
    399               Arrays.fill(core.sizeT, t); 
    400               Arrays.fill(core.imageCount, count); 
    401               Arrays.fill(core.pixelType, pixelType); 
    402             } 
    403           } 
    404  
    405           if (in.getFilePointer() < in.length() - 1) { 
    406             if (in.read() != -38) in.skipBytes(15); 
    407             else in.seek(in.getFilePointer() - 1); 
    408           } 
    409         } 
    410       } 
    411  
    412       if (offsets.length != core.imageCount.length && core.imageCount[0] == 1) { 
    413         core.imageCount[0] = offsets.length; 
    414         if (core.sizeC[0] == 0) core.sizeC[0] = 1; 
    415         core.sizeT[0] = offsets.length / core.sizeC[0]; 
    416         if (core.sizeT[0] == 0) core.sizeT[0] = 1; 
     325          xml.add(b, off, b.length - off); 
     326        } 
     327      } 
     328 
     329      String xmlString = new String(xml.toByteArray()); 
     330      xmlString = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ND2>" + 
     331        xmlString + "</ND2>"; 
     332 
     333      ByteArrayInputStream s = 
     334        new ByteArrayInputStream(xmlString.getBytes(), 0, xmlString.length()); 
     335 
     336      try { 
     337        SAXParser parser = SAX_FACTORY.newSAXParser(); 
     338        parser.parse(s, handler); 
     339      } 
     340      catch (ParserConfigurationException exc) { 
     341        throw new FormatException(exc); 
     342      } 
     343      catch (SAXException exc) { 
     344        throw new FormatException(exc); 
     345      } 
     346 
     347      s.close(); 
     348 
     349      // adjust SizeT, if necessary 
     350      long planeSize = core.sizeX[0] * core.sizeY[0] * 
     351        FormatTools.getBytesPerPixel(core.pixelType[0]) * core.sizeC[0]; 
     352      if (planeSize*core.imageCount[0]*core.imageCount.length >= 
     353        in.length() && !isLossless) 
     354      { 
     355        int approxPlanes = (int) (in.length() / planeSize); 
     356        core.sizeT[0] = approxPlanes / core.imageCount.length; 
     357        if (core.sizeT[0] * core.imageCount.length < approxPlanes) { 
     358          core.sizeT[0]++; 
     359        } 
     360        core.imageCount[0] = core.sizeT[0]; 
    417361        core.sizeZ[0] = 1; 
    418         long[][] tmpOffsets = offsets; 
    419         offsets = new long[core.imageCount.length][core.imageCount[0]]; 
    420         for (int i=0; i<offsets.length; i++) { 
    421           for (int j=0; j<offsets[i].length; j++) { 
    422             offsets[i][j] = tmpOffsets[j][i]; 
    423           } 
    424         } 
    425       } 
    426       else if (offsets.length != core.imageCount.length) { 
     362      } 
     363 
     364      // read first CustomData block 
     365 
     366      if (customDataOffsets.size() > 0) { 
     367        in.seek(((Long) customDataOffsets.get(0)).longValue()); 
     368        Point p = (Point) customDataLengths.get(0); 
     369        int len = (int) (p.x + p.y); 
     370        byte[] b = new byte[len]; 
     371        in.read(b); 
     372 
     373        // the acqtimecache is a undeliniated stream of doubles 
     374        int off = 0; 
     375        for (int i=0; i<len; i++) { 
     376          char c = (char) b[i]; 
     377          if ((off == 0 && c == '!')) off = i + 1; 
     378        } 
     379        for (int j = off; j<len; j+=8) { 
     380          double time = DataTools.bytesToDouble(b, j, 8, true); 
     381          tsT.add(new Double(time)); 
     382          addMeta("timestamp " + (tsT.size() - 1), String.valueOf(time)); 
     383        } 
     384        b = null; 
     385      } 
     386 
     387      // rearrange image data offsets 
     388 
     389      if (numSeries == 0) numSeries = 1; 
     390 
     391      offsets = new long[numSeries][core.imageCount[0]]; 
     392 
     393      if (core.sizeZ[0] == 0) Arrays.fill(core.sizeZ, 1); 
     394      if (core.sizeT[0] == 0) Arrays.fill(core.sizeT, 1); 
     395 
     396      for (int i=0; i<imageOffsets.size(); i++) { 
     397        long offset = ((Long) imageOffsets.get(i)).longValue(); 
     398        Point p = (Point) imageLengths.get(i); 
     399        int length = (int) (p.x + p.y); 
     400 
     401        in.seek(offset); 
     402        byte[] b = new byte[length]; 
     403        in.read(b); 
     404 
     405        StringBuffer sb = new StringBuffer(); 
     406        int pt = 13; 
     407        while (b[pt] != '!') { 
     408          sb.append((char) b[pt++]); 
     409        } 
     410        int ndx = Integer.parseInt(sb.toString()); 
     411 
     412        if (core.sizeC[0] == 0) { 
     413          Arrays.fill(core.sizeC, length / (core.sizeX[0] * core.sizeY[0] * 
     414            FormatTools.getBytesPerPixel(core.pixelType[0]))); 
     415        } 
     416 
     417        int seriesIndex = ndx / (core.sizeT[0] * core.sizeZ[0]); 
     418        int plane = ndx % (core.sizeT[0] * core.sizeZ[0]); 
     419 
     420        offsets[seriesIndex][plane] = offset + p.x + 8; 
     421 
     422        b = null; 
     423      } 
     424 
     425      if (offsets.length != core.imageCount.length) { 
    427426        int x = core.sizeX[0]; 
    428427        int y = core.sizeY[0]; 
     
    473472      if (core.sizeC[0] > 1) { 
    474473        if (adjustImageCount) { 
    475           int n = numValidPlanes / core.sizeT.length; 
     474          int n = imageOffsets.size() / core.sizeT.length; 
    476475          Arrays.fill(core.sizeT, n == 0 ? 1 : n); 
    477476        } 
     
    599598      while (st.hasMoreTokens()) { 
    600599        String token = st.nextToken().trim(); 
    601         if (token.indexOf("<!--") != -1) continue; 
     600        if (token.indexOf("<!--") != -1 || token.indexOf("VCAL") != -1) { 
     601          continue; 
     602        } 
    602603        if (token.startsWith("<")) sb.append(token); 
    603604      } 
     
    837838      else if (qName.startsWith("TextInfo")) { 
    838839        parseKeyAndValue(qName, attributes.getValue("Text")); 
     840        parseKeyAndValue(qName, attributes.getValue("value")); 
    839841      } 
    840842      else if (qName.equals("dCompressionParam")) { 
     
    861863 
    862864  private void parseKeyAndValue(String key, String value) { 
     865    if (key == null || value == null) return; 
    863866    addMeta(key, value); 
    864867    if (key.endsWith("dCalibration")) { 
     
    889892      } 
    890893    } 
    891     else if (key.endsWith("TextInfoItem")) { 
     894    else if (key.startsWith("TextInfoItem") || key.endsWith("TextInfoItem")) { 
    892895      value = value.replaceAll("&#x000d;&#x000a;", "\n"); 
    893896      StringTokenizer tokens = new StringTokenizer(value, "\n"); 
Note: See TracChangeset for help on using the changeset viewer.