Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * Copyright 1999-2101 Alibaba Group.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
    * You may obtain a copy of the License at
    *
    *      http://www.apache.org/licenses/LICENSE-2.0
    *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.alibaba.simpleimage.codec.jpeg;
  
  
  
  public class JPEGDecoder extends AbstractImageDecoder {
  
      private ImageInputStream     in;
  
      private HuffmanTable[]       dcHuffTables      = new HuffmanTable[4];
      private HuffmanTable[]       acHuffTables      = new HuffmanTable[4];
      private QuantizationTable[]  qTables           = new QuantizationTable[4];
  
      private FrameHeader          frameHeader;
      private ScanHeader           scanHeader;
      private int                  restartInterval;
      private ExtendImageHeader    extendImageHeader = new ExtendImageHeader();
  
      // Util class
      private ColorConvertor       colorConvertor;
  
      private InternalRawImage     rawImage;                                    //
  
      // Runtime var frame level
      private int[][]              singleMCUData     = new int[4][];            // used by baseline mode
      private int[]                singleBlockData   = new int[];
      private int[]                pixesBuffer       = null;
      private int                  x                 = 0, y = 0;                //
      private int[][][]            allMCUDatas;                                 // used by progressive mode
      private int                  MCUsPerRow;
      private int                  MCUsPerColumn;
      private int                  maxHSampleFactor  = 0;                       // Max Horizontal sampling factor of
      // components
      private int                  maxVSampleFactor  = 0;                       // Max Vertical sampling factor of
      // components
  
      // Runtime var scan level
      private int[]                blocksInMCU       = new int[10];
      private int                  blocksNumInMCU    = 0;
      private int[]                preDC;
      private int                  EOBRUN            = 0;
  
      private boolean              fastIDCTMode      = false;
      private boolean              supportICC        = false;
      private boolean              broken            = false;                   // indicate the image is broken or not
  
      public JPEGDecoder(ImageInputStream inboolean fastIDCTModeboolean supportICC){
          this. = in;
          this. = fastIDCTMode;
          this. = supportICC;
  
          super.addExtendHeaderReader(MarkerConstants.APP0, new JFIFHeaderReader());
          if (supportICC) {
             super.addExtendHeaderReader(MarkerConstants.APP2, new ICCProfileReader());
         }
         super.addExtendHeaderReader(MarkerConstants.APP14, new AdobeHeaderReader());
 
         if (fastIDCTMode) {
             // temporary unsupported
              = new FastInverseDCTCalculator();
         } else {
              = new SlowInverseDCTCalculator();
         }
     }
 
     public JPEGDecoder(ImageInputStream in){
         this(infalsefalse);
     }
 
     public ImageWrapper decode() throws IOException {
         int prefix = .read();
         int magic = .read();
 
         if ((prefix != 0xFF) || (magic != .)) {
             throw new IllegalArgumentException("Not JPEG file");
         }
 
         int marker = nextMarker();
 
         try {
             while (!isSOFnMarker(marker)) {
                 readTables(marker);
 
                 marker = nextMarker();
 
                 if (marker == -1) {
                     throw new IOException("Unexpected end of file");
                 }
             }
         } catch (JPEGMarkerException e) {
             // unknown marker detected
             throw new JPEGDecoderException("Decode JPEG fail");
         }
 
         marker = decodeFrame(marker);
 
         if (marker == -1 || marker == .) {
             if ( == null) {
                 throw new JPEGDecoderException("Decode JPEG fail");
             }
 
             if(marker == -1) {
                  = true;
             }
             
             return createImage();
         } else {
             throw new JPEGDecoderException("Decode JPEG fail");
         }
     }
 
     protected ImageWrapper createImage() {
         Raster dstRaster = null;
         ColorSpace cs = null;
 
         if (.isProgressiveMode()) {
             inverseDCT();
 
             writeFull();
         }
 
         if (.getColorspace() == .) {
             dstRaster = Raster.createInterleavedRaster(
                                                        new DataBufferByte(.getData(), .getData().length),
                                                        .getWidth(), .getHeight(),
                                                        .getWidth() * 1, 1, new int[] { 0 }, null);
 
             cs = getColorSpace();
         } else if (.getColorspace() == .) {
             dstRaster = Raster.createInterleavedRaster(
                                                        new DataBufferByte(.getData(), .getData().length),
                                                        .getWidth(), .getHeight(),
                                                        .getWidth() * 3, 3, new int[] { 0, 1, 2 }, null);
 
             cs = getColorSpace();
         } else if (.getColorspace() == .) {
             dstRaster = Raster.createInterleavedRaster(
                                                        new DataBufferByte(.getData(), .getData().length),
                                                        .getWidth(), .getHeight(),
                                                        .getWidth() * 4, 4, new int[] { 0, 1, 2, 3 }, null);
 
             cs = getColorSpace();
         } else {
             throw new JPEGDecoderException("Unknow colorspace");
         }
 
         ColorModel cm = new ComponentColorModel(csfalsetrue..);
 
         BufferedImage img = new BufferedImage(cm, (WritableRasterdstRastertruenull);
 
         ImageWrapper wi = new ImageWrapper(imggetQuality(), );
         wi.setImageFormat(.);
 
         for (Component c : .getComponents()) {
             wi.setHorizontalSamplingFactor(c.getIndex(), c.getH());
             wi.setVerticalSamplingFactor(c.getIndex(), c.getV());
         }
 
         return wi;
     }
 
     protected ColorSpace getColorSpace() {
         ColorSpace cs = null;
 
         if () {
             if (.isExistProfile()) {
                 ICC_Profile profile = null;
 
                 try {
                     synchronized (ICC_Profile.class) {
                         profile = ICC_Profile.getInstance(.getProfileData());
                     }
                 } catch (Exception ignore) {
                     profile = null;
                 }
 
                 if (profile != null) {
                     try {
                         cs = new ICC_ColorSpace(profile);
                     } catch (Exception ignore) {
                         cs = null;
                     }
                 }
             }
         }
 
         // use standard color space if create color space from ICC_Profile fail
         // or doesn't exists ICC_Profile
         if (cs == null) {
             .setExistProfile(false);
 
             if (.getColorspace() == .) {
                 cs = CMMColorSpace.getInstance(.);
             } else if (.getColorspace() == .) {
                 cs = ColorSpace.getInstance(.);
             } else {
                 cs = ColorSpace.getInstance(.);
             }
         }
 
         return cs;
     }
 
     protected int decodeFrame(int markerthrows IOException {
         readFrameHeader(marker);
 
         determinColorspace();
 
         marker = nextMarker();
 
         for (int scanNum = 0;;) {
             scanNum++;
 
             if (.isProgressiveMode()) {
                 marker = decodeProgressiveScan(marker);
             } else {
                 marker = decodeScan(marker);
             }
 
             if (marker == . && scanNum == 1) {
                 decodeDNL();
             }
 
             if (marker == . || marker == -1) {
                 return marker;
             }
         }
     }
 
     protected void calculateMCUs(int[] componentIndexesComponent[] components) {
          = 0;
 
         for (int i : componentIndexes) {
             int blocks = components[i].getH() * components[i].getV();
             while ((blocks--) > 0) {
                 [++] = i;
             }
         }
     }

    
Decode baseline and sequencal scan

Returns:
Throws:
java.io.IOException
 
     protected int decodeScan(int markerthrows IOException {
 
         try {
             while (marker != .) {
                 readTables(marker);
 
                 marker = nextMarker();
 
                 if (marker == -1) {
                     return marker;
                 }
             }
         } catch (JPEGMarkerException e) {
             // just ignore unknown marker
             return -1;
         }
 
         // Decode scan header
         int[] componentIndexes = readScanHeader();
         Component[] components = .getComponents();
 
         // Calculate MCU size
         calculateMCUs(componentIndexescomponents);
 
         try {
             int restartsLeft = ;
             .resetBuffer();
             resetDecoder();
             HuffmanTable curDCTable;
             HuffmanTable curACTable;
             QuantizationTable curQTable;
 
             for (int m = 0; m <  * m++) {
                 // If support restart interval
                 if ( > 0 && restartsLeft == 0) {
                     marker = nextMarker();
 
                     if (marker > . || marker < .) {
                         return marker;
                     }
 
                     .resetBuffer();
                     resetDecoder();
 
                     restartsLeft = ;
                 }
 
                 // Begin decode MCU
                 for (int c = 0, index = 0, ctr = 0; c < c++) {
                     index = [c];
 
                     if (c == 0) {
                         ctr = 0;
                     } else {
                         if (index == [c - 1]) {
                             ctr++;
                         } else {
                             ctr = 0;
                         }
                     }
 
                     // Begin decode block
                     curACTable = components[index].;
                     curDCTable = components[index].;
                     curQTable = components[index].;
 
                     // init 0
                     for (int z = 0; z < z++) {
                         [z] = 0;
                     }
 
                     int s = 0, r = 0;
 
                     // Decode DC
                     s = curDCTable.decode();
                     if (s > 0) {
                         r = (int.readBits(s);
                         s = curDCTable.extend(rs);
                     }
 
                     [index] = s = [index] + s;
                     [0] = s;
 
                     // Decode AC
                     for (int k = 1;;) {
                         s = curACTable.decode();
 
                         r = s >> 4;
                         s = s & 15;
 
                         if (s == 0) {
                             if (r == 15) {
                                 k += 16;
                                 continue;
                             } else {
                                 break;
                             }
                         } else {
                             k += r;
 
                             r = (int.readBits(s);
                             s = curACTable.extend(rs);
 
                             // Output coefficient in natural (dezigzagged) order
                             [.[k]] = s;
 
                             if (k >= 63) {
                                 break;
                             } else {
                                 k++;
                             }
                         }
                     }
                     // End decode block
 
                     if () {
                         throw new UnsupportedOperationException("Not implemented yet");
                     } else {
                         .calculate(, 0, curQTable.getQ(), [index],
                                                        ctr * components[index].getHorizonDCTScaledSize(),
                                                        components[index].getVerticaDCTScaledSize());
 
                     }
                 }
                 // End decode MCU
 
                 writeMCU();
 
                 restartsLeft--;
             }
 
             marker = nextMarker();
         } catch (JPEGMarkerException e) { // Unexpected marker occur
             marker = e.getMarker();
         } catch (EOFException e) {
             marker = -1;
         } catch (ArrayIndexOutOfBoundsException e) {
             // just ignore huffman decode error
             marker = -1;
              = true;
         }
 
         return marker;
     }

    
Decode progressive scan

Returns:
Throws:
java.io.IOException
 
     protected int decodeProgressiveScan(int markerthrows IOException {
 
         try {
             while (marker != .) {
                 readTables(marker);
 
                 marker = nextMarker();
 
                 if (marker == -1) {
                     return marker;
                 }
             }
         } catch (JPEGMarkerException e) {
             // just ignore unknown marker
             return -1;
         }
 
         int[] componentIndexes = readScanHeader();
 
         validateProgressiveParam();
 
         Component[] components = .getComponents();
 
         // Calculate MCU size
         calculateMCUs(componentIndexescomponents);
 
         // AC scans can only contain one component, DC scans may contain more
         // than one component
         try {
             int restartsLeft = ;
             .resetBuffer();
             resetDecoder();
             HuffmanTable curDCTable;
             HuffmanTable curACTable;
 
             /*
              * Note:If the compressed image data is non-interleaved, the MCU is defined to be one data unit
              */
             // interleaved
             if (.getSs() == 0) {
                 for (int m = 0; m <  * m++) {
                     // If support restart interval
                     if ( > 0 && restartsLeft == 0) {
                         marker = nextMarker();
 
                         if (marker > . || marker < .) {
                             return marker;
                         }
 
                         .resetBuffer();
 
                         resetDecoder();
 
                         restartsLeft = ;
                     }
 
                     // Begin decode MCU
                     for (int c = 0, index = 0, blkIndex = 0; c < c++) {
                         index = [c];
 
                         if (c == 0) {
                             blkIndex = 0;
                         } else {
                             if (index == [c - 1]) {
                                 blkIndex++;
                             } else {
                                 blkIndex = 0;
                             }
                         }
                         curDCTable = components[index].;
 
                         if (.getAh() == 0) { // first scan
                             // only DC
                             decodeDCFirst(indexcurDCTable.getAl(), [index][m], blkIndex);
                         } else { // subsequent scans
                             // only DC
                             decodeDCRefine(.getAl(), [index][m], blkIndex);
 
                         }
                     }
                     // End decode MCU
 
                     restartsLeft--;
                 }
             } else {
                 // non-interleaved
                 int componentH = components[componentIndexes[0]].getH();
                 int componentV = components[componentIndexes[0]].getV();
                 int blksInVertica = (componentV == 1 ?  : ((.getY() + 7) / ));
                 int blksInHorizon = (componentH == 1 ?  : ((.getX() + 7) / ));
                 int MCUIndex = 0, blkIndex = 0, secondBlkIndex = (componentH == 1 ? 1 : 2);
 
                 curACTable = components[componentIndexes[0]].;
 
                 for (int v = 0; v < blksInVerticav++) {
                     MCUIndex = (v / componentV) *  - 1;
 
                     for (int h = 0; h < blksInHorizonh++) {
                         if (h % componentH == 0) {
                             MCUIndex++;
                             blkIndex = 0;
 
                             if (v % componentV != 0) {
                                 blkIndex = secondBlkIndex;
                             }
                         }
 
                         // If support restart interval
                         if ( > 0 && restartsLeft == 0) {
                             marker = nextMarker();
 
                             if (marker > . || marker < .) {
                                 return marker;
                             }
 
                             .resetBuffer();
 
                             resetDecoder();
 
                             restartsLeft = ;
                         }
 
                         if (.getAh() == 0) {
                             decodeACFirst(curACTable.getSs(), .getSe(), .getAl(),
                                           [componentIndexes[0]][MCUIndex], blkIndex);
                         } else {
                             decodeACRefine(curACTable.getSs(), .getSe(), .getAl(),
                                            [componentIndexes[0]][MCUIndex], blkIndex);
                         }
 
                         blkIndex++;
 
                         /* There is always only one block per MCU */
                         restartsLeft--;
                     }
                 }
             }
 
             marker = nextMarker();
         } catch (JPEGMarkerException e) {
             marker = e.getMarker();
         } catch (EOFException e) {
             marker = -1;
         } catch (ArrayIndexOutOfBoundsException e) {
             // Note : just ignore huffman decode error
             marker = -1;
              = true;
         }
 
         return marker;
     }
 
     protected void validateProgressiveParam() {
         if (.getSs() == 0) {
             if (.getSe() != 0) {
                 throw new IllegalArgumentException("Invalid progressive parameters");
             }
         } else {
             /* need not check Ss/Se < 0 since they came from unsigned bytes */
             if (.getSe() < .getSs() || .getSe() > 63) throw new IllegalArgumentException(
                                                                                                                        "Invalid progressive parameters");
 
             /* AC scans may have only one component */
             if (.getNs() != 1) throw new IllegalArgumentException("Invalid progressive parameters");
         }
 
         if (.getAh() != 0) {
             /* Successive approximation refinement scan: must have Al = Ah-1. */
             if (.getAh() - 1 != .getAl()) throw new IllegalArgumentException(
                                                                                                  "Invalid progressive parameters");
         }
 
         if (.getAl() > 13) { /* need not check for < 0 */
             throw new IllegalArgumentException("Invalid progressive parameters");
         }
     }

    
can opt using array

Parameters:
marker
Returns:
 
     protected boolean isSOFnMarker(int marker) {
         if (marker <= 0xC3 && marker >= 0xC0) {
             return true;
         }
 
         if (marker <= 0xCB && marker >= 0xC5) {
             return true;
         }
 
         if (marker <= 0xCF && marker >= 0xCD) {
             return true;
         }
 
         return false;
     }
 
     protected void readTables(int markerthrows IOExceptionJPEGMarkerException {
         switch (marker) {
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
             case .:
                 decodeExtendMarker(marker);
                 break;
             case .:
                 decodeDAC();
                 break;
             case .:
                 decodeHuffmanTable();
                 break;
             case .:
                 decodeQuantizationTable();
                 break;
             case .:
                 decodeDRI();
                 break;
             case .:
                 decodeExtendMarker(.);
                 break;
             case .:
                 decodeDNL();
                 break;
             default:
                 // Unknown marker, just throws it
                 throw new JPEGMarkerException(marker);
         }
     }
 
     protected void decodeDNL() throws IOException {
         .readShort(); // Skip Ld
 
         .readUnsignedShort(); // Read NL just ignore, because the DNL marker is unsupported
     }
 
     protected void decodeDRI() throws IOException {
         int length;
 
         length = .readUnsignedShort();
 
         if (length != 4) {
             throw new JPEGDecoderException("Bogus marker length");
         }
 
          = .readUnsignedShort();
     }
 
     protected void decodeHuffmanTable() throws IOException {
         int length;
         int bits[];
         int huffval[];
 
         int indexcount;
 
         length = .readUnsignedShort();
         length -= 2;
 
         while (length > 0) {
             index = .read();
 
             count = 0;
 
             bits = new int[17];
             for (int i = 1; i <= 16; i++) {
                 bits[i] = .read();
                 count += bits[i];
             }
 
             length -= (1 + 16);
 
             /*
              * Here we just do minimal validation of the counts to avoid walking off the end of our table space
              */
             if (count > 256 || count > length) {
                 throw new JPEGDecoderException("Bogus Huffman table definition");
             }
 
             huffval = new int[256];
             for (int i = 0; i < counti++) {
                 huffval[i] = .read();
             }
 
             length -= count;
 
             if ((index >> 4) == .) {
                 /* AC table definition */
                 index -= 0x10;
                 [index] = new HuffmanTable(.indexbitshuffval);
             } else {
                 /* DC table definition */
                 [index] = new HuffmanTable(.indexbitshuffval);
             }
 
             if (index < 0 || index >= 4) {
                 throw new JPEGDecoderException("Bogus DHT index " + index);
             }
         }
 
         if (length != 0) {
             throw new JPEGDecoderException("Bogus marker length");
         }
     }
 
     protected void decodeQuantizationTable() throws IOException {
         int lengthcount = 0;
         int[] Q;
 
         length = .readUnsignedShort();
         length -= 2;
 
         while (length > 0) {
             int prec = 0, n = 0;
 
             n = .read();
             length--;
 
             prec = n >> 4; // Pq
             n &= 0x0F; // Tq
 
             if (n >= 4) {
                 throw new JPEGDecoderException("Unsupport quantization table more than 4 ");
             }
 
             Q = new int[64];
 
             if (prec > 0) {
                 if (length < 64 * 2) {
                     /* Initialize full table for safety. */
                     for (int i = 0; i < 64; i++) {
                         Q[i] = 1;
                     }
                     count = length >> 1;
                 } else count = 64;
             } else {
                 if (length < 64) {
                     /* Initialize full table for safety. */
                     for (int i = 0; i < 64; i++) {
                         Q[i] = 1;
                     }
                     count = length;
                 } else count = 64;
             }
 
             for (int i = 0; i < counti++) {
                 if (prec > 0) {
                     Q[.[i]] = .readUnsignedShort();
                 } else {
                     Q[.[i]] = .read();
                 }
             }
 
             /*
              * For AA&N IDCT method, multipliers are equal to quantization coefficients scaled by
              * scalefactor[row]*scalefactor[col], where scalefactor[0] = 1 scalefactor[k] = cos(k*PI/16) * sqrt(2) for
              * k=1..7 For integer operation, the multiplier table is to be scaled by IFAST_SCALE_BITS. nothing to do for
              * slowIDCTMode
              */
             if () {
                 int half = 1 << 11;
                 for (int i = 0; i < 64; i++) {
                     Q[i] = (Q[i] * .[i] + half) >> 12;
                 }
             }
 
             QuantizationTable qTable = new QuantizationTable(Q);
             [n] = qTable;
 
             length -= count;
             if (prec > 0) length -= count;
         }
 
         if (length != 0) {
             throw new JPEGDecoderException("Bogus marker length");
         }
     }
 
     protected void decodeDAC() throws IOException {
         throw new UnsupportedOperationException("Not implement yet");
     }
 
     protected void decodeExtendMarker(int markerthrows IOException {
         int length = .readUnsignedShort();
         length -= 2;
 
         ExtendImageHeaderReader reader = .get(marker);
 
         if (reader != null) {
             reader.readProperties(length);
         } else {
             if (length > 0) {
                 .skipBytes(length);
             }
         }
     }
 
     protected void determinColorspace() {
         switch (.getNf()) {
             case 1:
                 .setRawColorspace(.);
                 .setColorspace(.);
                  = new NullColorConvertor();
                 break;
 
             case 3:
                 if (.isSawJFIFMarker()) {
                     /* JFIF implies YCbCr */
                     .setRawColorspace(.);
                      = new YCbCr2RGBColorConvertor();
                 } else if (.isSawAdobeMarker()) {
                     switch (.getAdobeTransform()) {
                         case 0:
                             .setRawColorspace(.);
                              = new NullColorConvertor();
                             break;
                         case 1:
                             .setRawColorspace(.);
                              = new YCbCr2RGBColorConvertor();
                             break;
                         default:
                             /* assume it's YCbCr */
                             .setRawColorspace(.);
                              = new YCbCr2RGBColorConvertor();
                             break;
                     }
                 } else {
                     /*
                      * Saw no special markers, try to guess from the component IDs
                      */
                     int cid0 = .getComponents()[0].getC();
                     int cid1 = .getComponents()[1].getC();
                     int cid2 = .getComponents()[2].getC();
 
                     if (cid0 == 1 && cid1 == 2 && cid2 == 3) {
                         /* assume JFIF w/out marker */
                         .setRawColorspace(.);
                          = new YCbCr2RGBColorConvertor();
                     } else if (cid0 == 82 && cid1 == 71 && cid2 == 66) {
                         /* ASCII 'R', 'G', 'B' */
                         .setRawColorspace(.);
                          = new NullColorConvertor();
                     } else {
                         /* assume it's YCbCr */
                         .setRawColorspace(.);
                          = new YCbCr2RGBColorConvertor();
                     }
                 }
 
                 /* Always guess RGB is proper output colorspace. */
                 .setColorspace(.);
                 break;
 
             case 4:
                 if (.isSawAdobeMarker()) {
                     switch (.getAdobeTransform()) {
                         case 0:
                             .setRawColorspace(.);
                              = new InverseColorConvertor();
                             break;
                         case 2:
                             .setRawColorspace(.);
                              = new YCCK2CMYKColorConvertor();
                             break;
                         default:
                             /* assume it's YCCK */
                             .setRawColorspace(.);
                              = new YCCK2CMYKColorConvertor();
                             break;
                     }
                 } else {
                     /* No special markers, assume straight CMYK. */
                     .setRawColorspace(.);
                      = new InverseColorConvertor();
                 }
                 .setColorspace(.);
                 break;
 
             default:
                 .setRawColorspace(.);
                 .setColorspace(.);
                  = new NullColorConvertor();
                 break;
         }
     }
 
     protected void readFrameHeader(int markerthrows IOException {
         switch (marker) {
             case .:/* Baseline */
                 createFrameHeader(truefalse);
                 break;
             case .:/* Extended sequential, Huffman */
                 createFrameHeader(falsefalse);
                 break;
             case .:/* Progressive, Huffman */
                 createFrameHeader(falsetrue);
                 break;
 
             /* Currently unsupported SOFn types */
             case .:/* Extended sequential, arithmetic */
             case .:/* Progressive, arithmetic */
             case ./* Lossless, Huffman */
             case ./* Differential sequential, Huffman */
             case ./* Differential progressive, Huffman */
             case ./* Differential lossless, Huffman */
             case ./* Reserved for JPEG extensions */
             case ./* Lossless, arithmetic */
             case ./* Differential sequential, arithmetic */
             case ./* Differential progressive, arithmetic */
             case ./* Differential lossless, arithmetic */
             default:
                 throw new JPEGDecoderException("Unsupported SOFn types " + marker);
         }
     }
 
     protected void createFrameHeader(boolean baselineboolean progressivethrows IOException {
         if ( != null) {
             throw new JPEGDecoderException("Duplicate SOFn marker");
         }
 
         int length = .readUnsignedShort();
 
          = new FrameHeader(baselineprogressive);
         .setLF(length);
         .setP(.read());
         .setY(.readUnsignedShort());
         .setX(.readUnsignedShort());
         .setNf(.read());
 
         length -= 8;
 
         if (.getX() <= 0 || .getY() <= 0 || .getNf() <= 0) {
             throw new JPEGDecoderException("Illegal JPEG frame width or height or components");
         }
 
         if (length != .getNf() * 3) {
             throw new JPEGDecoderException("Illegal JPEG frame length");
         }
 
 
         for (int i = 0; i < .getNf(); i++) {
             Component com = new Component();
             com.setIndex(i);
            com.setC(.read());
            int factor = .read();
            com.setH((factor >> 4) & 0x0F);
            com.setV((factor) & 0x0F);
            com.setTq(.read());
            .getComponents()[i] = com;
            if (com.getH() > ) {
                 = com.getH();
            }
            if (com.getV() > ) {
                 = com.getV();
            }
        }
        for (int i = 0; i < .getNf(); i++) {
            Component comp = .getComponents()[i];
            int st = ( * ) / (comp.getH() * comp.getV());
            comp.setSampleTimes(st);
            if (comp.getH() != ) {
                comp.setHorizonDCTScaledSize( * 8);
            } else {
                comp.setHorizonDCTScaledSize(8);
            }
            if (comp.getV() != ) {
                comp.setVerticaDCTScaledSize( * 8);
            } else {
                comp.setVerticaDCTScaledSize(8);
            }
        }
        if ( == null) {
             = new InternalRawImage();
        }
        .initData();
         = new int[.getNf()];
        // Calculate some parameter
         = (((.getX() + 7) / 8) + ( - 1)) / ;
         = (((.getY() + 7) / 8) + ( - 1)) / ;
        if (progressive) {
            int MCUs =  * ;
            // x components, y max MCU, z MZU size
             = new int[4][][];
            [0] = new int[MCUs][ *  * ];
            if (.getNf() > 1) {
                [1] = new int[MCUs][ *  * ];
                [2] = new int[MCUs][ *  * ];
            }
       &nbs