Class JPEGImageReader


  • public final class JPEGImageReader
    extends ImageReaderBase
    A JPEG ImageReader implementation based on the JRE JPEGImageReader, that adds support and properly handles cases where the JRE version throws exceptions.
    Main features:
    • Support for YCbCr JPEGs without JFIF segment (converted to RGB, using the embedded ICC profile if applicable)
    • Support for CMYK JPEGs (converted to RGB by default or as CMYK, using the embedded ICC profile if applicable)
    • Support for Adobe YCCK JPEGs (converted to RGB by default or as CMYK, using the embedded ICC profile if applicable)
    • Support for JPEGs containing ICC profiles with interpretation other than 'Perceptual' (profile is assumed to be 'Perceptual' and used)
    • Support for JPEGs containing ICC profiles with class other than 'Display' (profile is assumed to have class 'Display' and used)
    • Support for JPEGs containing ICC profiles that are incompatible with stream data (image data is read, profile is ignored)
    • Support for JPEGs with corrupted ICC profiles (image data is read, profile is ignored)
    • Support for JPEGs with corrupted ICC_PROFILE segments (image data is read, profile is ignored)
    • Support for JPEGs using non-standard color spaces, unsupported by Java 2D (image data is read, profile is ignored)
    • Issues warnings instead of throwing exceptions in cases of corrupted data where ever the image data can still be read in a reasonable way
    Thumbnail support:
    • Support for JFIF thumbnails (even if stream contains inconsistent metadata)
    • Support for JFXX thumbnails (JPEG, Indexed and RGB)
    • Support for EXIF thumbnails (JPEG, RGB and YCbCr)
    Metadata support:
    • Support for JPEG metadata in both standard and native formats (even if stream contains inconsistent metadata)
    • Support for javax_imageio_jpeg_image_1.0 format (currently as native format, may change in the future)
    • Support for illegal combinations of JFIF, Exif and Adobe markers, using "unknown" segments in the "MarkerSequence" tag for the unsupported segments (for javax_imageio_jpeg_image_1.0 format)
    Version:
    $Id: JPEGImageReader.java,v 1.0 24.01.11 16.37 haraldk Exp$
    • Field Summary

      Fields 
      Modifier and Type Field Description
      (package private) static int ALL_APP_MARKERS
      Internal constant for referring all APP segments
      private int currentStreamIndex  
      (package private) static boolean DEBUG  
      private javax.imageio.ImageReader delegate
      Our JPEG reading delegate
      (package private) static boolean FORCE_RASTER_CONVERSION  
      private JPEGImageReader.ProgressDelegator progressDelegator
      Listens to progress updates in the delegate, and delegates back to this instance
      private java.util.List<Segment> segments
      Cached list of JPEG segments we filter from the underlying stream
      private java.util.List<java.lang.Long> streamOffsets  
      private javax.imageio.ImageReader thumbnailReader
      Extra delegate for reading JPEG encoded thumbnails
      private java.util.List<ThumbnailReader> thumbnails  
      • Fields inherited from class javax.imageio.ImageReader

        availableLocales, ignoreMetadata, input, locale, minIndex, originatingProvider, progressListeners, seekForwardOnly, updateListeners, warningListeners, warningLocales
    • Constructor Summary

      Constructors 
      Constructor Description
      JPEGImageReader​(javax.imageio.spi.ImageReaderSpi provider, javax.imageio.ImageReader delegate)  
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      void abort()  
      boolean canReadRaster()  
      private void checkThumbnailBounds​(int imageIndex, int thumbnailIndex)  
      private static void convertYCbCr2RGB​(java.awt.image.Raster raster, int numComponents)  
      private static void convertYCCK2CMYK​(java.awt.image.Raster raster)  
      private boolean delegateCSTypeMismatch​(JFIF jfif, AdobeDCT adobeDCT, Frame startOfFrame, JPEGColorSpace sourceCSType)  
      void dispose()  
      private java.awt.color.ICC_Profile ensureDisplayProfile​(java.awt.color.ICC_Profile profile)  
      (package private) AdobeDCT getAdobeDCT()  
      (package private) java.util.List<Application> getAppSegments​(int marker, java.lang.String identifier)  
      javax.imageio.ImageReadParam getDefaultReadParam()  
      (package private) java.awt.color.ICC_Profile getEmbeddedICCProfile​(boolean allowBadIndexes)  
      private EXIF getExif()  
      java.lang.String getFormatName()  
      int getHeight​(int imageIndex)  
      javax.imageio.metadata.IIOMetadata getImageMetadata​(int imageIndex)
      Default implementation that always returns null.
      java.util.Iterator<javax.imageio.ImageTypeSpecifier> getImageTypes​(int imageIndex)  
      (package private) JFIF getJFIF()  
      (package private) JFXX getJFXX()  
      int getNumImages​(boolean allowSearch)
      Default implementation that always returns 1.
      int getNumThumbnails​(int imageIndex)  
      javax.imageio.ImageTypeSpecifier getRawImageType​(int imageIndex)  
      (package private) Frame getSOF()  
      (package private) static JPEGColorSpace getSourceCSType​(JFIF jfif, AdobeDCT adobeDCT, Frame startOfFrame)  
      javax.imageio.metadata.IIOMetadata getStreamMetadata()
      Default implementation that always returns null.
      int getThumbnailHeight​(int imageIndex, int thumbnailIndex)  
      (package private) javax.imageio.ImageReader getThumbnailReader()  
      int getThumbnailWidth​(int imageIndex, int thumbnailIndex)  
      int getWidth​(int imageIndex)  
      private void gotoImage​(int imageIndex)  
      private void initDelegate​(boolean seekForwardOnly, boolean ignoreMetadata)  
      private void initHeader()  
      private void initHeader​(int imageIndex)  
      private void installListeners()  
      (package private) static int intFromBigEndian​(byte[] array, int index)  
      (package private) static void intToBigEndian​(int value, byte[] array, int index)  
      private static void invertCMYK​(java.awt.image.Raster raster)  
      private boolean isLossless()  
      private Application lastAppSegment​(int marker, java.lang.String identifier)  
      static void main​(java.lang.String[] args)  
      private CompoundDirectory parseExif​(EXIF exif)  
      protected void processWarningOccurred​(java.lang.String warning)  
      java.awt.image.BufferedImage read​(int imageIndex, javax.imageio.ImageReadParam param)  
      java.awt.image.RenderedImage readAsRenderedImage​(int imageIndex, javax.imageio.ImageReadParam param)  
      boolean readerSupportsThumbnails()  
      private java.awt.color.ICC_Profile readICCProfileSafe​(java.io.InputStream stream, boolean allowBadProfile)  
      private java.awt.image.BufferedImage readImageAsRasterAndReplaceColorProfile​(int imageIndex, javax.imageio.ImageReadParam param, Frame startOfFrame, JPEGColorSpace csType, java.awt.color.ICC_Profile profile)  
      java.awt.image.Raster readRaster​(int imageIndex, javax.imageio.ImageReadParam param)  
      private java.util.List<JPEGSegment> readSegments()  
      java.awt.image.BufferedImage readThumbnail​(int imageIndex, int thumbnailIndex)  
      private void readThumbnailMetadata​(int imageIndex)  
      protected void resetMembers()
      Resets all member variables.
      void setInput​(java.lang.Object input, boolean seekForwardOnly, boolean ignoreMetadata)
      Overrides setInput, to allow easy access to the input, in case it is an ImageInputStream.
      protected static void showIt​(java.awt.image.BufferedImage pImage, java.lang.String pTitle)  
      • Methods inherited from class javax.imageio.ImageReader

        abortRequested, addIIOReadProgressListener, addIIOReadUpdateListener, addIIOReadWarningListener, checkReadParamBandSettings, clearAbortRequest, computeRegions, getAspectRatio, getAvailableLocales, getImageMetadata, getInput, getLocale, getMinIndex, getOriginatingProvider, getSourceRegion, getStreamMetadata, getTileGridXOffset, getTileGridYOffset, getTileHeight, getTileWidth, hasThumbnails, isIgnoringMetadata, isImageTiled, isRandomAccessEasy, isSeekForwardOnly, processImageComplete, processImageProgress, processImageStarted, processImageUpdate, processPassComplete, processPassStarted, processReadAborted, processSequenceComplete, processSequenceStarted, processThumbnailComplete, processThumbnailPassComplete, processThumbnailPassStarted, processThumbnailProgress, processThumbnailStarted, processThumbnailUpdate, processWarningOccurred, read, readAll, readAll, readTile, readTileRaster, removeAllIIOReadProgressListeners, removeAllIIOReadUpdateListeners, removeAllIIOReadWarningListeners, removeIIOReadProgressListener, removeIIOReadUpdateListener, removeIIOReadWarningListener, setInput, setInput, setLocale
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Field Detail

      • DEBUG

        static final boolean DEBUG
      • FORCE_RASTER_CONVERSION

        static final boolean FORCE_RASTER_CONVERSION
      • ALL_APP_MARKERS

        static final int ALL_APP_MARKERS
        Internal constant for referring all APP segments
        See Also:
        Constant Field Values
      • delegate

        private final javax.imageio.ImageReader delegate
        Our JPEG reading delegate
      • progressDelegator

        private final JPEGImageReader.ProgressDelegator progressDelegator
        Listens to progress updates in the delegate, and delegates back to this instance
      • thumbnailReader

        private javax.imageio.ImageReader thumbnailReader
        Extra delegate for reading JPEG encoded thumbnails
      • segments

        private java.util.List<Segment> segments
        Cached list of JPEG segments we filter from the underlying stream
      • currentStreamIndex

        private int currentStreamIndex
      • streamOffsets

        private final java.util.List<java.lang.Long> streamOffsets
    • Constructor Detail

      • JPEGImageReader

        JPEGImageReader​(javax.imageio.spi.ImageReaderSpi provider,
                        javax.imageio.ImageReader delegate)
    • Method Detail

      • installListeners

        private void installListeners()
      • getFormatName

        public java.lang.String getFormatName()
                                       throws java.io.IOException
        Overrides:
        getFormatName in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • isLossless

        private boolean isLossless()
                            throws java.io.IOException
        Throws:
        java.io.IOException
      • getWidth

        public int getWidth​(int imageIndex)
                     throws java.io.IOException
        Specified by:
        getWidth in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • getHeight

        public int getHeight​(int imageIndex)
                      throws java.io.IOException
        Specified by:
        getHeight in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • getImageTypes

        public java.util.Iterator<javax.imageio.ImageTypeSpecifier> getImageTypes​(int imageIndex)
                                                                           throws java.io.IOException
        Specified by:
        getImageTypes in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • getRawImageType

        public javax.imageio.ImageTypeSpecifier getRawImageType​(int imageIndex)
                                                         throws java.io.IOException
        Overrides:
        getRawImageType in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • read

        public java.awt.image.BufferedImage read​(int imageIndex,
                                                 javax.imageio.ImageReadParam param)
                                          throws java.io.IOException
        Specified by:
        read in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • delegateCSTypeMismatch

        private boolean delegateCSTypeMismatch​(JFIF jfif,
                                               AdobeDCT adobeDCT,
                                               Frame startOfFrame,
                                               JPEGColorSpace sourceCSType)
                                        throws java.io.IOException
        Throws:
        java.io.IOException
      • readImageAsRasterAndReplaceColorProfile

        private java.awt.image.BufferedImage readImageAsRasterAndReplaceColorProfile​(int imageIndex,
                                                                                     javax.imageio.ImageReadParam param,
                                                                                     Frame startOfFrame,
                                                                                     JPEGColorSpace csType,
                                                                                     java.awt.color.ICC_Profile profile)
                                                                              throws java.io.IOException
        Throws:
        java.io.IOException
      • getSourceCSType

        static JPEGColorSpace getSourceCSType​(JFIF jfif,
                                              AdobeDCT adobeDCT,
                                              Frame startOfFrame)
                                       throws javax.imageio.IIOException
        Throws:
        javax.imageio.IIOException
      • ensureDisplayProfile

        private java.awt.color.ICC_Profile ensureDisplayProfile​(java.awt.color.ICC_Profile profile)
                                                         throws java.io.IOException
        Throws:
        java.io.IOException
      • intFromBigEndian

        static int intFromBigEndian​(byte[] array,
                                    int index)
      • intToBigEndian

        static void intToBigEndian​(int value,
                                   byte[] array,
                                   int index)
      • setInput

        public void setInput​(java.lang.Object input,
                             boolean seekForwardOnly,
                             boolean ignoreMetadata)
        Description copied from class: ImageReaderBase
        Overrides setInput, to allow easy access to the input, in case it is an ImageInputStream.
        Overrides:
        setInput in class ImageReaderBase
        Parameters:
        input - the ImageInputStream or other Object to use for future decoding.
        seekForwardOnly - if true, images and metadata may only be read in ascending order from this input source.
        ignoreMetadata - if true, metadata may be ignored during reads.
        See Also:
        ImageInputStream
      • initDelegate

        private void initDelegate​(boolean seekForwardOnly,
                                  boolean ignoreMetadata)
                           throws java.io.IOException
        Throws:
        java.io.IOException
      • initHeader

        private void initHeader()
                         throws java.io.IOException
        Throws:
        java.io.IOException
      • initHeader

        private void initHeader​(int imageIndex)
                         throws java.io.IOException
        Throws:
        java.io.IOException
      • gotoImage

        private void gotoImage​(int imageIndex)
                        throws java.io.IOException
        Throws:
        java.io.IOException
      • getNumImages

        public int getNumImages​(boolean allowSearch)
                         throws java.io.IOException
        Description copied from class: ImageReaderBase
        Default implementation that always returns 1.
        Overrides:
        getNumImages in class ImageReaderBase
        Parameters:
        allowSearch - ignored, unless overridden
        Returns:
        1, unless overridden
        Throws:
        java.io.IOException - never, unless overridden
      • readSegments

        private java.util.List<JPEGSegment> readSegments()
                                                  throws java.io.IOException
        Throws:
        java.io.IOException
      • getAppSegments

        java.util.List<Application> getAppSegments​(int marker,
                                                   java.lang.String identifier)
                                            throws java.io.IOException
        Throws:
        java.io.IOException
      • getSOF

        Frame getSOF()
              throws java.io.IOException
        Throws:
        java.io.IOException
      • lastAppSegment

        private Application lastAppSegment​(int marker,
                                           java.lang.String identifier)
                                    throws java.io.IOException
        Throws:
        java.io.IOException
      • getAdobeDCT

        AdobeDCT getAdobeDCT()
                      throws java.io.IOException
        Throws:
        java.io.IOException
      • getJFIF

        JFIF getJFIF()
              throws java.io.IOException
        Throws:
        java.io.IOException
      • getJFXX

        JFXX getJFXX()
              throws java.io.IOException
        Throws:
        java.io.IOException
      • getExif

        private EXIF getExif()
                      throws java.io.IOException
        Throws:
        java.io.IOException
      • parseExif

        private CompoundDirectory parseExif​(EXIF exif)
                                     throws java.io.IOException
        Throws:
        java.io.IOException
      • getEmbeddedICCProfile

        java.awt.color.ICC_Profile getEmbeddedICCProfile​(boolean allowBadIndexes)
                                                  throws java.io.IOException
        Throws:
        java.io.IOException
      • readICCProfileSafe

        private java.awt.color.ICC_Profile readICCProfileSafe​(java.io.InputStream stream,
                                                              boolean allowBadProfile)
      • canReadRaster

        public boolean canReadRaster()
        Overrides:
        canReadRaster in class javax.imageio.ImageReader
      • readRaster

        public java.awt.image.Raster readRaster​(int imageIndex,
                                                javax.imageio.ImageReadParam param)
                                         throws java.io.IOException
        Overrides:
        readRaster in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • readAsRenderedImage

        public java.awt.image.RenderedImage readAsRenderedImage​(int imageIndex,
                                                                javax.imageio.ImageReadParam param)
                                                         throws java.io.IOException
        Overrides:
        readAsRenderedImage in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • abort

        public void abort()
        Overrides:
        abort in class javax.imageio.ImageReader
      • getDefaultReadParam

        public javax.imageio.ImageReadParam getDefaultReadParam()
        Overrides:
        getDefaultReadParam in class javax.imageio.ImageReader
      • readerSupportsThumbnails

        public boolean readerSupportsThumbnails()
        Overrides:
        readerSupportsThumbnails in class javax.imageio.ImageReader
      • readThumbnailMetadata

        private void readThumbnailMetadata​(int imageIndex)
                                    throws java.io.IOException
        Throws:
        java.io.IOException
      • getThumbnailReader

        javax.imageio.ImageReader getThumbnailReader()
                                              throws java.io.IOException
        Throws:
        java.io.IOException
      • getNumThumbnails

        public int getNumThumbnails​(int imageIndex)
                             throws java.io.IOException
        Overrides:
        getNumThumbnails in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • checkThumbnailBounds

        private void checkThumbnailBounds​(int imageIndex,
                                          int thumbnailIndex)
                                   throws java.io.IOException
        Throws:
        java.io.IOException
      • getThumbnailWidth

        public int getThumbnailWidth​(int imageIndex,
                                     int thumbnailIndex)
                              throws java.io.IOException
        Overrides:
        getThumbnailWidth in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • getThumbnailHeight

        public int getThumbnailHeight​(int imageIndex,
                                      int thumbnailIndex)
                               throws java.io.IOException
        Overrides:
        getThumbnailHeight in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • readThumbnail

        public java.awt.image.BufferedImage readThumbnail​(int imageIndex,
                                                          int thumbnailIndex)
                                                   throws java.io.IOException
        Overrides:
        readThumbnail in class javax.imageio.ImageReader
        Throws:
        java.io.IOException
      • getImageMetadata

        public javax.imageio.metadata.IIOMetadata getImageMetadata​(int imageIndex)
                                                            throws java.io.IOException
        Description copied from class: ImageReaderBase
        Default implementation that always returns null.
        Overrides:
        getImageMetadata in class ImageReaderBase
        Parameters:
        imageIndex - ignored, unless overridden
        Returns:
        null, unless overridden
        Throws:
        java.io.IOException - never, unless overridden.
      • getStreamMetadata

        public javax.imageio.metadata.IIOMetadata getStreamMetadata()
                                                             throws java.io.IOException
        Description copied from class: ImageReaderBase
        Default implementation that always returns null.
        Overrides:
        getStreamMetadata in class ImageReaderBase
        Returns:
        null, unless overridden
        Throws:
        java.io.IOException - never, unless overridden.
      • processWarningOccurred

        protected void processWarningOccurred​(java.lang.String warning)
        Overrides:
        processWarningOccurred in class javax.imageio.ImageReader
      • invertCMYK

        private static void invertCMYK​(java.awt.image.Raster raster)
      • convertYCbCr2RGB

        private static void convertYCbCr2RGB​(java.awt.image.Raster raster,
                                             int numComponents)
      • convertYCCK2CMYK

        private static void convertYCCK2CMYK​(java.awt.image.Raster raster)
      • showIt

        protected static void showIt​(java.awt.image.BufferedImage pImage,
                                     java.lang.String pTitle)
      • main

        public static void main​(java.lang.String[] args)
                         throws java.io.IOException
        Throws:
        java.io.IOException