Class PNGCodec


public class PNGCodec extends ImageCodec
A codec for the Portable Network Graphics (PNG) format. Supports both loading and saving of images.

Usage examples

Load an image

The following example code loads an image from a PNG file. Note that you could also use ImageLoader or ToolkitLoader which require only a single line of code and can load all formats supported by JIU, including PNG.
  PNGCodec codec = new PNGCodec();
  codec.setFile("image.png", CodecMode.LOAD);
  codec.process();
  PixelImage image = codec.getImage();

Save an image

  PNGCodec codec = new PNGCodec();
  codec.setFile("out.png", CodecMode.SAVE);
  codec.setImage(image);
  codec.setCompressionLevel(Deflater.BEST_COMPRESSION);
  codec.appendComment("Copyright (c) 1992 John Doe");
  // sets last modification time to current time
  codec.setModification(new GregorianCalendar(
   new SimpleTimeZone(0, "UTC")));
  codec.process();

Supported storage order types

Loading

This codec reads both non-interlaced and Adam7 interlaced PNG files.

Saving

This codec only writes non-interlaced PNG files.

Supported color types

Loading

Saving

  • BilevelImage objects are stored as grayscale 1 bit PNG streams.
  • Paletted8Image objects are stored as indexed 8 bit PNG streams. Images will always be stored as 8 bit files, even if the palette has only 16, 4 or 2 entries.
  • Gray8Image objects are stored as 8 bit grayscale PNG streams.
  • Gray16Image objects are stored as 16 bit grayscale PNG streams.
  • RGB24Image objects are stored as 24 bit RGB truecolor PNG streams.
  • RGB48Image objects are stored as 48 bit RGB truecolor PNG streams.

Transparency information

PNG allows to store different types of transparency information. Full alpha channels, transparent index values, and more. Right now, this JIU codec does not make use of this information and simply skips over it when encountered.

Bounds

This codec regards the bounds concept. If bounds are specified with ImageCodec.setBounds(int, int, int, int), the codec will only load or save part of an image.

Metadata

Loading

Saving

Implementation details

This class relies heavily on the Java runtime library for decompression and checksum creation.

Background

To learn more about the PNG file format, visit its official homepage. There you can find a detailed specification, test images and existing PNG libraries and PNG-aware applications. The book PNG - The Definitive Guide by Greg Roelofs, published by O'Reilly, 1999, ISBN 1-56592-542-4 is a valuable source of information on PNG. It is out of print, but it can be viewed online and downloaded for offline reading in its entirety from the site.
Since:
0.12.0
Author:
Marco Schmidt
  • Field Details

    • CHUNK_CRC32_IEND

      private final int CHUNK_CRC32_IEND
      See Also:
    • CHUNK_SIZE_IHDR

      private final int CHUNK_SIZE_IHDR
      See Also:
    • CHUNK_TYPE_IDAT

      private final int CHUNK_TYPE_IDAT
      See Also:
    • CHUNK_TYPE_IEND

      private final int CHUNK_TYPE_IEND
      See Also:
    • CHUNK_TYPE_IHDR

      private final int CHUNK_TYPE_IHDR
      See Also:
    • CHUNK_TYPE_PHYS

      private final int CHUNK_TYPE_PHYS
      See Also:
    • CHUNK_TYPE_PLTE

      private final int CHUNK_TYPE_PLTE
      See Also:
    • CHUNK_TYPE_TEXT

      private final int CHUNK_TYPE_TEXT
      See Also:
    • CHUNK_TYPE_TIME

      private final int CHUNK_TYPE_TIME
      See Also:
    • COLOR_TYPE_GRAY

      private final int COLOR_TYPE_GRAY
      See Also:
    • COLOR_TYPE_GRAY_ALPHA

      private final int COLOR_TYPE_GRAY_ALPHA
      See Also:
    • COLOR_TYPE_INDEXED

      private final int COLOR_TYPE_INDEXED
      See Also:
    • COLOR_TYPE_RGB

      private final int COLOR_TYPE_RGB
      See Also:
    • COLOR_TYPE_RGB_ALPHA

      private final int COLOR_TYPE_RGB_ALPHA
      See Also:
    • COLOR_TYPE_ALPHA

      private final int COLOR_TYPE_ALPHA
      See Also:
    • FILTER_TYPE_NONE

      private final int FILTER_TYPE_NONE
      See Also:
    • FILTER_TYPE_SUB

      private final int FILTER_TYPE_SUB
      See Also:
    • FILTER_TYPE_UP

      private final int FILTER_TYPE_UP
      See Also:
    • FILTER_TYPE_AVERAGE

      private final int FILTER_TYPE_AVERAGE
      See Also:
    • FILTER_TYPE_PAETH

      private final int FILTER_TYPE_PAETH
      See Also:
    • COMPRESSION_DEFLATE

      private final int COMPRESSION_DEFLATE
      See Also:
    • INTERLACING_NONE

      private final int INTERLACING_NONE
      See Also:
    • INTERLACING_ADAM7

      private final int INTERLACING_ADAM7
      See Also:
    • FILTERING_ADAPTIVE

      private final int FILTERING_ADAPTIVE
      See Also:
    • MAX_TEXT_SIZE

      private final int MAX_TEXT_SIZE
      See Also:
    • ADAM7_NUM_PASSES

      private final int ADAM7_NUM_PASSES
      See Also:
    • DEFAULT_ENCODING_MIN_IDAT_SIZE

      private final int DEFAULT_ENCODING_MIN_IDAT_SIZE
      See Also:
    • ADAM7_COLUMN_INCREMENT

      private final int[] ADAM7_COLUMN_INCREMENT
    • ADAM7_FIRST_COLUMN

      private final int[] ADAM7_FIRST_COLUMN
    • ADAM7_FIRST_ROW

      private final int[] ADAM7_FIRST_ROW
    • ADAM7_ROW_INCREMENT

      private final int[] ADAM7_ROW_INCREMENT
    • MAGIC_BYTES

      private final byte[] MAGIC_BYTES
    • alpha

      private boolean alpha
    • buffers

      private byte[][] buffers
    • bpp

      private int bpp
    • checksum

      private CRC32 checksum
    • checkedIn

      private CheckedInputStream checkedIn
    • chunkCounter

      private int chunkCounter
    • colorType

      private int colorType
    • compressionType

      private int compressionType
    • currentBufferIndex

      private int currentBufferIndex
    • deflateLevel

      private int deflateLevel
    • deflateStrategy

      private int deflateStrategy
    • encodingMinIdatSize

      private int encodingMinIdatSize
    • filterType

      private int filterType
    • hasIhdr

      private boolean hasIhdr
    • height

      private int height
    • image

      private IntegerImage image
    • in

      private DataInputStream in
    • infl

      private InflaterInputStream infl
    • interlaceType

      private int interlaceType
    • modification

      private Calendar modification
    • numChannels

      private int numChannels
    • out

      private DataOutput out
    • palette

      private Palette palette
    • precision

      private int precision
    • previousBufferIndex

      private int previousBufferIndex
    • width

      private int width
  • Constructor Details

    • PNGCodec

      public PNGCodec()
  • Method Details

    • allocateImage

      private void allocateImage() throws InvalidFileStructureException, UnsupportedTypeException
      Allocates the right image to private field image, taking into consideration the fields width, height, precision and colorType. Assumes that an IHDR chunk has been read and the above mentioned fields have been initialized and checked for their validity.
      Throws:
      InvalidFileStructureException
      UnsupportedTypeException
    • checkColorTypeAndPrecision

      private void checkColorTypeAndPrecision() throws UnsupportedTypeException
      Checks values precision and colorType. A lot of combinations possibly found in an IHDR chunk are invalid. Also initializes alpha and numChannels.
      Throws:
      UnsupportedTypeException - if an invalid combination of precision and colorType is found
    • computeBytesPerRow

      private int computeBytesPerRow(int numPixels)
      Computes a number of bytes for a given number of pixels, regarding precision and availability of an alpha channel.
      Parameters:
      numPixels - the number of pixels for which the number of bytes necessary to store them is to be computed
      Returns:
      number of bytes
    • computeColumnsAdam7

      private int computeColumnsAdam7(int pass)
    • fillRowBuffer

      private void fillRowBuffer(int y, byte[] row, int offs)
    • getChunkName

      private static String getChunkName(int chunk)
      Creates a four-letter String from the parameter, an int value, supposed to be storing a chunk name.
      Returns:
      the chunk name
    • getFormatName

      public String getFormatName()
      Description copied from class: ImageCodec
      Returns the name of the file format supported by this codec. All classes extending ImageCodec must override this method. When overriding, leave out any words in a particular language so that this format name can be understood by everyone. Usually it is enough to return the format creator plus a typical abbreviation, e.g. Microsoft BMP or Portable Anymap (PNM).
      Specified by:
      getFormatName in class ImageCodec
      Returns:
      name of the file format supported by this codec
    • getMimeTypes

      public String[] getMimeTypes()
      Description copied from class: ImageCodec
      Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, or null if none are available.
      Specified by:
      getMimeTypes in class ImageCodec
      Returns:
      MIME type strings or null
    • getPaeth

      private static int getPaeth(byte l, byte u, byte nw)
    • inflateBytes

      private void inflateBytes(byte[] buffer, int numBytes) throws InvalidFileStructureException, IOException
      Throws:
      InvalidFileStructureException
      IOException
    • isLoadingSupported

      public boolean isLoadingSupported()
      Description copied from class: ImageCodec
      Returns if this codec is able to load images in the file format supported by this codec. If true is returned this does not necessarily mean that all files in this format can be read, but at least some.
      Specified by:
      isLoadingSupported in class ImageCodec
      Returns:
      if loading is supported
    • isSavingSupported

      public boolean isSavingSupported()
      Description copied from class: ImageCodec
      Returns if this codec is able to save images in the file format supported by this codec. If true is returned this does not necessarily mean that all types files in this format can be written, but at least some.
      Specified by:
      isSavingSupported in class ImageCodec
      Returns:
      if saving is supported
    • load

      Throws:
      InvalidFileStructureException
      IOException
      UnsupportedTypeException
      WrongFileFormatException
    • loadChunk

      Throws:
      InvalidFileStructureException
      IOException
      UnsupportedTypeException
    • loadImage

      private void loadImage(long chunkSize) throws InvalidFileStructureException, IOException, UnsupportedTypeException
      Load an image from the current position in the file. Assumes the last things read from input are an IDAT chunk type and its size, which is the sole argument of this method.
      Parameters:
      chunkSize - size of the IDAT chunk that was just read
      Throws:
      InvalidFileStructureException - if there are values in the PNG stream that make it invalid
      IOException - if there were I/O errors when reading
      UnsupportedTypeException - if something was encountered in the stream that is valid but not supported by this codec
    • loadImageHeader

      private void loadImageHeader() throws IOException, InvalidFileStructureException, UnsupportedTypeException
      Reads data from an IHDR chunk and initializes private fields with it. Does a lot of checking if read values are valid and supported by this class.
      Throws:
      IOException
      InvalidFileStructureException
      UnsupportedTypeException
    • loadImageInterlacedAdam7

      private void loadImageInterlacedAdam7() throws InvalidFileStructureException, IOException, UnsupportedTypeException
      Throws:
      InvalidFileStructureException
      IOException
      UnsupportedTypeException
    • loadImageNonInterlaced

      private void loadImageNonInterlaced() throws InvalidFileStructureException, IOException, UnsupportedTypeException
      Throws:
      InvalidFileStructureException
      IOException
      UnsupportedTypeException
    • loadPalette

      private void loadPalette(long numEntries) throws InvalidFileStructureException, IOException
      Throws:
      InvalidFileStructureException
      IOException
    • main

      public static void main(String[] args) throws Exception
      Throws:
      Exception
    • process

      Description copied from class: Operation
      This method does the actual work of the operation. It must be called after all parameters have been given to the operation object.
      Overrides:
      process in class Operation
      Throws:
      MissingParameterException - if any mandatory parameter was not given to the operation
      OperationFailedException
      InvalidFileStructureException
      UnsupportedTypeException
      WrongFileFormatException
    • readFilterType

      private int readFilterType() throws InvalidFileStructureException, IOException
      Throws:
      InvalidFileStructureException
      IOException
    • reverseFilter

      private void reverseFilter(int rowFilterType, byte[] buffer, byte[] prev, int numBytes) throws UnsupportedTypeException
      Throws:
      UnsupportedTypeException
    • save

      private void save() throws IOException
      Throws:
      IOException
    • saveChunk

      private void saveChunk(int chunkType, int chunkSize, byte[] data) throws IOException
      Throws:
      IOException
    • saveIendChunk

      private void saveIendChunk() throws IOException
      Throws:
      IOException
    • saveIhdrChunk

      private void saveIhdrChunk() throws IOException
      Throws:
      IOException
    • saveImage

      private void saveImage() throws IOException
      Throws:
      IOException
    • saveImageNonInterlaced

      private void saveImageNonInterlaced() throws IOException
      Throws:
      IOException
    • savePhysChunk

      private void savePhysChunk() throws IOException
      Throws:
      IOException
    • savePlteChunk

      private void savePlteChunk() throws IOException
      Throws:
      IOException
    • saveTextChunks

      private void saveTextChunks() throws IOException
      Throws:
      IOException
    • saveTimeChunk

      private void saveTimeChunk() throws IOException
      Throws:
      IOException
    • setCompressionLevel

      public void setCompressionLevel(int newLevel)
      Sets the compression level to be used with the underlying Deflater object which does the compression. If no value is specified, Deflater.DEFAULT_COMPRESSION is used.
      Parameters:
      newLevel - compression level, from 0 to 9, 0 being fastest and compressing worst and 9 offering highest compression and taking the most time
    • setCompressionStrategy

      public void setCompressionStrategy(int newStrategy)
      Sets the compression strategy to be used with the underlying Deflater object which does the compression. If no value is specified, Deflater.DEFAULT_STRATEGY is used.
      Parameters:
      newStrategy - one of Deflater's strategy values: Deflater.DEFAULT_STRATEGY, Deflater.FILTERED, Deflater.HUFFMAN_ONLY
    • setEncodingIdatSize

      public void setEncodingIdatSize(int newSize)
      Sets the size of IDAT chunks generated when encoding. If this method is never called, a default value of 32768 bytes (32 KB) is used. Note that a byte array of the size of the value you specify here is allocated, so make sure that you keep the value small enough to stay within a system's memory.

      Compressed image data is spread over several IDAT chunks by this codec. The length of the compressed data of a complete image is known only after the complete image has been encoded. With PNG, that length value has to be stored before the compressed data as a chunk size value. This codec is supposed to work with OutputStream objects, so seeking back to adjust the chunk size value of an IDAT chunk is not possible. That's why all data of a chunk is compressed into a memory buffer. Whenever the buffer gets full, it is written to output as an IDAT chunk.

      Note that the last IDAT chunk may be smaller than the size defined here.

      Parameters:
      newSize - size of encoding compressed data buffer
    • setFile

      public void setFile(String fileName, CodecMode codecMode) throws IOException, UnsupportedCodecModeException
      Description copied from class: ImageCodec
      Gives a file name and codec mode to the codec which will then try to create the corresponding I/O object. The default implementation in ImageCodec creates a DataInputStream object wrapped around a BufferedInputStream wrapped around a FileInputStream for CodecMode.LOAD. Similar for CodecMode.SAVE: a DataOutputStream around a BufferedOutputStream object around a FileOutputStream object. Codecs that need different I/O objects must override this method (some codecs may need random access and thus require a RandomAccessFile object).
      Overrides:
      setFile in class ImageCodec
      Parameters:
      fileName - name of the file to be used for loading or saving
      codecMode - defines whether file is to be used for loading or saving
      Throws:
      IOException
      UnsupportedCodecModeException
    • setModification

      public void setModification(Calendar time)
      Sets date and time of last modification of the image to be stored in a PNG stream when saving. Make sure the argument object has UTC as time zone (as demanded by the PNG specs). If you want the current time and date, use new GregorianCalendar(new SimpleTimeZone(0, "UTC")) as parameter for this method.
      Parameters:
      time - time of last modification of the image
    • skip

      private void skip(long num) throws IOException
      Skips a number of bytes in the input stream.
      Parameters:
      num - number of bytes to be skipped
      Throws:
      IOException - if there were I/O errors
    • storeInterlacedAdam7

      private void storeInterlacedAdam7(int pass, int y, byte[] buffer)
    • storeInterlacedAdam7Gray

      private void storeInterlacedAdam7Gray(int pass, int y, byte[] buffer)
    • storeInterlacedAdam7GrayAlpha

      private void storeInterlacedAdam7GrayAlpha(int pass, int y, byte[] buffer)
    • storeInterlacedAdam7Indexed

      private void storeInterlacedAdam7Indexed(int pass, int y, byte[] buffer)
    • storeInterlacedAdam7Rgb

      private void storeInterlacedAdam7Rgb(int pass, int y, byte[] buffer)
    • storeInterlacedAdam7RgbAlpha

      private void storeInterlacedAdam7RgbAlpha(int pass, int y, byte[] buffer)
    • storeNonInterlaced

      private void storeNonInterlaced(int y, byte[] buffer)
    • storeNonInterlacedGray

      private void storeNonInterlacedGray(int y, byte[] buffer)
    • storeNonInterlacedGrayAlpha

      private void storeNonInterlacedGrayAlpha(int y, byte[] buffer)
    • storeNonInterlacedIndexed

      private void storeNonInterlacedIndexed(int y, byte[] buffer)
    • storeNonInterlacedRgb

      private void storeNonInterlacedRgb(int y, byte[] buffer)
    • storeNonInterlacedRgbAlpha

      private void storeNonInterlacedRgbAlpha(int y, byte[] buffer)
    • suggestFileExtension

      public String suggestFileExtension(PixelImage image)
      Description copied from class: ImageCodec
      Attempts to suggest a filename extension. The type of the argument image will be taken into consideration, although this will be necessary for some file formats only (as an example, PNM has different extensions for different image types, see PNMCodec). This default implementation always returns null.
      Overrides:
      suggestFileExtension in class ImageCodec
      Parameters:
      image - the image that is to be written to a file
      Returns:
      the file extension, including a leading dot, or null if no file extension can be recommended