⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jpegdecoder.java

📁 Free Software Foundation Inc.公司用java写的jpeg解码器。一个优秀的图像解码器面向对象模型。
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                  dcTables[(int) huffmanIndex] = new JPEGHuffmanTable(codeLength,
                                                                      huffmanVal);
                // Assign AC Huffman Table.
                else if (tableClass == HuffmanTable.JPEG_AC_TABLE)
                  acTables[(int) huffmanIndex] = new JPEGHuffmanTable(codeLength,
                                                                      huffmanVal);
              }
            break;
          case JPEGMarker.DQT:
            // DQT non-SOF Marker - This defines the quantization
            // coeffecients, this allows us to figure out the quality of
            // compression and unencode the data. The data is loaded and
            // then stored in to an array.
            short quantizationLength = (short) (jpegStream.readShort() - 2);
            for (int j = 0; j < quantizationLength / 65; j++)
              {
                byte quantSpecs = jpegStream.readByte();
                int[] quantData = new int[64];
                if ((byte) (quantSpecs >> 4) == 0)
                  // Precision 8 bit.
                  {
                    for (int i = 0; i < 64; i++)
                      quantData[i] = jpegStream.readByte();
                  
                  }
                else if ((byte) (quantSpecs >> 4) == 1)
                  // Precision 16 bit.
                  {
                    for (int i = 0; i < 64; i++)
                      quantData[i] = jpegStream.readShort();
                  }
                qTables[(int) (quantSpecs & 0x0f)] = new JPEGQTable (quantData);
              }
            break;
          case JPEGMarker.SOS:
            // SOS non-SOF Marker - Start Of Scan Marker, this is where the
            // actual data is stored in a interlaced or non-interlaced with
            // from 1-4 components of color data, if three components most
            // likely a YCrCb model, this is a fairly complex process.

            // Read in the scan length.
            jpegStream.readShort();
            // Number of components in the scan.
            byte numberOfComponents = jpegStream.readByte();
            byte[] componentSelector = new byte[numberOfComponents];
            for (int i = 0; i < numberOfComponents; i++)
              {
                // Component ID, packed byte containing the Id for the
                // AC table and DC table.
                byte componentID = jpegStream.readByte();
                byte tableInfo = jpegStream.readByte();
                frame.setHuffmanTables(componentID,
                                       acTables[(byte) (tableInfo >> 4)],
                                       dcTables[(byte) (tableInfo & 0x0f)]);
                componentSelector[i] = componentID;
              }
            byte startSpectralSelection = jpegStream.readByte();
            byte endSpectralSelection = jpegStream.readByte();
            byte successiveApproximation = jpegStream.readByte();

            int mcuIndex = 0; 
            int mcuTotalIndex = 0;
            // This loops through until a MarkerTagFound exception is
            // found, if the marker tag is a RST (Restart Marker) it
            // simply skips it and moves on this system does not handle
            // corrupt data streams very well, it could be improved by
            // handling misplaced restart markers.
            while (true)
              {
                try
                  {
                    // Loop though capturing MCU, instruct each
                    // component to read in its necessary count, for
                    // scaling factors the components automatically
                    // read in how much they need
                    for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
                      {
                        JPEGComponent comp = (JPEGComponent) frame.components.getComponentByID(componentSelector[compIndex]);
                        comp.readComponentMCU(jpegStream);
                      }
                    mcuIndex++;
                    mcuTotalIndex++;
                  }
                // We've found a marker, see if the marker is a restart
                // marker or just the next marker in the stream. If
                // it's the next marker in the stream break out of the
                // while loop, if it's just a restart marker skip it
                catch (JPEGMarkerFoundException bse)
                  {
                    // Handle JPEG Restart Markers, this is where the
                    // count of MCU's per interval is compared with
                    // the count actually obtained, if it's short then
                    // pad on some MCU's ONLY for components that are
                    // greater than one. Also restart the DC prediction
                    // to zero.
                    if (marker == JPEGMarker.RST0
                        || marker == JPEGMarker.RST1
                        || marker == JPEGMarker.RST2
                        || marker == JPEGMarker.RST3
                        || marker == JPEGMarker.RST4
                        || marker == JPEGMarker.RST5
                        || marker == JPEGMarker.RST6
                        || marker == JPEGMarker.RST7)
                      {
                        for (int compIndex = 0; compIndex < numberOfComponents; compIndex++)
                          {
                            JPEGComponent comp = (JPEGComponent) frame.components.getComponentByID(componentSelector[compIndex]);
                            if (compIndex > 1)
                              comp.padMCU(mcuTotalIndex, resetInterval - mcuIndex);
                            comp.resetInterval();
                          }
                        mcuTotalIndex += (resetInterval - mcuIndex);
                        mcuIndex = 0;
                      }
                    else
                      {
                        // We're at the end of our scan, exit out.
                        break;
                      }
                  }
              }
            break;
          case JPEGMarker.DRI:
            // DRI - This defines the restart interval, if we have a
            // restart interval when we reach our restart modulo calculate
            // whether the count of MCU's specified in the restart
            // interval have been reached, if they havent then pad with
            // whatever MCU was last used, this is supposed to be a form of
            // error recovery but it turns out that some JPEG encoders
            // purposely cause missing MCU's on repeating MCU's to compress
            // data even more (even though it adds an extra layer of
            // complexity.. But since when is JPEG easy?
            jpegStream.skipBytes(2);
            resetInterval = jpegStream.readShort();
            break;
          case JPEGMarker.COM:
            // COM - This is a comment that was inserted into the JPEG, we
            // simply skip over the comment because it's really of no
            // importance, usually contains a verbal description of the
            // application or author who created the JPEG.
            jpegStream.skipBytes(jpegStream.readShort() - 2);
            break;
          case JPEGMarker.DNL:
            // DNL - This sets the height of the image. This is the Define
            // Number Lines for the image, I'm not sure exactly why we need
            // this but, whatever we'll abide.
            frame.setScanLines(jpegStream.readShort());
            break;
          case JPEGMarker.EOI:
            // EOI - End of Image, this processes the frames and turns the
            // frames into a buffered image.

            if (jpegFrames.size() == 0)
              {
                return;
              }
            else if (jpegFrames.size() == 1)
              {
                // Only one frame, JPEG Non-Heirarchial Frame.

                DCT myDCT = new DCT();
                WritableRaster raster =
                  Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
                                                 frame.width,
                                                 frame.height,
                                                 frame.getComponentCount(),
                                                 new Point(0, 0));

                // Unencode the data.
                for (int i = 0; i < frame.getComponentCount(); i++)
                  {
                    JPEGComponent comp =
                      (JPEGComponent) frame.components.get(i);
                    comp.setQuantizationTable(qTables[comp.quant_id].getTable());
                    comp.quantitizeData();
                    comp.idctData(myDCT);
                  }
                // Scale the image and write the data to the raster.
                for (int i = 0; i < frame.getComponentCount(); i++)
                  {
                    JPEGComponent comp = (JPEGComponent) frame.components.get(i);
                    comp.scaleByFactors();
                    comp.writeData(raster, i);
                    // Ensure garbage collection.
                    comp = null;
                  }
                // Grayscale Color Image (1 Component).
                if (frame.getComponentCount() == 1)
                  {
                    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
                    ComponentColorModel ccm =
                      new ComponentColorModel(cs, false, false,
                                              Transparency.OPAQUE,
                                              DataBuffer.TYPE_BYTE);
                    image = new BufferedImage(ccm, raster, false,
                                              new Hashtable());
                  }
                // YCbCr Color Image (3 Components).
                else if (frame.getComponentCount() == 3)
                  {
                    ComponentColorModel ccm =
                      new ComponentColorModel(new YCbCr_ColorSpace(), false,
                                              false, Transparency.OPAQUE,
                                              DataBuffer.TYPE_BYTE);
                    image = new BufferedImage(ccm, raster, false,
                                              new Hashtable());
                  }
                // Possibly CMYK or RGBA ?
                else
                  {
                    throw new JPEGException("Unsupported Color Mode: 4 "
                                            + "Component Color Mode found.");
                  }
                height = frame.height;
                width = frame.width;
              }
            else
              {
                //JPEG Heirarchial Frame (progressive or baseline).
                throw new JPEGException("Unsupported Codec Type:"
                                        + " Hierarchial JPEG");
              }
            break;
          case JPEGMarker.SOF1:
            // ERROR - If we encounter any of the following marker codes
            // error out with a codec exception, progressive, heirarchial,
            // differential, arithmetic, lossless JPEG's are not supported.
            // This is where enhancements can be made for future versions.
            // Thankfully 99% of all JPEG's are baseline DCT.
            throw new JPEGException("Unsupported Codec Type: Extended "
                                    + "Sequential DCT JPEG's Not-Supported");
            //case JPEGMarker.SOF2:
            //	throw new JPEGException("Unsupported Codec Type: Progressive DCT JPEG's Not-Supported");
          case JPEGMarker.SOF3:
            throw new JPEGException("Unsupported Codec Type:"
                                    + " Lossless (sequential)");
          case JPEGMarker.SOF5:
            throw new JPEGException("Unsupported Codec Type:"
                                    + " Differential sequential DCT");
          case JPEGMarker.SOF6:
            throw new JPEGException("Unsupported Codec Type:"
                                    + " Differential progressive DCT");
          case JPEGMarker.SOF7:
            throw new JPEGException("Unsupported Codec Type:"
                                    + " Differential lossless");
          case JPEGMarker.SOF9:
          case JPEGMarker.SOF10:
          case JPEGMarker.SOF11:
          case JPEGMarker.SOF13:
          case JPEGMarker.SOF14:
          case JPEGMarker.SOF15:
            throw new JPEGException("Unsupported Codec Type:"
                                    + " Arithmetic Coding Frame");
          default:
            // Unknown marker found, ignore it.
          }
        marker = jpegStream.findNextMarker();
      }
  }

  // If the current marker is APP0, tries to decode a JFIF extension
  // and advances the current marker to the next marker in the stream.
  private void decodeJFIFExtension() throws IOException
  {
    if (marker == JPEGMarker.APP0)
      {
        int length = jpegStream.readShort();

        if (length >= JFXX_FIXED_LENGTH)
          {
            byte[] identifier = new byte[5];
            jpegStream.read(identifier);
            if (identifier[0] != JPEGMarker.JFIF_J
                || identifier[1] != JPEGMarker.JFIF_F
                || identifier[2] != JPEGMarker.JFIF_X
                || identifier[3] != JPEGMarker.JFIF_X
                || identifier[4] != JPEGMarker.X00)
              // Not a JFXX field.  Ignore it and continue.
              jpegStream.skipBytes(length - 7);
            else
              {
                byte extension_code = jpegStream.readByte();

                switch (extension_code)
                  {
                  case JPEGMarker.JFXX_JPEG:
                    // FIXME: add support for JFIF Extension:
                    // Thumbnail coded using JPEG.
                    jpegStream.skipBytes(length - 8);
                  case JPEGMarker.JFXX_ONE_BPP:
                    // FIXME: add support for JFIF Extension:
                    // Thumbnail stored using 1 byte/pixel.
                    jpegStream.skipBytes(length - 8);
                  case JPEGMarker.JFXX_THREE_BPP:
                    // FIXME: add support for JFIF Extension:
                    // Thumbnail stored using 3 bytes/pixel.
                    jpegStream.skipBytes(length - 8);
                  }
              }
          }
        else
          {
            // Unknown APP0 marker.  Ignore it and continue.
            jpegStream.skipBytes(length - 2);
          }
        marker = jpegStream.findNextMarker();
      }
  }

  public BufferedImage getImage()
  {
    return image;
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -