Package net.sourceforge.jiu.codecs
Class PNGCodec
java.lang.Object
net.sourceforge.jiu.ops.Operation
net.sourceforge.jiu.codecs.ImageCodec
net.sourceforge.jiu.codecs.PNGCodec
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 useImageLoader 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
- Grayscale 1 bit streams are loaded as
BilevelImageobjects, 2, 4 and 8 bit streams asGray8Imageand 16 bit asGray16Imageobjects. - Indexed 1, 2, 4 and 8 bit streams are all loaded as
Paletted8Image. - RGB truecolor 24 bit streams are loaded as
RGB24Image, 48 bit streams asRGB48Imageobjects.
Saving
BilevelImageobjects are stored as grayscale 1 bit PNG streams.Paletted8Imageobjects 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.Gray8Imageobjects are stored as 8 bit grayscale PNG streams.Gray16Imageobjects are stored as 16 bit grayscale PNG streams.RGB24Imageobjects are stored as 24 bit RGB truecolor PNG streams.RGB48Imageobjects 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 withImageCodec.setBounds(int, int, int, int), the codec will only load or save
part of an image.
Metadata
Loading
- Physical resolution information is loaded from
pHYschunks. UseImageCodec.getDpiX()andImageCodec.getDpiY()to retrieve that information. after the call toprocess(). - Textual comments are read from
tEXtchunks and can be retrieved withImageCodec.getComment(int)after the call toprocess().
Saving
- Physical resolution information (specified with
ImageCodec.setDpi(int, int)) is stored in apHYschunk. - Textual comments (specified with
ImageCodec.appendComment(java.lang.String)) are stored astEXtchunks. The keyword used isComment. Each of theImageCodec.getNumComments()is stored in a chunk of its own. - Time of modification is stored in a
tIMEchunk. UsesetModification(Calendar)to give a point in time to this codec.
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 Summary
FieldsModifier and TypeFieldDescriptionprivate final int[]private final int[]private final int[]private final intprivate final int[]private booleanprivate intprivate byte[][]private CheckedInputStreamprivate CRC32private final intprivate final intprivate final intprivate final intprivate final intprivate final intprivate final intprivate final intprivate final intprivate intprivate final intprivate final intprivate final intprivate final intprivate final intprivate final intprivate intprivate final intprivate intprivate intprivate final intprivate intprivate intprivate intprivate final intprivate final intprivate final intprivate final intprivate final intprivate final intprivate intprivate booleanprivate intprivate IntegerImageprivate DataInputStreamprivate InflaterInputStreamprivate intprivate final intprivate final intprivate final byte[]private final intprivate Calendarprivate intprivate DataOutputprivate Paletteprivate intprivate intprivate int -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate voidAllocates the right image to private fieldimage, taking into consideration the fields width, height, precision and colorType.private voidprivate intcomputeBytesPerRow(int numPixels) Computes a number of bytes for a given number of pixels, regarding precision and availability of an alpha channel.private intcomputeColumnsAdam7(int pass) private voidfillRowBuffer(int y, byte[] row, int offs) private static StringgetChunkName(int chunk) Creates a four-letter String from the parameter, anintvalue, supposed to be storing a chunk name.Returns the name of the file format supported by this codec.String[]Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, ornullif none are available.private static intgetPaeth(byte l, byte u, byte nw) private voidinflateBytes(byte[] buffer, int numBytes) booleanReturns if this codec is able to load images in the file format supported by this codec.booleanReturns if this codec is able to save images in the file format supported by this codec.private voidload()private voidprivate voidloadImage(long chunkSize) Load an image from the current position in the file.private voidReads data from an IHDR chunk and initializes private fields with it.private voidprivate voidprivate voidloadPalette(long numEntries) static voidvoidprocess()This method does the actual work of the operation.private intprivate voidreverseFilter(int rowFilterType, byte[] buffer, byte[] prev, int numBytes) private voidsave()private voidsaveChunk(int chunkType, int chunkSize, byte[] data) private voidprivate voidprivate voidprivate voidprivate voidprivate voidprivate voidprivate voidvoidsetCompressionLevel(int newLevel) Sets the compression level to be used with the underlyingDeflaterobject which does the compression.voidsetCompressionStrategy(int newStrategy) Sets the compression strategy to be used with the underlyingDeflaterobject which does the compression.voidsetEncodingIdatSize(int newSize) Sets the size of IDAT chunks generated when encoding.voidGives a file name and codec mode to the codec which will then try to create the corresponding I/O object.voidsetModification(Calendar time) Sets date and time of last modification of the image to be stored in a PNG stream when saving.private voidskip(long num) Skips a number of bytes in the input stream.private voidstoreInterlacedAdam7(int pass, int y, byte[] buffer) private voidstoreInterlacedAdam7Gray(int pass, int y, byte[] buffer) private voidstoreInterlacedAdam7GrayAlpha(int pass, int y, byte[] buffer) private voidstoreInterlacedAdam7Indexed(int pass, int y, byte[] buffer) private voidstoreInterlacedAdam7Rgb(int pass, int y, byte[] buffer) private voidstoreInterlacedAdam7RgbAlpha(int pass, int y, byte[] buffer) private voidstoreNonInterlaced(int y, byte[] buffer) private voidstoreNonInterlacedGray(int y, byte[] buffer) private voidstoreNonInterlacedGrayAlpha(int y, byte[] buffer) private voidstoreNonInterlacedIndexed(int y, byte[] buffer) private voidstoreNonInterlacedRgb(int y, byte[] buffer) private voidstoreNonInterlacedRgbAlpha(int y, byte[] buffer) suggestFileExtension(PixelImage image) Attempts to suggest a filename extension.Methods inherited from class net.sourceforge.jiu.codecs.ImageCodec
appendComment, checkBounds, checkImageResolution, close, getBoundsHeight, getBoundsWidth, getBoundsX1, getBoundsX2, getBoundsY1, getBoundsY2, getComment, getDataInput, getDataOutput, getDpiX, getDpiY, getFileExtensions, getImage, getImageIndex, getInputAsDataInput, getInputStream, getMode, getNumComments, getOutputAsDataOutput, getOutputStream, getRandomAccessFile, hasBounds, initModeFromIOObjects, isRowRequired, isTileRequired, removeAllComments, removeBounds, setBounds, setBoundsIfNecessary, setDataInput, setDataOutput, setDpi, setFile, setImage, setImageIndex, setInputStream, setOutputStream, setRandomAccessFileMethods inherited from class net.sourceforge.jiu.ops.Operation
addProgressListener, addProgressListeners, getAbort, removeProgressListener, setAbort, setProgress, setProgress
-
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
-
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
-
in
-
infl
-
interlaceType
private int interlaceType -
modification
-
numChannels
private int numChannels -
out
-
palette
-
precision
private int precision -
previousBufferIndex
private int previousBufferIndex -
width
private int width
-
-
Constructor Details
-
PNGCodec
public PNGCodec()
-
-
Method Details
-
allocateImage
Allocates the right image to private fieldimage, 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. -
checkColorTypeAndPrecision
Checks valuesprecisionandcolorType. A lot of combinations possibly found in an IHDR chunk are invalid. Also initializesalphaandnumChannels.- 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
Creates a four-letter String from the parameter, anintvalue, supposed to be storing a chunk name.- Returns:
- the chunk name
-
getFormatName
Description copied from class:ImageCodecReturns the name of the file format supported by this codec. All classes extendingImageCodecmust 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 BMPorPortable Anymap (PNM).- Specified by:
getFormatNamein classImageCodec- Returns:
- name of the file format supported by this codec
-
getMimeTypes
Description copied from class:ImageCodecReturn the MIME (Multipurpose Internet Mail Extensions) type strings for this format, ornullif none are available.- Specified by:
getMimeTypesin classImageCodec- 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 -
isLoadingSupported
public boolean isLoadingSupported()Description copied from class:ImageCodecReturns if this codec is able to load images in the file format supported by this codec. Iftrueis returned this does not necessarily mean that all files in this format can be read, but at least some.- Specified by:
isLoadingSupportedin classImageCodec- Returns:
- if loading is supported
-
isSavingSupported
public boolean isSavingSupported()Description copied from class:ImageCodecReturns if this codec is able to save images in the file format supported by this codec. Iftrueis returned this does not necessarily mean that all types files in this format can be written, but at least some.- Specified by:
isSavingSupportedin classImageCodec- Returns:
- if saving is supported
-
load
private void load() throws InvalidFileStructureException, IOException, UnsupportedTypeException, WrongFileFormatException -
loadChunk
private void 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 invalidIOException- if there were I/O errors when readingUnsupportedTypeException- if something was encountered in the stream that is valid but not supported by this codec
-
loadImageHeader
private void loadImageHeader() throws IOException, InvalidFileStructureException, UnsupportedTypeExceptionReads 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. -
loadImageInterlacedAdam7
private void loadImageInterlacedAdam7() throws InvalidFileStructureException, IOException, UnsupportedTypeException -
loadImageNonInterlaced
private void loadImageNonInterlaced() throws InvalidFileStructureException, IOException, UnsupportedTypeException -
loadPalette
-
main
- Throws:
Exception
-
process
public void process() throws InvalidFileStructureException, MissingParameterException, OperationFailedException, UnsupportedTypeException, WrongFileFormatExceptionDescription copied from class:OperationThis method does the actual work of the operation. It must be called after all parameters have been given to the operation object.- Overrides:
processin classOperation- Throws:
MissingParameterException- if any mandatory parameter was not given to the operationWrongParameterException- if at least one of the input parameters was not initialized appropriately (values out of the valid interval, etc.)OperationFailedExceptionInvalidFileStructureExceptionUnsupportedTypeExceptionWrongFileFormatException
-
readFilterType
-
reverseFilter
private void reverseFilter(int rowFilterType, byte[] buffer, byte[] prev, int numBytes) throws UnsupportedTypeException - Throws:
UnsupportedTypeException
-
save
- Throws:
IOException
-
saveChunk
- Throws:
IOException
-
saveIendChunk
- Throws:
IOException
-
saveIhdrChunk
- Throws:
IOException
-
saveImage
- Throws:
IOException
-
saveImageNonInterlaced
- Throws:
IOException
-
savePhysChunk
- Throws:
IOException
-
savePlteChunk
- Throws:
IOException
-
saveTextChunks
- Throws:
IOException
-
saveTimeChunk
- Throws:
IOException
-
setCompressionLevel
public void setCompressionLevel(int newLevel) Sets the compression level to be used with the underlyingDeflaterobject which does the compression. If no value is specified,Deflater.DEFAULT_COMPRESSIONis 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 underlyingDeflaterobject which does the compression. If no value is specified,Deflater.DEFAULT_STRATEGYis 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
OutputStreamobjects, 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:ImageCodecGives 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:
setFilein classImageCodec- Parameters:
fileName- name of the file to be used for loading or savingcodecMode- defines whether file is to be used for loading or saving- Throws:
IOExceptionUnsupportedCodecModeException
-
setModification
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, usenew GregorianCalendar(new SimpleTimeZone(0, "UTC"))as parameter for this method.- Parameters:
time- time of last modification of the image
-
skip
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
Description copied from class:ImageCodecAttempts 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, seePNMCodec). This default implementation always returnsnull.- Overrides:
suggestFileExtensionin classImageCodec- Parameters:
image- the image that is to be written to a file- Returns:
- the file extension, including a leading dot, or
nullif no file extension can be recommended
-