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
BilevelImage
objects, 2, 4 and 8 bit streams asGray8Image
and 16 bit asGray16Image
objects. - 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 asRGB48Image
objects.
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 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
pHYs
chunks. UseImageCodec.getDpiX()
andImageCodec.getDpiY()
to retrieve that information. after the call toprocess()
. - Textual comments are read from
tEXt
chunks and can be retrieved withImageCodec.getComment(int)
after the call toprocess()
.
Saving
- Physical resolution information (specified with
ImageCodec.setDpi(int, int)
) is stored in apHYs
chunk. - Textual comments (specified with
ImageCodec.appendComment(java.lang.String)
) are stored astEXt
chunks. The keyword used isComment
. Each of theImageCodec.getNumComments()
is stored in a chunk of its own. - Time of modification is stored in a
tIME
chunk. 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 int
private final int[]
private boolean
private int
private byte[][]
private CheckedInputStream
private CRC32
private final int
private final int
private final int
private final int
private final int
private final int
private final int
private final int
private final int
private int
private final int
private final int
private final int
private final int
private final int
private final int
private int
private final int
private int
private int
private final int
private int
private int
private int
private final int
private final int
private final int
private final int
private final int
private final int
private int
private boolean
private int
private IntegerImage
private DataInputStream
private InflaterInputStream
private int
private final int
private final int
private final byte[]
private final int
private Calendar
private int
private DataOutput
private Palette
private int
private int
private int
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionprivate void
Allocates the right image to private fieldimage
, taking into consideration the fields width, height, precision and colorType.private void
private int
computeBytesPerRow
(int numPixels) Computes a number of bytes for a given number of pixels, regarding precision and availability of an alpha channel.private int
computeColumnsAdam7
(int pass) private void
fillRowBuffer
(int y, byte[] row, int offs) private static String
getChunkName
(int chunk) Creates a four-letter String from the parameter, anint
value, 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, ornull
if none are available.private static int
getPaeth
(byte l, byte u, byte nw) private void
inflateBytes
(byte[] buffer, int numBytes) boolean
Returns if this codec is able to load images in the file format supported by this codec.boolean
Returns if this codec is able to save images in the file format supported by this codec.private void
load()
private void
private void
loadImage
(long chunkSize) Load an image from the current position in the file.private void
Reads data from an IHDR chunk and initializes private fields with it.private void
private void
private void
loadPalette
(long numEntries) static void
void
process()
This method does the actual work of the operation.private int
private void
reverseFilter
(int rowFilterType, byte[] buffer, byte[] prev, int numBytes) private void
save()
private void
saveChunk
(int chunkType, int chunkSize, byte[] data) private void
private void
private void
private void
private void
private void
private void
private void
void
setCompressionLevel
(int newLevel) Sets the compression level to be used with the underlyingDeflater
object which does the compression.void
setCompressionStrategy
(int newStrategy) Sets the compression strategy to be used with the underlyingDeflater
object which does the compression.void
setEncodingIdatSize
(int newSize) Sets the size of IDAT chunks generated when encoding.void
Gives a file name and codec mode to the codec which will then try to create the corresponding I/O object.void
setModification
(Calendar time) Sets date and time of last modification of the image to be stored in a PNG stream when saving.private void
skip
(long num) Skips a number of bytes in the input stream.private void
storeInterlacedAdam7
(int pass, int y, byte[] buffer) private void
storeInterlacedAdam7Gray
(int pass, int y, byte[] buffer) private void
storeInterlacedAdam7GrayAlpha
(int pass, int y, byte[] buffer) private void
storeInterlacedAdam7Indexed
(int pass, int y, byte[] buffer) private void
storeInterlacedAdam7Rgb
(int pass, int y, byte[] buffer) private void
storeInterlacedAdam7RgbAlpha
(int pass, int y, byte[] buffer) private void
storeNonInterlaced
(int y, byte[] buffer) private void
storeNonInterlacedGray
(int y, byte[] buffer) private void
storeNonInterlacedGrayAlpha
(int y, byte[] buffer) private void
storeNonInterlacedIndexed
(int y, byte[] buffer) private void
storeNonInterlacedRgb
(int y, byte[] buffer) private void
storeNonInterlacedRgbAlpha
(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, setRandomAccessFile
Methods 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 valuesprecision
andcolorType
. A lot of combinations possibly found in an IHDR chunk are invalid. Also initializesalpha
andnumChannels
.- 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, anint
value, supposed to be storing a chunk name.- Returns:
- the chunk name
-
getFormatName
Description copied from class:ImageCodec
Returns the name of the file format supported by this codec. All classes extendingImageCodec
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
orPortable Anymap (PNM)
.- Specified by:
getFormatName
in classImageCodec
- Returns:
- name of the file format supported by this codec
-
getMimeTypes
Description copied from class:ImageCodec
Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, ornull
if none are available.- Specified by:
getMimeTypes
in 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:ImageCodec
Returns if this codec is able to load images in the file format supported by this codec. Iftrue
is returned this does not necessarily mean that all files in this format can be read, but at least some.- Specified by:
isLoadingSupported
in classImageCodec
- 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. Iftrue
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 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: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 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.)OperationFailedException
InvalidFileStructureException
UnsupportedTypeException
WrongFileFormatException
-
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 underlyingDeflater
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 underlyingDeflater
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 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:
IOException
UnsupportedCodecModeException
-
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: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, seePNMCodec
). This default implementation always returnsnull
.- Overrides:
suggestFileExtension
in classImageCodec
- 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
-