Changeset 2811


Ignore:
Timestamp:
05/24/07 09:34:41 (13 years ago)
Author:
melissa
Message:

Reworked most of the logic in initFile to be more general.

File:
1 edited

Legend:

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

    r2800 r2811  
    2727import java.awt.image.BufferedImage; 
    2828import java.io.*; 
     29import java.util.Vector; 
    2930 
    3031import loci.formats.*; 
     
    3233/** 
    3334 * SlidebookReader is the file format reader for 3I Slidebook files. 
     35 * The strategies employed by this reader are highly suboptimal, as we 
     36 * have very little information on the Slidebook format. 
    3437 * 
    3538 * @author Melissa Linkert linkert at wisc.edu 
     
    3740public class SlidebookReader extends FormatReader { 
    3841 
    39   // -- Constants -- 
    40  
    4142  // -- Fields -- 
    4243 
    43   /** Offset to pixel data. */ 
    44   private long offset = 256; 
    45  
    46   /** Number of bytes per pixel. */ 
    47   private int bpp; 
    48  
    49   private int uCount = 0; 
    50   private int planeCount = 0; 
     44  private Vector metadataOffsets; 
     45  private Vector pixelOffsets; 
     46  private Vector pixelLengths; 
    5147 
    5248  // -- Constructor -- 
     
    8278      throw new FormatException("Buffer too small."); 
    8379    } 
    84     in.seek(offset + (no * core.sizeX[0] * core.sizeY[0] * 2)); 
    85  
    86     uCount = 0; 
    87     long fp1 = in.getFilePointer(); 
    88     skipDataBlocks(planeCount); 
    89     long fp2 = in.getFilePointer(); 
    90     offset += fp2 - fp1; 
    91     if (fp2 - fp1 > 0) planeCount = 1; 
    92     else planeCount++; 
    93  
     80 
     81    int plane = core.sizeX[0] * core.sizeY[0] * 2; 
     82   
     83    long relativeOffset = plane * no; 
     84    int ndx = 0; 
     85    long bytes = 0; 
     86 
     87    int oldNo = no; 
     88    while (relativeOffset - bytes > 4) { 
     89      long len = ((Long) pixelLengths.get(ndx)).longValue(); 
     90      double planes = (double) len / plane; 
     91      if ((int) planes < planes) len += 2;  
     92       
     93      if (bytes + len <= relativeOffset) { 
     94        ndx++; 
     95        no -= (len / plane);  
     96      } 
     97      bytes += len;  
     98    } 
     99 
     100    long offset = ((Long) pixelOffsets.get(ndx)).longValue() + plane * no; 
     101    in.seek(offset);  
    94102    in.read(buf); 
    95103    return buf; 
     
    100108    FormatTools.assertId(currentId, true, 1); 
    101109    return ImageTools.makeImage(openBytes(no), core.sizeX[0], 
    102       core.sizeY[0], 1, true, bpp, true); 
     110      core.sizeY[0], 1, true, 2, true); 
    103111  } 
    104112 
     
    111119    in = new RandomAccessStream(id); 
    112120 
    113     status("Determining series count"); 
     121    status("Finding offsets to pixel data"); 
    114122 
    115123    in.skipBytes(4); 
    116124    core.littleEndian[0] = in.read() == 0x49; 
    117125 
    118     bpp = 2; 
    119  
    120     // check if there are multiple "series" - note that each series has the 
    121     // same dimensions, so we can display each plane as part of the same series 
    122  
    123     in.seek(160); 
    124     boolean multiSeries = DataTools.read4UnsignedBytes(in, true) > 1; 
    125  
    126     // pixel data always begins at 0x6b0 
    127  
    128     in.seek(1792); 
    129  
    130     // determine the number of images 
    131  
    132     status("Determining image count"); 
    133  
    134     byte[] buf = new byte[8192]; 
    135     boolean found = false; 
    136  
    137     int count = 0; 
    138     int n = in.read(buf); 
    139  
    140     while (!found && in.getFilePointer() < in.length()) { 
    141       count += n; 
    142       for (int i=0; i<n-3; i++) { 
    143         found = buf[i] == 0x68 && buf[i+1] == 0x00 && buf[i+2] == 0x00 && 
    144           buf[i+3] == 0x01; 
    145         if (found) { 
    146           count -= (n - i); 
    147           i = n; 
     126    metadataOffsets = new Vector(); 
     127    pixelOffsets = new Vector(); 
     128    pixelLengths = new Vector(); 
     129 
     130    in.seek(0); 
     131 
     132    while (in.getFilePointer() < in.length() - 8) { 
     133      in.skipBytes(4); 
     134      int checkOne = in.read(); 
     135      int checkTwo = in.read(); 
     136      if (checkOne == 'I' && checkTwo == 'I') { 
     137        metadataOffsets.add(new Long(in.getFilePointer() - 6)); 
     138        if (in.read() == 0) in.skipBytes(249); 
     139        else in.skipBytes(121); 
     140      } 
     141      else { 
     142        String s = null;  
     143        long fp = in.getFilePointer() - 6;  
     144        in.seek(fp); 
     145        int len = in.read(); 
     146        if (len > 0 && len < 32) {  
     147          byte[] b = new byte[len]; 
     148          in.read(b); 
     149          s = new String(b); 
     150        }  
     151 
     152        if (s != null && s.indexOf("Annotation") != -1) { 
     153          if (s.equals("CTimelapseAnnotation")) { 
     154            in.skipBytes(41); 
     155            if (in.read() == 0) in.skipBytes(10);  
     156            else in.seek(in.getFilePointer() - 1); 
     157          }  
     158          else if (s.equals("CIntensityBarAnnotation")) { 
     159            in.skipBytes(56); 
     160            int n = in.read();  
     161            while (n == 0 || n < 6 || n > 0x80) n = in.read();  
     162            in.seek(in.getFilePointer() - 1); 
     163          }  
     164          else if (s.equals("CCubeAnnotation")) { 
     165            in.skipBytes(66); 
     166            int n = in.read();  
     167            if (n != 0) in.seek(in.getFilePointer() - 1); 
     168          } 
     169          else if (s.equals("CScaleBarAnnotation")) { 
     170            in.skipBytes(52);  
     171          }  
    148172        } 
    149       } 
    150       byte[] tmp = buf; 
    151       buf = new byte[8192]; 
    152       System.arraycopy(tmp, tmp.length - 20, buf, 0, 20); 
    153       n = in.read(buf, 20, buf.length - 20); 
    154     } 
    155  
    156     in.seek(1792 + count - 20); 
    157  
    158     int check = in.read(); 
    159     long lastH = 0; 
    160     while (check == 'h') { 
    161       lastH = in.getFilePointer(); 
    162       in.skipBytes(255); 
    163       core.sizeC[0]++; 
    164       check = in.read(); 
    165     } 
    166  
    167     // scan the remaining bytes for the "CTimelapseAnnotation" tag 
    168  
    169     in.seek(1792 + count); 
    170     buf = new byte[8192]; 
    171     n = in.read(buf); 
    172     while (n > 0) { 
    173       String t = new String(buf); 
    174       t.trim(); 
    175       while (t.indexOf("CTimelapseAnnotation") != -1) { 
    176         t = t.substring(t.indexOf("CTimelapseAnnotation") + 20); 
    177         core.sizeT[0]++; 
    178       } 
    179       byte[] tmp = buf; 
    180       buf = new byte[8192]; 
    181       System.arraycopy(tmp, tmp.length - 20, buf, 0, 20); 
    182       n = in.read(buf, 20, buf.length - 20); 
    183     } 
    184  
    185     // look for the first "i...II" block - this will have the width and height 
    186  
    187     status("Populating metadata"); 
    188  
    189     in.seek(lastH); 
    190     in.skipBytes(335); 
    191  
    192     core.sizeX[0] = DataTools.read2UnsignedBytes(in, true); 
    193     core.sizeY[0] = DataTools.read2UnsignedBytes(in, true); 
    194  
    195     if (multiSeries) { 
    196       core.sizeX[0] /= core.sizeC[0]; 
    197       core.sizeY[0] /= core.sizeC[0]; 
    198     } 
    199  
    200     core.imageCount[0] = count / (core.sizeX[0] * core.sizeY[0] * bpp); 
    201  
    202     float planes = (float) count / (float) (core.sizeX[0]*core.sizeY[0] * bpp); 
    203     core.imageCount[0] = (int) planes; 
    204  
    205     core.sizeZ[0] = core.imageCount[0] / (core.sizeC[0] * core.sizeT[0]); 
    206  
    207     core.pixelType[0] = FormatTools.UINT16; 
    208     core.currentOrder[0] = "XY"; 
     173        else { 
     174          in.seek(fp);  
     175          pixelOffsets.add(new Long(fp)); 
     176          try { 
     177            byte[] buf = new byte[8192];  
     178            boolean found = false; 
     179            int n = in.read(buf); 
     180 
     181            while (!found && in.getFilePointer() < in.length()) { 
     182              for (int i=0; i<buf.length-6; i++) { 
     183                if (buf[i] == 'h' && buf[i+4] == 'I' && buf[i+5] == 'I') { 
     184                  found = true; 
     185                  in.seek(in.getFilePointer() - n + i - 20);  
     186                  break;  
     187                } 
     188              } 
     189              if (!found) { 
     190                byte[] tmp = buf; 
     191                buf = new byte[8192];  
     192                System.arraycopy(tmp, tmp.length - 20, buf, 0, 20); 
     193                n = in.read(buf, 20, buf.length - 20); 
     194              }  
     195            } 
     196             
     197            if (in.getFilePointer() <= in.length()) {  
     198              pixelLengths.add(new Long(in.getFilePointer() - fp));  
     199            } 
     200            else pixelOffsets.remove(pixelOffsets.size() - 1); 
     201          } 
     202          catch (EOFException e) { 
     203            pixelOffsets.remove(pixelOffsets.size() - 1); 
     204          } 
     205        } 
     206      } 
     207    } 
     208 
     209    status("Determining dimensions"); 
     210 
     211    // determine total number of pixel bytes 
     212 
     213    long pixelBytes = 0; 
     214    for (int i=0; i<pixelLengths.size(); i++) { 
     215      pixelBytes += ((Long) pixelLengths.get(i)).longValue();  
     216    } 
     217 
     218    // try to find the width and height  
     219    int iCount = 0;  
     220    int hCount = 0;  
     221    int uCount = 0;  
     222    for (int i=0; i<metadataOffsets.size(); i++) { 
     223      long off = ((Long) metadataOffsets.get(i)).longValue(); 
     224      in.seek(off); 
     225      int n = in.read();  
     226      if (n == 'i') { 
     227        in.skipBytes(79);  
     228        core.sizeX[0] = DataTools.read2UnsignedBytes(in, true);  
     229        core.sizeY[0] = DataTools.read2UnsignedBytes(in, true);  
     230        iCount++;  
     231      } 
     232      else if (n == 'h') hCount++;  
     233      else if (n == 'u') uCount++;  
     234    } 
     235 
    209236    core.rgb[0] = false; 
    210     core.interleaved[0] = false; 
    211  
    212     if (core.imageCount[0] != (core.sizeZ[0] * core.sizeC[0] * core.sizeT[0])) { 
    213       core.sizeZ[0] = 1; 
    214       core.sizeT[0] = core.imageCount[0] / core.sizeC[0]; 
    215     } 
    216  
    217     int[] dims = {core.sizeZ[0], core.sizeC[0], core.sizeT[0]}; 
    218     String[] names = {"Z", "C", "T"}; 
    219     int max = 0, min = Integer.MAX_VALUE; 
    220     int maxNdx = 0, minNdx = 0, medNdx = 0; 
    221     for (int i=0; i<dims.length; i++) { 
    222       if (dims[i] > max) { 
    223         max = dims[i]; 
    224         maxNdx = i; 
    225       } 
    226       else if (dims[i] < min) { 
    227         min = dims[i]; 
    228         minNdx = i; 
    229       } 
    230     } 
    231  
    232     for (int i=0; i<dims.length; i++) { 
    233       if (maxNdx != i && minNdx != i) medNdx = i; 
    234     } 
    235  
    236     core.currentOrder[0] += names[maxNdx]; 
    237     core.currentOrder[0] += names[medNdx]; 
    238     core.currentOrder[0] += names[minNdx]; 
    239  
     237    core.sizeC[0] = iCount < 5 ? iCount : 1; 
     238     
     239    if (core.sizeC[0] == 0) core.sizeC[0] = 1; 
    240240    if (core.sizeZ[0] == 0) core.sizeZ[0] = 1; 
    241     if (core.sizeC[0] == 0) core.sizeC[0] = 1; 
    242241    if (core.sizeT[0] == 0) core.sizeT[0] = 1; 
    243242 
    244     if (core.imageCount[0] == 0) { 
    245       core.imageCount[0] = core.sizeZ[0] * core.sizeT[0] * core.sizeZ[0]; 
    246     } 
    247  
    248     if (core.sizeX[0] * core.sizeY[0] * 2 * core.imageCount[0] > in.length()) { 
    249       core.sizeX[0] /= 2; 
    250       core.sizeY[0] /= 2; 
    251     } 
    252  
    253     MetadataStore store = getMetadataStore(); 
    254     store.setPixels(new Integer(core.sizeX[0]), new Integer(core.sizeY[0]), 
    255       new Integer(core.sizeZ[0]), new Integer(core.sizeC[0]), 
    256       new Integer(core.sizeT[0]), new Integer(core.pixelType[0]), 
    257       new Boolean(!core.littleEndian[0]), core.currentOrder[0], null, null); 
    258     for (int i=0; i<core.sizeC[0]; i++) { 
    259       store.setLogicalChannel(i, null, null, null, null, null, null, null); 
    260     } 
    261   } 
    262  
    263   // -- Helper methods -- 
    264  
    265   private void skipDataBlocks(int n) throws IOException { 
    266     long fp = in.getFilePointer(); 
    267  
    268     int type = in.read(); 
    269     in.skipBytes(3); 
    270     int one = in.read(); 
    271     int two = in.read(); 
    272  
    273     if ((one == 0x49 && two == 0x49) || (one == 0x4d && two == 0x4d)) { 
    274       if (type == 0x69) in.skipBytes(122); 
    275       else if (type == 0x75 && uCount == n - 1) { 
    276         in.skipBytes(250); 
    277         int len = in.read(); 
    278         while (((byte) len) > 0) { 
    279           int oldLen = len; 
    280           in.skipBytes(len + 4); 
    281           len = in.read(); 
    282           in.skipBytes(len + 3); 
    283           len = in.read(); 
    284           if (in.read() != 0x43 && ((byte) len) > 0) { 
    285             in.skipBytes(len + 2); 
    286             len = in.read(); 
    287           } 
    288           else in.seek(in.getFilePointer() - 1); 
     243    if (core.sizeX[0] * core.sizeY[0] * 2 * core.sizeC[0] *  
     244      core.sizeZ[0] * core.sizeT[0] != pixelBytes && hCount > 0)  
     245    {  
     246      core.sizeZ[0] = hCount / core.sizeC[0]; 
     247    } 
     248 
     249    int n = core.sizeZ[0] * core.sizeC[0] * core.sizeT[0]; 
     250     
     251    if (uCount == core.sizeZ[0] * core.sizeT[0]) uCount = n;  
     252    if (uCount < core.sizeZ[0] * core.sizeT[0] * core.sizeC[0]) {  
     253      int planesPerMontage = (n * 2) / uCount; 
     254 
     255      while (planesPerMontage > 1) { 
     256        core.sizeY[0] /= 2; 
     257        planesPerMontage /= 2; 
     258        if (planesPerMontage > 1) { 
     259          core.sizeX[0] /= 2; 
     260          planesPerMontage /= 2; 
    289261        } 
    290         in.seek(in.getFilePointer() - 1); 
    291       } 
    292       else if (type == 0x75) { 
     262      } 
     263      if (core.sizeC[0] == 1) core.sizeC[0] = 2; 
     264      else core.sizeT[0] *= 2; 
     265    } 
     266    else if (uCount > core.sizeZ[0] * core.sizeT[0] * core.sizeC[0]) { 
     267      int planesPerMontage =  
     268        (int) ((core.sizeX[0] * core.sizeY[0] * 2) / (pixelBytes / uCount));  
     269      if (planesPerMontage % 2 != 0) planesPerMontage++;  
     270      if (planesPerMontage == 2) planesPerMontage += 2;  
     271      if (planesPerMontage == 0) planesPerMontage++; 
     272 
     273      int plane = core.sizeX[0] * core.sizeY[0];  
     274      while (uCount * core.sizeC[0] * (plane*2 / planesPerMontage) <  
     275        (pixelBytes - plane))  
     276      { 
    293277        uCount++; 
    294         in.skipBytes(250); 
    295       } 
    296       else in.skipBytes(250); 
    297       skipDataBlocks(n); 
    298     } 
    299     else in.seek(fp); 
     278      } 
     279 
     280      while (planesPerMontage > 1 &&  
     281        core.sizeX[0] * core.sizeY[0] * 2 * uCount > pixelBytes)  
     282      { 
     283        core.sizeY[0] /= 2; 
     284        planesPerMontage /= 2; 
     285        if (planesPerMontage > 1 &&  
     286          core.sizeX[0] * core.sizeY[0] * 2 * uCount > pixelBytes)  
     287        { 
     288          core.sizeX[0] /= 2; 
     289          planesPerMontage /= 2; 
     290        } 
     291        else planesPerMontage = 1;  
     292      } 
     293      core.sizeZ[0] = uCount;  
     294    } 
     295 
     296    // couldn't find the dimensions; these are reasonable guesses 
     297    if (core.sizeX[0] == 0) core.sizeX[0] = 512; 
     298    if (core.sizeY[0] == 0) core.sizeY[0] = 512; 
     299  
     300    core.imageCount[0] = core.sizeC[0] * core.sizeZ[0] * core.sizeT[0]; 
     301    
     302    core.currentOrder[0] = "XYZCT";  
     303    core.pixelType[0] = FormatTools.UINT16;  
     304    core.littleEndian[0] = true;  
    300305  } 
    301306 
Note: See TracChangeset for help on using the changeset viewer.