Changeset 2795


Ignore:
Timestamp:
05/17/07 11:33:41 (13 years ago)
Author:
melissa
Message:

Finished rpza support.

File:
1 edited

Legend:

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

    r2701 r2795  
    193193    in.read(pixs); 
    194194 
    195     canUsePrevious = (prevPixels != null) && (prevPlane == no - 1); 
     195    canUsePrevious = (prevPixels != null) && (prevPlane == no - 1) &&  
     196      !code.equals(altCodec); 
    196197 
    197198    if (code.equals("jpeg") || code.equals("mjpb")) { 
     
    200201    } 
    201202 
    202     byte[] bytes = uncompress(pixs, code); 
     203    byte[] bytes = null; 
     204    if (!code.equals("rpza")) bytes = uncompress(pixs, code); 
     205    else { 
     206      bytes = rpzaUncompress(pixs, canUsePrevious ? prevPixels : null);  
     207     
     208      for (int i=0; i<bytes.length; i++) { 
     209        bytes[i] = (byte) (255 - bytes[i]); 
     210      } 
     211      prevPlane = no; 
     212      return bytes;  
     213    }  
     214    
    203215    // on rare occassions, we need to trim the data 
    204216    if (canUsePrevious && (prevPixels.length < bytes.length)) { 
     
    208220    } 
    209221 
    210     /* 
    211     if (flip) { 
    212       // we need to flip the X and Y axes before displaying 
    213  
    214       byte[] tmp = bytes; 
    215       bytes = new byte[tmp.length]; 
    216  
    217       int t = core.sizeX[0]; 
    218       core.sizeX[0] = core.sizeY[0]; 
    219       core.sizeY[0] = t; 
    220  
    221       int b = bytes.length / (core.sizeX[0] * core.sizeY[0]); 
    222  
    223       if (b % 3 != 0) { 
    224         for (int i=0; i<core.sizeX[0]; i++) { 
    225           for (int j=0; j<core.sizeY[0]; j++) { 
    226             for (int k=0; k<b; k++) { 
    227               int bndx = j * core.sizeX[0] * b + (core.sizeX[0] - i) + b; 
    228               int tndx = i * core.sizeY[0] * b + j + b; 
    229               bytes[bndx] = tmp[tndx]; 
    230             } 
    231           } 
    232         } 
    233       } 
    234       else { 
    235         for (int i=0; i<3; i++) { 
    236           for (int j=0; j<core.sizeX[0]; j++) { 
    237             for (int k=0; k<core.sizeY[0]; k++) { 
    238               int q = i * core.sizeX[0] * core.sizeY[0]; 
    239               int bndx = k * core.sizeX[0] + q + (core.sizeX[0] - j - 1); 
    240               int tndx = j * core.sizeY[0] + k + q; 
    241               bytes[bndx] = tmp[tndx]; 
    242             } 
    243           } 
    244         } 
    245       } 
    246     } 
    247     */ 
    248  
    249222    prevPixels = bytes; 
    250223    prevPlane = no; 
     
    258231    if (size * (bitsPerPixel / 8) == prevPixels.length) pad = 0; 
    259232 
    260     if (pad > 0 && !code.equals("rpza")) { 
     233    if (pad > 0) { 
    261234      bytes = new byte[prevPixels.length - core.sizeY[0]*pad]; 
    262235 
     
    266239      } 
    267240    } 
    268     else if (code.equals("rpza")) { 
    269       bytes = new byte[prevPixels.length]; 
    270  
    271       int cut = 0; 
    272  
    273       for (int i=core.sizeX[0]-1; i>=0; i--) { 
    274         byte[] redColumn = new byte[core.sizeY[0]]; 
    275         byte[] greenColumn = new byte[core.sizeY[0]]; 
    276         byte[] blueColumn = new byte[core.sizeY[0]]; 
    277  
    278         for (int j=0; j<cut; j++) { 
    279           int ndx = (j + core.sizeY[0] - cut) * core.sizeX[0] + i; 
    280           redColumn[j] = prevPixels[ndx]; 
    281           greenColumn[j] = prevPixels[ndx + size]; 
    282           blueColumn[j] = prevPixels[ndx + 2 * size]; 
    283         } 
    284  
    285         for (int j=cut; j<core.sizeY[0]; j++) { 
    286           int ndx = j * core.sizeX[0] + i; 
    287           redColumn[j] = prevPixels[ndx]; 
    288           greenColumn[j] = prevPixels[ndx + size]; 
    289           blueColumn[j] = prevPixels[ndx + 2 * size]; 
    290         } 
    291  
    292         if (i > core.sizeX[0] - 1 - core.sizeY[0]) cut++; 
    293  
    294         for (int j=0; j<core.sizeY[0]; j++) { 
    295           int ndx = j * core.sizeX[0] + i; 
    296           bytes[ndx] = redColumn[j]; 
    297           bytes[ndx + size] = greenColumn[j]; 
    298           bytes[ndx + 2 * size] = blueColumn[j]; 
    299         } 
    300       } 
    301     } 
    302  
    303     /* 
    304     if (flip) { 
    305       int t = core.sizeX[0]; 
    306       core.sizeX[0] = core.sizeY[0]; 
    307       core.sizeY[0] = t; 
    308     } 
    309     */ 
    310241 
    311242    if (bitsPerPixel == 40 || bitsPerPixel == 8) { 
     
    819750    if (code.equals("raw ")) return pixs; 
    820751    else if (code.equals("rle ")) return rleUncompress(pixs); 
    821     else if (code.equals("rpza")) return rpzaUncompress(pixs); 
     752    else if (code.equals("rpza")) return rpzaUncompress(pixs, null); 
    822753    else { 
    823754      throw new FormatException("Sorry, " + codec + " codec is not supported"); 
     
    825756  } 
    826757 
    827   /** Uncompresses an RPZA compressed image plane. */ 
    828   private byte[] rpzaUncompress(byte[] input) throws FormatException { 
    829     bitsPerPixel = 8; 
    830     int[] out = new int[core.sizeX[0] * core.sizeY[0]]; 
    831  
    832     int pt = 1; // pointer into the array of compressed bytes 
    833  
    834     // get the chunk size 
    835     int size = DataTools.bytesToInt(input, pt, 3, false); 
    836     pt += 3; 
    837  
    838     int totalBlocks = ((core.sizeX[0] + 3) / 4) * ((core.sizeY[0] + 3) / 4); 
    839     int currentBlock = 0; 
    840     int blocksPerRow = ((core.sizeX[0] + 3) / 4); 
    841     int rowPtr = 0; 
    842     int pixelPtr = 0; 
    843     int colorA = 0, colorB = 0; 
    844  
    845     // process chunk data 
    846  
    847     while (pt + 4 < input.length && currentBlock < totalBlocks) { 
    848       byte opcode = input[pt]; 
    849       pt++; 
    850  
    851       int nBlocks = (opcode & 0x1f) + 1; 
     758  /**  
     759   * Uncompresses an RPZA compressed image plane. Adapted from the ffmpeg 
     760   * codec - see http://ffmpeg.mplayerhq.hu 
     761   */ 
     762  private byte[] rpzaUncompress(byte[] input, byte[] rtn)  
     763    throws FormatException  
     764  { 
     765    int width = core.sizeX[0]; 
     766    int stride = core.sizeX[0];  
     767    int rowInc = stride - 4; 
     768    int streamPtr = 0; 
     769    short opcode; 
     770    int nBlocks; 
     771    int colorA = 0, colorB; 
     772    int[] color4 = new int[4]; 
     773    int index, idx; 
     774    int ta, tb; 
     775    int rowPtr = 0, pixelPtr = 0, blockPtr = 0; 
     776    int pixelX, pixelY; 
     777    int totalBlocks; 
     778 
     779    int[] pixels = new int[width * core.sizeY[0]]; 
     780    if (rtn == null) rtn = new byte[width * core.sizeY[0] * 3]; 
     781 
     782    while (input[streamPtr] != (byte) 0xe1) streamPtr++; 
     783    streamPtr += 4; 
     784 
     785    totalBlocks = ((width + 3) / 4) * ((core.sizeY[0] + 3) / 4); 
     786   
     787    while (streamPtr < input.length) { 
     788      opcode = input[streamPtr++]; 
     789      nBlocks = (opcode & 0x1f) + 1; 
    852790 
    853791      if ((opcode & 0x80) == 0) { 
    854         colorA = (opcode << 8) | input[pt]; 
    855         pt++; 
     792        if (streamPtr >= input.length) break;  
     793        colorA = (opcode << 8) | input[streamPtr++]; 
    856794        opcode = 0; 
    857  
    858         if ((input[pt] & 0x80) != 0) { 
     795        if (streamPtr >= input.length) break;  
     796        if ((input[streamPtr] & 0x80) != 0) { 
    859797          opcode = 0x20; 
    860798          nBlocks = 1; 
    861799        } 
    862800      } 
    863  
     801    
    864802      switch (opcode & 0xe0) { 
    865803        case 0x80: 
    866           // skip blocks 
    867           while (nBlocks > 0) { 
    868             currentBlock++; 
    869             nBlocks--; 
     804          while (nBlocks-- > 0) { 
    870805            pixelPtr += 4; 
    871             if (pixelPtr >= core.sizeX[0] - 1) { 
    872               rowPtr += 4; 
     806            if (pixelPtr >= width) { 
    873807              pixelPtr = 0; 
    874             } 
     808              rowPtr += stride * 4; 
     809            } 
     810            totalBlocks--; 
    875811          } 
    876812          break; 
    877813        case 0xa0: 
    878           // fill blocks with one color 
    879           colorA = DataTools.bytesToInt(input, pt, 2, false); 
    880           pt += 2; 
    881           while (nBlocks > 0) { 
    882             // fill the whole block with colorA 
    883  
    884             for (int y=0; y<4; y++) { 
    885               for (int x=0; x<4; x++) { 
    886                 if ((rowPtr + y)*core.sizeX[0] + pixelPtr + x < out.length) { 
    887                   out[(rowPtr + y)*core.sizeX[0] + pixelPtr + x] = colorA; 
    888                 } 
     814          colorA = DataTools.bytesToInt(input, streamPtr, 2, false); 
     815          streamPtr += 2; 
     816          while (nBlocks-- > 0) { 
     817            blockPtr = rowPtr + pixelPtr; 
     818            for (pixelY=0; pixelY < 4; pixelY++) { 
     819              for (pixelX=0; pixelX < 4; pixelX++) { 
     820                if (blockPtr >= pixels.length) break;  
     821                pixels[blockPtr] = colorA; 
     822               
     823                short s = (short) (pixels[blockPtr] & 0x7fff); 
     824 
     825                rtn[blockPtr] = (byte) (255 - ((s & 0x7c00) >> 10));  
     826                rtn[blockPtr + pixels.length] =  
     827                  (byte) (255 - ((s & 0x3e0) >> 5)); 
     828                rtn[blockPtr + 2*pixels.length] = (byte) (255 - (s & 0x1f)); 
     829 
     830                blockPtr++; 
    889831              } 
    890             } 
    891  
     832              blockPtr += rowInc;  
     833            } 
    892834            pixelPtr += 4; 
    893             if (pixelPtr >= core.sizeX[0] - 1) { 
    894               rowPtr += 4; 
     835            if (pixelPtr >= width) { 
    895836              pixelPtr = 0; 
    896             } 
    897             currentBlock++; 
    898             nBlocks--; 
     837              rowPtr += stride * 4; 
     838            } 
     839            totalBlocks--; 
    899840          } 
    900841          break; 
    901842        case 0xc0: 
    902           colorA = DataTools.bytesToInt(input, pt, 2, false); 
    903           pt += 2; 
    904           break; 
     843          colorA = DataTools.bytesToInt(input, streamPtr, 2, false); 
     844          streamPtr += 2; 
    905845        case 0x20: 
    906           // fill blocks with 4 colors 
    907           colorA = DataTools.bytesToInt(input, pt, 2, false); 
    908           colorB = DataTools.bytesToInt(input, pt, 2, false); 
    909           pt += 4; 
    910  
    911           // sort out the colors 
    912           int[] colors = new int[4]; 
    913           colors[0] = colorB; 
    914           colors[1] = 0; 
    915           colors[2] = 0; 
    916           colors[3] = colorA; 
    917  
    918           int ta = (colorA >> 10) & 0x1f; 
    919           int tb = (colorB >> 10) & 0x1f; 
    920           colors[1] |= ((11 * ta + 21 * tb) >> 5) << 10; 
    921           colors[2] |= ((21 * ta + 11 * tb) >> 5) << 10; 
     846          colorB = DataTools.bytesToInt(input, streamPtr, 2, false); 
     847          streamPtr += 2; 
     848 
     849          color4[0] = colorB; 
     850          color4[1] = 0; 
     851          color4[2] = 0; 
     852          color4[3] = colorA; 
     853 
     854          ta = (colorA >> 10) & 0x1f; 
     855          tb = (colorB >> 10) & 0x1f; 
     856          color4[1] |= ((11*ta + 21*tb) >> 5) << 10; 
     857          color4[2] |= ((21*ta + 11*tb) >> 5) << 10; 
    922858 
    923859          ta = (colorA >> 5) & 0x1f; 
    924860          tb = (colorB >> 5) & 0x1f; 
    925           colors[1] |= ((11 * ta + 21 * tb) >> 5) << 5; 
    926           colors[2] |= ((21 * ta + 11 * tb) >> 5) << 5; 
     861          color4[1] |= ((11*ta + 21*tb) >> 5) << 5; 
     862          color4[2] |= ((21*ta + 11*tb) >> 5) << 5; 
    927863 
    928864          ta = colorA & 0x1f; 
    929865          tb = colorB & 0x1f; 
    930           colors[1] |= ((11 * ta + 21 * tb) >> 5); 
    931           colors[2] |= ((21 * ta + 11 * tb) >> 5); 
    932  
    933           while (nBlocks > 0) { 
    934             for (int y=0; y<4; y++) { 
    935               if (pt >= input.length) break; 
    936               int ndx = input[pt]; 
    937               pt++; 
    938               for (int x=0; x<4; x++) { 
    939                 int idx = (ndx >> (2 * (3 - x))) & 0x03; 
    940                 if ((rowPtr + y)*core.sizeX[0] + pixelPtr + x < out.length) { 
    941                   out[(rowPtr + y)*core.sizeX[0] + pixelPtr + x] = colors[idx]; 
    942                 } 
     866          color4[1] |= ((11*ta + 21*tb) >> 5); 
     867          color4[2] |= ((21*ta + 11*tb) >> 5); 
     868 
     869          while (nBlocks-- > 0) { 
     870            blockPtr = rowPtr + pixelPtr; 
     871            for (pixelY=0; pixelY<4; pixelY++) { 
     872              if (streamPtr >= input.length) break;  
     873              index = input[streamPtr++]; 
     874              for (pixelX=0; pixelX<4; pixelX++) { 
     875                idx = (index >> (2*(3 - pixelX))) & 0x03; 
     876                if (blockPtr >= pixels.length) break;  
     877                pixels[blockPtr] = color4[idx]; 
     878                 
     879                short s = (short) (pixels[blockPtr] & 0x7fff); 
     880 
     881                rtn[blockPtr] = (byte) (255 - ((s & 0x7c00) >> 10));  
     882                rtn[blockPtr + pixels.length] =  
     883                  (byte) (255 - ((s & 0x3e0) >> 5)); 
     884                rtn[blockPtr + 2*pixels.length] = (byte) (255 - (s & 0x1f)); 
     885 
     886                blockPtr++; 
    943887              } 
    944             } 
    945  
     888              blockPtr += rowInc;  
     889            } 
    946890            pixelPtr += 4; 
    947             if (pixelPtr >= core.sizeX[0] - 1) { 
    948               rowPtr += 4; 
     891            if (pixelPtr >= width) { 
    949892              pixelPtr = 0; 
    950             } 
    951             currentBlock++; 
    952             nBlocks--; 
    953           } 
    954  
     893              rowPtr += stride * 4; 
     894            } 
     895            totalBlocks--; 
     896          } 
     897          break;  
     898        case 0x00: 
     899          blockPtr = rowPtr + pixelPtr; 
     900          for (pixelY=0; pixelY < 4; pixelY++) { 
     901            for (pixelX=0; pixelX < 4; pixelX++) { 
     902              if ((pixelY != 0) || (pixelX != 0)) { 
     903                colorA = DataTools.bytesToInt(input, streamPtr, 2, false); 
     904                streamPtr += 2; 
     905              } 
     906              if (blockPtr >= pixels.length) break;  
     907              pixels[blockPtr] = colorA; 
     908               
     909              short s = (short) (pixels[blockPtr] & 0x7fff); 
     910 
     911              rtn[blockPtr] = (byte) (255 - ((s & 0x7c00) >> 10));  
     912              rtn[blockPtr + pixels.length] = (byte) (255 - ((s & 0x3e0) >> 5)); 
     913              rtn[blockPtr + 2*pixels.length] = (byte) (255 - (s & 0x1f)); 
     914               
     915              blockPtr++; 
     916            } 
     917            blockPtr += rowInc;  
     918          } 
     919          pixelPtr += 4; 
     920          if (pixelPtr >= width) { 
     921            pixelPtr = 0; 
     922            rowPtr += stride * 4; 
     923          } 
     924          totalBlocks--; 
    955925          break; 
    956         case 0x00: 
    957           // fill block with 16 colors 
    958  
    959           for (int y=0; y<4; y++) { 
    960             for (int x=0; x<4; x++) { 
    961               if (y != 0 || x != 0) { 
    962                 colorA = DataTools.bytesToInt(input, pt, 2, false); 
    963                 pt += 2; 
    964               } 
    965               if ((rowPtr + y)*core.sizeX[0] + pixelPtr + x < out.length) { 
    966                 out[(rowPtr + y)*core.sizeX[0] + pixelPtr + x] = colorA; 
    967               } 
    968             } 
    969           } 
    970  
    971           pixelPtr += 4; 
    972           if (pixelPtr >= core.sizeX[0] - 1) { 
    973             rowPtr += 4; 
    974             pixelPtr = 0; 
    975           } 
    976  
    977           currentBlock++; 
    978           break; 
    979       } 
    980     } 
    981  
    982     // convert int array to byte array and return 
    983     // note that the colors need to be reversed 
    984  
    985     byte[] rtn = new byte[out.length * 3]; 
    986     for (int i=0; i<out.length; i++) { 
    987       int color = 65535 - out[i]; 
    988       rtn[i] = (byte) ((color >> 10) & 0x1f); 
    989       rtn[i + out.length] = (byte) ((color >> 5) & 0x1f); 
    990       rtn[i + 2*out.length] = (byte) (color & 0x1f); 
    991     } 
     926      } 
     927    } 
     928 
    992929    return rtn; 
    993930  } 
    994  
     931   
    995932  /** Uncompresses a MJPEG-B compressed image plane. */ 
    996933  private BufferedImage mjpbUncompress(byte[] input) throws FormatException { 
Note: See TracChangeset for help on using the changeset viewer.