Changeset 2602


Ignore:
Timestamp:
04/12/07 09:23:19 (13 years ago)
Author:
melissa
Message:

Fixed EOFException when reading QuickTime mjpb files.

File:
1 edited

Legend:

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

    r2601 r2602  
    3131import loci.formats.*; 
    3232import loci.formats.codec.ByteVector; 
    33  
    34 // TODO : move decompression logic to loci.formats.codec 
    3533 
    3634/** 
     
    247245  // -- FormatReader API methods -- 
    248246 
    249   /* @see loci.formats.IFormatReader#isThisType(byte[]) */ 
     247  /* @see loci.formats.IFormatReader#isThisType(byte[]) */  
    250248  public boolean isThisType(byte[] block) { 
    251249    return false; 
     
    258256  } 
    259257 
    260   /* @see loci.formats.IFormatReader#openBytes(int) */ 
     258  /* @see loci.formats.IFormatReader#openBytes(int) */  
    261259  public byte[] openBytes(int no) throws FormatException, IOException { 
    262260    if (no < 0 || no >= getImageCount()) { 
     
    334332          for (int j=0; j<core.sizeY[0]; j++) { 
    335333            for (int k=0; k<b; k++) { 
    336               int bndx = j * core.sizeX[0] * b + (core.sizeX[0] - i) + b; 
    337               int tndx = i * core.sizeY[0] * b + j + b; 
    338               bytes[bndx] = tmp[tndx]; 
     334              bytes[j*core.sizeX[0]*b + (core.sizeX[0] - i) + b] =  
     335                tmp[i*core.sizeY[0]*b + j + b]; 
    339336            } 
    340337          } 
     
    345342          for (int j=0; j<core.sizeX[0]; j++) { 
    346343            for (int k=0; k<core.sizeY[0]; k++) { 
    347               int q = i * core.sizeX[0] * core.sizeY[0]; 
    348               int bndx = k * core.sizeX[0] + q + (core.sizeX[0] - j - 1); 
    349               int tndx = j * core.sizeY[0] + k + q; 
    350               bytes[bndx] = tmp[tndx]; 
     344              bytes[k*core.sizeX[0] +i*core.sizeX[0]*core.sizeY[0] +  
     345               (core.sizeX[0] - j - 1)] = tmp[j*core.sizeY[0] + k +  
     346               i*core.sizeX[0]*core.sizeY[0]]; 
    351347            } 
    352348          } 
     
    363359    pad = (4 - pad) % 4; 
    364360 
    365     int size = core.sizeX[0] * core.sizeY[0]; 
    366     if (size * (bitsPerPixel / 8) == prevPixels.length) pad = 0; 
     361    if (core.sizeX[0]*core.sizeY[0] * (bitsPerPixel / 8) == prevPixels.length) { 
     362      pad = 0; 
     363    } 
    367364 
    368365    if (pad > 0 && !code.equals("rpza")) { 
    369       bytes = new byte[prevPixels.length - core.sizeY[0] * pad]; 
     366      bytes = new byte[prevPixels.length - core.sizeY[0]*pad]; 
    370367 
    371368      for (int row=0; row<core.sizeY[0]; row++) { 
    372         System.arraycopy(prevPixels, row * (core.sizeY[0] + pad), bytes, 
    373           row * core.sizeX[0], core.sizeX[0]); 
     369        System.arraycopy(prevPixels, row*(core.sizeY[0]+pad), bytes, 
     370          row*core.sizeX[0], core.sizeX[0]); 
    374371      } 
    375372    } 
     
    385382 
    386383        for (int j=0; j<cut; j++) { 
    387           int ndx = (j + core.sizeY[0] - cut) * core.sizeX[0] + i; 
    388           redColumn[j] = prevPixels[ndx]; 
    389           greenColumn[j] = prevPixels[ndx + size]; 
    390           blueColumn[j] = prevPixels[ndx + 2 * size]; 
     384          redColumn[j] = prevPixels[(j+core.sizeY[0]-cut)*core.sizeX[0] + i]; 
     385          greenColumn[j] = prevPixels[(j+core.sizeY[0]-cut)*core.sizeX[0] + i +  
     386            core.sizeX[0]*core.sizeY[0]]; 
     387          blueColumn[j] = prevPixels[(j+core.sizeY[0]-cut)*core.sizeX[0] + i +  
     388            2*core.sizeX[0]*core.sizeY[0]]; 
    391389        } 
    392390 
    393391        for (int j=cut; j<core.sizeY[0]; j++) { 
    394           int ndx = j * core.sizeX[0] + i; 
    395           redColumn[j] = prevPixels[ndx]; 
    396           greenColumn[j] = prevPixels[ndx + size]; 
    397           blueColumn[j] = prevPixels[ndx + 2 * size]; 
     392          redColumn[j] = prevPixels[j*core.sizeX[0] + i]; 
     393          greenColumn[j] =  
     394            prevPixels[j*core.sizeX[0] + i + core.sizeX[0]*core.sizeY[0]]; 
     395          blueColumn[j] =  
     396            prevPixels[j*core.sizeX[0] + i + 2*core.sizeX[0]*core.sizeY[0]]; 
    398397        } 
    399398 
     
    401400 
    402401        for (int j=0; j<core.sizeY[0]; j++) { 
    403           int ndx = j * core.sizeX[0] + i; 
    404           bytes[ndx] = redColumn[j]; 
    405           bytes[ndx + size] = greenColumn[j]; 
    406           bytes[ndx + 2 * size] = blueColumn[j]; 
     402          bytes[j*core.sizeX[0] + i] = redColumn[j]; 
     403          bytes[j*core.sizeX[0] + i + core.sizeX[0]*core.sizeY[0]] =  
     404            greenColumn[j]; 
     405          bytes[j*core.sizeX[0] + i + 2*core.sizeX[0]*core.sizeY[0]] =  
     406            blueColumn[j]; 
    407407        } 
    408408      } 
     
    411411    if (flip) { 
    412412      int t = core.sizeX[0]; 
    413       core.sizeX[0] = core.sizeY[0]; 
     413      core.sizeX[0] = core.sizeY[0];  
    414414      core.sizeY[0] = t; 
    415415    } 
     
    426426      byte[][] data = new byte[3][bytes.length / 4]; 
    427427      for (int i=0; i<data[0].length; i++) { 
    428         data[0][i] = bytes[4 * i + 1]; 
    429         data[1][i] = bytes[4 * i + 2]; 
    430         data[2][i] = bytes[4 * i + 3]; 
     428        data[0][i] = bytes[4*i + 1]; 
     429        data[1][i] = bytes[4*i + 2]; 
     430        data[2][i] = bytes[4*i + 3]; 
    431431      } 
    432432 
     
    442442  } 
    443443 
    444   /* @See loci.formats.IFormatReader#openImage(int) */ 
     444  /* @See loci.formats.IFormatReader#openImage(int) */  
    445445  public BufferedImage openImage(int no) throws FormatException, IOException { 
    446446    if (no < 0 || no >= getImageCount()) { 
     
    512512  } 
    513513 
    514   /* @see loci.formats.IFormatReader#close() */ 
     514  /* @see loci.formats.IFormatReader#close() */  
    515515  public void close() throws FormatException, IOException { 
    516     super.close(); 
     516    if (in != null) in.close(); 
     517    in = null; 
     518    currentId = null; 
    517519    prevPixels = null; 
    518520  } 
     
    527529    offsets = new Vector(); 
    528530    chunkSizes = new Vector(); 
    529     status("Parsing tags"); 
     531    status("Parsing tags");  
    530532    parse(0, 0, in.length()); 
    531533    core.imageCount[0] = offsets.size(); 
     
    554556      core.sizeY[0] = tmp; 
    555557    } 
    556  
     558     
     559    core.rgb[0] = bitsPerPixel < 40; 
    557560    core.sizeZ[0] = 1; 
    558     core.sizeC[0] = bitsPerPixel < 40 ? 3 : 1; 
     561    core.sizeC[0] = core.rgb[0] ? 3 : 1; 
    559562    core.sizeT[0] = core.imageCount[0]; 
    560563    core.currentOrder[0] = "XYCZT"; 
    561     core.rgb[0] = bitsPerPixel < 40; 
     564    core.littleEndian[0] = false; 
    562565    core.interleaved[0] = true; 
    563     core.littleEndian[0] = false; 
    564566 
    565567    // The metadata store we're working with. 
     
    574576      new Integer(core.pixelType[0]), 
    575577      new Boolean(!core.littleEndian[0]), 
    576       core.currentOrder[0], 
     578      core.currentOrder[0],  
    577579      null, 
    578580      null); 
     
    642644 
    643645      // read through the file looking for occurences of the codec string 
    644       numImages = 0; 
     646      core.imageCount[0] = 0; 
    645647      String codecString = new String(pixels, 4, 4); 
    646648      if (codecString.equals("mjpg")) codec = "mjpb"; 
     
    663665          if (canAdd) { 
    664666            offsets.add(new Integer(i - 4)); 
    665             numImages++; 
     667            core.imageCount[0]++; 
    666668            canAdd = false; 
    667669          } 
     
    679681 
    680682  /** Parse all of the atoms in the file. */ 
    681   public void parse(int depth, long offset, long length) 
    682     throws FormatException, IOException 
     683  public void parse(int depth, long offset, long length)  
     684    throws FormatException, IOException  
    683685  { 
    684686    while (offset < length) { 
     
    949951            for (int y=0; y<4; y++) { 
    950952              for (int x=0; x<4; x++) { 
    951                 int ondx = (rowPtr + y) * core.sizeX[0] + pixelPtr + x; 
    952                 if (ondx < out.length) out[ondx] = colorA; 
     953                if ((rowPtr + y)*core.sizeX[0] + pixelPtr + x < out.length) { 
     954                  out[(rowPtr + y)*core.sizeX[0] + pixelPtr + x] = colorA; 
     955                } 
    953956              } 
    954957            } 
     
    10021005              for (int x=0; x<4; x++) { 
    10031006                int idx = (ndx >> (2 * (3 - x))) & 0x03; 
    1004                 int ondx = (rowPtr + y) * core.sizeX[0] + pixelPtr + x; 
    1005                 if (ondx < out.length) out[ondx] = colors[idx]; 
     1007                if ((rowPtr + y)*core.sizeX[0] + pixelPtr + x < out.length) { 
     1008                  out[(rowPtr + y)*core.sizeX[0] + pixelPtr + x] = colors[idx]; 
     1009                } 
    10061010              } 
    10071011            } 
     
    10261030                pt += 2; 
    10271031              } 
    1028               int ondx = (rowPtr + y) * core.sizeX[0] + pixelPtr + x; 
    1029               if (ondx < out.length) out[ondx] = colorA; 
     1032              if ((rowPtr + y)*core.sizeX[0] + pixelPtr + x < out.length) { 
     1033                out[(rowPtr + y)*core.sizeX[0] + pixelPtr + x] = colorA; 
     1034              } 
    10301035            } 
    10311036          } 
     
    10501055      rtn[i] = (byte) ((color >> 10) & 0x1f); 
    10511056      rtn[i + out.length] = (byte) ((color >> 5) & 0x1f); 
    1052       rtn[i + 2 * out.length] = (byte) (color & 0x1f); 
     1057      rtn[i + 2*out.length] = (byte) (color & 0x1f); 
    10531058    } 
    10541059    return rtn; 
     
    10561061 
    10571062  /** Uncompresses a MJPEG-B compressed image plane. */ 
    1058   public BufferedImage mjpbUncompress(byte[] input) 
    1059     throws FormatException, IOException 
    1060   { 
     1063  public BufferedImage mjpbUncompress(byte[] input) throws FormatException { 
    10611064    byte[] raw = null; 
    10621065    byte[] raw2 = null; 
    1063  
    1064     RandomAccessStream stream = new RandomAccessStream(input); 
    1065     stream.skipBytes(16); 
     1066    int pt = 16; // pointer into the compressed data 
    10661067 
    10671068    // official documentation at 
     
    10911092    // contains some interesting notes on why Apple chose to define this codec 
    10921093 
    1093     stream.skipBytes(4); 
    1094     if (stream.getFilePointer() >= stream.length()) stream.seek(0); 
    1095  
    1096     boolean hasID = stream.readChar() == 'm' && stream.readChar() == 'j' && 
    1097       stream.readChar() == 'p' && stream.readChar() == 'g'; 
    1098     stream.seek(stream.getFilePointer() - 20); 
    1099     if (!hasID) { 
    1100       hasID = stream.readChar() == 'm' && stream.readChar() == 'j' && 
    1101         stream.readChar() == 'p' && stream.readChar() == 'g'; 
    1102     } 
    1103     stream.skipBytes(12); 
    1104     stream.order(core.littleEndian[0]); 
     1094    pt += 4; 
     1095    if (pt >= input.length) pt = 0; 
    11051096 
    11061097    // most MJPEG-B planes don't have this identifier 
    1107     if (hasID) { 
     1098    if (!(input[pt] != 'm' || input[pt+1] != 'j' || input[pt+2] != 'p' || 
     1099      input[pt+3] != 'g') || !(input[pt-16] != 'm' || input[pt-15] != 'j' || 
     1100      input[pt-14] != 'p' || input[pt-13] != 'g')) 
     1101    { 
    11081102      int extra = 16; 
    1109       stream.seek(stream.getFilePointer() - 16); 
    1110       if (stream.readChar() == 'm') { 
    1111         stream.seek(4); 
     1103      if (input[pt-16] == 'm') { 
     1104        pt = 4; 
    11121105        extra = 0; 
    11131106      } 
    1114       else stream.skipBytes(16); 
    1115       stream.skipBytes(12); 
     1107      pt += 4; 
     1108 
     1109      // number of compressed bytes (minus padding) 
     1110      pt += 4; 
     1111 
     1112      // number of compressed bytes (including padding) 
     1113      pt += 4; 
    11161114 
    11171115      // offset to second field 
    1118       int offset = stream.readInt() + extra; 
     1116      int offset =  
     1117        DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]) + extra; 
     1118      pt += 4; 
    11191119 
    11201120      // offset to quantization table 
    1121       int quantOffset = stream.readInt() + extra; 
     1121      int quantOffset =  
     1122        DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]) + extra; 
     1123      pt += 4; 
    11221124 
    11231125      // offset to Huffman table 
    1124       int huffmanOffset = stream.readInt() + extra; 
     1126      int huffmanOffset =  
     1127        DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]) + extra; 
     1128      pt += 4; 
    11251129 
    11261130      // offset to start of frame 
    1127       int sof = stream.readInt() + extra; 
     1131      int sof = DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]) + extra; 
     1132      pt += 4; 
    11281133 
    11291134      // offset to start of scan 
    1130       int sos = stream.readInt() + extra; 
     1135      int sos = DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]) + extra; 
     1136      pt += 4; 
    11311137 
    11321138      // offset to start of data 
    1133       int sod = stream.readInt() + extra; 
     1139      int sod = DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]) + extra; 
     1140      pt += 4; 
    11341141 
    11351142      // skip over the quantization table, if it exists 
    11361143      if (quantOffset != 0) { 
    1137         stream.seek(quantOffset); 
    1138         int length = stream.readShort(); 
    1139         stream.skipBytes(length - 2); 
     1144        pt = quantOffset; 
     1145        int length = DataTools.bytesToInt(input, pt, 2, core.littleEndian[0]); 
     1146        pt += length; 
    11401147      } 
    11411148 
    11421149      // skip over the Huffman table, if it exists 
    11431150      if (huffmanOffset != 0) { 
    1144         stream.seek(huffmanOffset); 
    1145         int length = stream.readShort(); 
    1146         stream.skipBytes(length - 2); 
     1151        pt = huffmanOffset; 
     1152        int length = DataTools.bytesToInt(input, pt, 2, core.littleEndian[0]); 
     1153        pt += length; 
    11471154      } 
    11481155 
    11491156      // skip to the frame header 
    1150       stream.seek(sof + 7); 
     1157      pt = sof; 
     1158 
     1159      // read sof header 
     1160      // we can skip over the first 7 bytes (length, bps, height, width) 
     1161      pt += 7; 
    11511162 
    11521163      // number of channels 
    1153       int channels = stream.read(); 
     1164      int channels = DataTools.bytesToInt(input, pt, 1, core.littleEndian[0]); 
     1165      pt++; 
    11541166 
    11551167      int[] sampling = new int[channels]; 
    11561168      for (int i=0; i<channels; i++) { 
    1157         stream.read(); 
    1158         sampling[i] = stream.read(); 
     1169        pt++; 
     1170        sampling[i] = DataTools.bytesToInt(input, pt, 1, core.littleEndian[0]); 
     1171        pt += 2; 
    11591172      } 
    11601173 
    11611174      // skip to scan header 
    1162       stream.seek(sos + 3); 
    1163  
     1175      pt = sos; 
     1176 
     1177      // we can skip over the first 3 bytes (length, number of channels) 
     1178      pt += 3; 
    11641179      int[] tables = new int[channels]; 
    11651180      for (int i=0; i<channels; i++) { 
    1166         stream.read(); 
    1167         tables[i] = stream.read(); 
    1168       } 
     1181        pt++; 
     1182        tables[i] = DataTools.bytesToInt(input, pt, 1, core.littleEndian[0]); 
     1183        pt++; 
     1184      } 
     1185      pt += 3; 
    11691186 
    11701187      // now we can finally read this field's data 
    1171       stream.seek(sod + 3); 
    1172  
    1173       int numBytes = offset - stream.getFilePointer(); 
    1174       if (offset == 0) numBytes = input.length - stream.getFilePointer(); 
     1188      pt = sod; 
     1189 
     1190      int numBytes = offset - pt; 
     1191      if (offset == 0) numBytes = input.length - pt; 
    11751192      raw = new byte[numBytes]; 
    1176       System.arraycopy(input, stream.getFilePointer(), raw, 0, raw.length); 
     1193      System.arraycopy(input, pt, raw, 0, raw.length); 
    11771194 
    11781195      // get the second field 
     
    11861203 
    11871204      if (offset != 0) { 
    1188         stream.seek(offset); 
    1189         stream.skipBytes(36); 
    1190  
    1191         stream.skipBytes(stream.readInt() - 36); 
    1192  
    1193         numBytes = input.length - stream.getFilePointer(); 
     1205        pt = offset; 
     1206 
     1207        pt += 4; // reserved = 0 
     1208        pt += 4; // 'mjpg' tag 
     1209        pt += 4; // field size 
     1210        pt += 4; // padded field size 
     1211        pt += 4; // offset to next field = 0 
     1212        pt += 4; // quantization table offset 
     1213        pt += 4; // Huffman table offset 
     1214        pt += 4; // sof offset 
     1215        pt += 4; // sos offset 
     1216 
     1217        pt += DataTools.bytesToInt(input, pt, 4, core.littleEndian[0]); 
     1218        pt -= 36; // HACK 
     1219 
     1220        numBytes = input.length - pt; 
    11941221        raw2 = new byte[numBytes]; 
    1195         System.arraycopy(input, stream.getFilePointer(), raw2, 0, raw2.length); 
     1222        System.arraycopy(input, pt, raw2, 0, raw2.length); 
    11961223      } 
    11971224    } 
     
    12771304    v.add((byte) (length & 0xff)); 
    12781305 
    1279     int fieldHeight = core.sizeY[0]; 
     1306    int fieldHeight = core.sizeY[0];  
    12801307    if (interlaced) fieldHeight /= 2; 
    12811308    if (core.sizeY[0] % 2 == 1) fieldHeight++; 
     
    14661493 
    14671494      if (canUsePrevious) { 
    1468         for (int i=start+numLines; i<core.sizeY[0]; i++) { 
     1495        for (int i=(start+numLines); i<core.sizeY[0]; i++) { 
    14691496          int offset = i * core.sizeX[0] * ebpp; 
    14701497          System.arraycopy(prevPixels, offset, output, offset, 
     
    14881515      if (canUsePrevious) { 
    14891516        try { 
    1490           System.arraycopy(prevPixels, rowPointer, 
    1491             output, rowPointer, (skip - 1) * ebpp); 
     1517          System.arraycopy(prevPixels, rowPointer, output, rowPointer, 
     1518            (skip-1) * ebpp); 
    14921519        } 
    14931520        catch (ArrayIndexOutOfBoundsException e) { } 
    14941521      } 
    14951522 
    1496       off = rowPointer + ((skip - 1) * ebpp); 
     1523      off = rowPointer + ((skip-1) * ebpp); 
    14971524      pt++; 
    14981525      while (true) { 
     
    15051532          if (canUsePrevious) { 
    15061533            try { 
    1507               System.arraycopy(prevPixels, off, 
    1508                 output, off, (skip-1) * ebpp); 
     1534              System.arraycopy(prevPixels, off, output, off, 
     1535                (skip-1) * ebpp); 
    15091536            } 
    15101537            catch (ArrayIndexOutOfBoundsException e) { } 
     
    15261553        else if (rle < -1) { 
    15271554          // unpack next pixel and copy it to output -(rle) times 
    1528           for (int j=0; j<-rle; j++) { 
     1555          for (int j=0; j<(-1*rle); j++) { 
    15291556            if (off < output.length) { 
    15301557              System.arraycopy(input, pt, output, off, ebpp); 
    15311558              off += ebpp; 
    15321559            } 
    1533             else j = -rle; 
     1560            else j = (-1*rle); 
    15341561          } 
    15351562          pt += ebpp; 
     
    15371564        else { 
    15381565          // copy (rle) pixels to output 
    1539           System.arraycopy(input, pt, output, off, rle * ebpp); 
    1540           pt += rle * ebpp; 
    1541           off += rle * ebpp; 
     1566          System.arraycopy(input, pt, output, off, rle*ebpp); 
     1567          pt += rle*ebpp; 
     1568          off += rle*ebpp; 
    15421569        } 
    15431570      } 
Note: See TracChangeset for help on using the changeset viewer.