Package net.sourceforge.jiu.codecs

# Class ImageCodec

java.lang.Object
net.sourceforge.jiu.ops.Operation
net.sourceforge.jiu.codecs.ImageCodec

Direct Known Subclasses:
  `BMPCodec`, `GIFCodec`, `IFFCodec`, `JPEGCodec`, `PalmCodec`, `PCDCodec`, `PNGCodec`, `PNMCodec`, `PSDCodec`, `RASCodec`, `TIFFCodec`

public abstract class ImageCodec extends Operation
The base class for image codecs, operations to read images from or write them to streams. A codec should support one file format only. The word codec is derived from enCOder DECoder.

### Usage

The codecs differ quite a bit in what they support. But here are two code snippets that demonstrate how to do loading and saving in general.

#### Load image

     ImageCodec codec = new BMPCodec(); // BMPCodec is just an example
     codec.setFile("image.bmp", CodecMode.LOAD);
     codec.process();
     PixelImage image = codec.getImage();

#### Save image

     PixelImage image = ...; // the image to be saved
     ImageCodec codec = new BMPCodec(); // BMPCodec is just an example
     codec.setFile("image.bmp", CodecMode.SAVE);
     codec.setImage(image);
     codec.process();

### I/O objects

There are several set and get methods for I/O objects, including DataInput, DataOutput, InputStream, OutputStream and RandomAccessFile. If you are just using the codec (and not developing one) make it easier for yourself and use `setFile(String, CodecMode)`. That way the picking of the right type of I/O class and the creation of a buffered stream wrapper is done automatically.

Codecs have different requirements concerning I/O objects. If an image is to be loaded, it's enough for some formats to linearly read from an `InputStream` to load the image. However, some formats (like TIFF) require random access.

When implementing a codec, take care that as many I/O classes as possible can be used. If possible, call `getInputAsDataInput()` when loading and `getOutputAsDataOutput()` when saving. That way, input / output streams, RandomAccessFiles and arbitrary DataInput / DataOutput objects can be used.

### Mode

Codecs can be used to save images or load them, or both. As was g; by default, no mode (of enumeration type `CodecMode`) is specified and `getMode()` returns `null`. Mode only has two possible values, `CodecMode.LOAD` and `CodecMode.SAVE`. In some cases, the codec can find out whether to load or save from the I/O objects that were given to it; if it has an input stream, something must be loaded, if it has an output stream, something is to be saved. If a codec demands a `RandomAccessFile`, there is no way to find out the mode automatically, that is why `setRandomAccessFile(java.io.RandomAccessFile, net.sourceforge.jiu.codecs.CodecMode)` also has an argument of type `CodecMode`.

Bounds; to load or save only part of an image. Defining bounds is optional; by default, the complete image is loaded or saved (no bounds). Using `setBounds(int, int, int, int)`, one can specify the rectangle which will be loaded or saved.

PixelImage object; get and set methods for the image which is to be loaded or saved. If an image is to be loaded, a PixelImage object can optionally be specified so that the image will be written to that object; image type and resolution must of course match the image from input. Normally, the codec will create the appropriate image object itself. If an image is to be saved, an image object must be provided, otherwise there is nothing to do.

Image index; the index of the image that is to be loaded (int value, default is 0). For image formats that support more than one image in one stream, the index of the image to be loaded (zero-based) can be specified using `setImageIndex(int)`.

### Textual comments

Some file formats allow for the inclusion of textual comments, to store a description, creator, copyright owner or anything else within the image file without actually drawing that text on the image itself. Some codecs support reading and writing of comments.

### Other methods

Each file format must be able to return its name (`getFormatName()`) and file extensions that are typical for it (`getFileExtensions()`).

A related method suggests a file extension for a given PixelImage object (`suggestFileExtension(PixelImage)`). That method need not be implemented, the default version returns simply `null`. However, it is encouraged that codec implementors provide this method as well. Most file formats only have one typical extension (e. g. `.bmp`). However, for a file format like PNM, the extension depends on the image type (a grayscale image would end in `.pgm`, a color image in `.ppm`).

Author:
  Marco Schmidt

## Field Summary

Fields
Modifier and Type
Field
Description
`private boolean`
`boundsAvail`
`private int`
`boundsHeight`
`private int`
`boundsWidth`
`private int`
`boundsX1`
`private int`
`boundsX2`
`private int`
`boundsY1`
`private int`
`boundsY2`
`private Vector`
`comments`
`private DataInput`
`din`
`private DataOutput`
`dout`
`private int`
`dpiX`
`private int`
`dpiY`
`private PixelImage`
`image`
`private int`
`imageIndex`
`private InputStream`
`in`
`private CodecMode`
`mode`
`private OutputStream`
`out`
`private RandomAccessFile`
`raf`

## Constructor Summary

Constructors
Constructor
Description
`ImageCodec()`
This constructor will be called by descendants.

## Method Summary

Modifier and Type
Method
Description
`void`
`appendComment(String comment)`
Appends a comment to the internal list of comments.
`void`
`checkBounds(int width, int height)`
If bounds were defined for this codec, this method tests if the bounds rectangle fits into the rectangle `(0, 0) / (width - 1, height - 1)`.
`void`
`checkImageResolution()`
If an image object was provided to be used for loading via `setImage(net.sourceforge.jiu.data.PixelImage)`, this method checks if its resolution is the same as the bounds' resolution.
`void`
`close()`
Calls the close method of all input and output I/O objects that were given to this object.
`int`
`getBoundsHeight()`
Returns the height of the rectangle specified by bounds.
`int`
`getBoundsWidth()`
Returns the width of the rectangle specified by bounds.
`int`
`getBoundsX1()`
Returns x coordinate of the upper left corner of the bounds.
`int`
`getBoundsX2()`
Returns x coordinate of the lower right corner of the bounds.
`int`
`getBoundsY1()`
Returns y coordinate of the upper left corner of the bounds.
`int`
`getBoundsY2()`
Returns y coordinate of the lower right corner of the bounds.
`String`
`getComment(int index)`
Returns a comment from the internal list of comments.
`DataInput`
`getDataInput()`
Returns a `DataInput` object if one was provided via `setDataInput(DataInput)` or `null` otherwise.
`DataOutput`
`getDataOutput()`
Returns a `DataOutput` object if one was provided via `setDataOutput(DataOutput)` or `null` otherwise.
`int`
`getDpiX()`
Returns the horizontal physical resolution of the image associated with this codec.
`int`
`getDpiY()`
Returns the vertical physical resolution of the image associated with this codec.
`String[]`
`getFileExtensions()`
Returns all file extensions that are typical for this file format.
`abstract String`
`getFormatName()`
Returns the name of the file format supported by this codec.
`PixelImage`
`getImage()`
Returns the image object stored in this codec.
`int`
`getImageIndex()`
Returns the zero-based index of the image to be loaded.
`DataInput`
`getInputAsDataInput()`
Returns a `DataInput` object if one was specified using `setDataInput(DataInput)`, or creates a `DataInputStream` if an `InputStream` was specified, or returns a `RandomAccessFile` if one was specified (RandomAccessFile implements DataInput).
`InputStream`
`getInputStream()`
Returns an `InputStream` object that was given to this codec via `setInputStream(InputStream)` (or `null` otherwise).
`abstract String[]`
`getMimeTypes()`
Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, or `null` if none are available.
`CodecMode`
`getMode()`
Returns the mode this codec is in.
`int`
`getNumComments()`
Returns the current number of comments in the internal comment list.
`DataOutput`
`getOutputAsDataOutput()`
Attempts to return an output object as a `DataOutput` object.
`OutputStream`
`getOutputStream()`
Returns an `OutputStream` object that was given to this codec via `setOutputStream(OutputStream)` (or `null` otherwise).
`RandomAccessFile`
`getRandomAccessFile()`
Returns a `RandomAccessFile` object that was given to this codec via `setRandomAccessFile(RandomAccessFile, CodecMode)` (or `null` otherwise).
`boolean`
`hasBounds()`
Returns if bounds have been specified.
`protected void`
`initModeFromIOObjects()`
`abstract boolean`
`isLoadingSupported()`
Returns if this codec is able to load images in the file format supported by this codec.
`boolean`
`isRowRequired(int row)`
Returns if an image row given by its number (zero-based) must be loaded in the context of the current bounds.
`abstract boolean`
`isSavingSupported()`
Returns if this codec is able to save images in the file format supported by this codec.
`boolean`
`isTileRequired(int x1, int y1, int x2, int y2)`
Returns if the tile formed by the argument coordinates form a rectangle that overlaps with the bounds.
`void`
`removeAllComments()`
Removes all entries from the internal list of comments.
`void`
`removeBounds()`
If bounds were set using `setBounds(int, int, int, int)`, these bounds are no longer regarded after the call to this method.
`void`
`setBounds(int x1, int y1, int x2, int y2)`
Sets the bounds of a rectangular part of the image that is to be loaded or saved, instead of the complete image.
`void`
`setBoundsIfNecessary(int width, int height)`
If no bounds have been set (`hasBounds()` returns `false`), this method will set the bounds to `0, 0, width - 1, height - 1`.
`void`
`setDataInput(DataInput dataInput)`
Specifies a DataInput object to be used for loading.
`void`
`setDataOutput(DataOutput dataOutput)`
Sets a `DataOutput` object to be used for saving an image.
`void`
`setDpi(int horizontalDpi, int verticalDpi)`
Sets the DPI values to be stored in the file to the argument values.
`void`
`setFile(File file, CodecMode codecMode)`
Gives a File object and a codec mode to this codec and attempts to initialize the appropriate I/O objects.
`void`
`setFile(String fileName, CodecMode codecMode)`
Gives a file name and codec mode to the codec which will then try to create the corresponding I/O object.
`void`
`setImage(PixelImage img)`
Give an image to this codec to be used for loading an image into it or saving the image.
`void`
`setImageIndex(int index)`
Sets the index of the image to be loaded to the argument value (which must be zero or larger).
`void`
`setInputStream(InputStream inputStream)`
An `InputStream` can be given to this codec using this method.
`void`
`setOutputStream(OutputStream outputStream)`
A method to give an `OutputStream` to this codec to be used for saving an image.
`void`
`setRandomAccessFile(RandomAccessFile randomAccessFile, CodecMode codecMode)`
A method to give a `RandomAccessFile` to this codec to be used for loading or saving an image.
`String`
`suggestFileExtension(PixelImage image)`
Attempts to suggest a filename extension.

### Methods inherited from class net.sourceforge.jiu.ops.Operation

`addProgressListener, addProgressListeners, getAbort, process, removeProgressListener, setAbort, setProgress, setProgress`

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Field Details

### boundsX1

private int boundsX1

### boundsY1

private int boundsY1

### boundsX2

private int boundsX2

### boundsY2

private int boundsY2

### boundsAvail

private boolean boundsAvail

### boundsWidth

private int boundsWidth

### boundsHeight

private int boundsHeight

### comments

private Vector comments

### dpiX

private int dpiX

### dpiY

private int dpiY

### din

private DataInput din

### dout

private DataOutput dout

### image

private PixelImage image

### imageIndex

private int imageIndex

### in

private InputStream in

### mode

private CodecMode mode

### out

private OutputStream out

### raf

private RandomAccessFile raf

## Constructor Details

### ImageCodec

public ImageCodec()
This constructor will be called by descendants. The bounds state is initialized to no bounds.

## Method Details

### appendComment

public void appendComment(String comment)
Appends a comment to the internal list of comments. If the argument comment is non-null, it will be added to the internal list of comment strings.

Parameters:
  `comment` - the comment to be added

### checkBounds

public void checkBounds(int width, int height) throws WrongParameterException
If bounds were defined for this codec, this method tests if the bounds rectangle fits into the rectangle `(0, 0) / (width - 1, height - 1)`. If the bounds are incorrect, a `WrongParameterException` is thrown, otherwise nothing happens. To be used within codecs that support the bounds concept.

Throws:
  `WrongParameterException`

### checkImageResolution

public void checkImageResolution() throws WrongParameterException
If an image object was provided to be used for loading via `setImage(net.sourceforge.jiu.data.PixelImage)`, this method checks if its resolution is the same as the bounds' resolution. If the two differ, a `WrongParameterException` is thrown.

Throws:
  `WrongParameterException` - if image resolution and bounds dimension differ

### close

public void close()
Calls the close method of all input and output I/O objects that were given to this object. Catches and ignores any IOException objects that may be thrown in the process. Note that not all I/O objects have a close method (e.g. `DataInput` and `DataOutput` have not).

### getBoundsX1

public int getBoundsX1()
Returns x coordinate of the upper left corner of the bounds. Bounds must have been specified using `setBounds(int, int, int, int)`, otherwise the return value is undefined.

Returns:
  x coordinate of the upper left corner of the bounds

### getBoundsX2

public int getBoundsX2()
Returns x coordinate of the lower right corner of the bounds. Bounds must have been specified using `setBounds(int, int, int, int)`, otherwise the return value is undefined.

Returns:
  x coordinate of the lower right corner of the bounds

### getBoundsY1

public int getBoundsY1()
Returns y coordinate of the upper left corner of the bounds. Bounds must have been specified using `setBounds(int, int, int, int)`, otherwise the return value is undefined.

Returns:
  y coordinate of the upper left corner of the bounds

### getBoundsY2

public int getBoundsY2()
Returns y coordinate of the lower right corner of the bounds. Bounds must have been specified using `setBounds(int, int, int, int)`, otherwise the return value is undefined.

Returns:
  y coordinate of the lower right corner of the bounds

### getBoundsHeight

public int getBoundsHeight()
Returns the height of the rectangle specified by bounds. Bounds must have been specified using `setBounds(int, int, int, int)`, otherwise the return value is undefined. This equals `getBoundsY2()` - `getBoundsY1()` + 1.

Returns:
  height of bounds rectangle

### getBoundsWidth

public int getBoundsWidth()
Returns the width of the rectangle specified by bounds. Bounds must have been specified using `setBounds(int, int, int, int)`, otherwise the return value is undefined. This equals `getBoundsX2()` - `getBoundsX1()` + 1.

Returns:
  width of bounds rectangle

### getComment

public String getComment(int index)
Returns a comment from the internal list of comments.

Parameters:
  `index` - the index of the comment to be returned, must be from `0` to `getNumComments()``- 1`; if this is not the case, `null` will be returned
See Also:
  - `getNumComments()`
  - `appendComment(java.lang.String)`
  - `removeAllComments()`

### getDataInput

public DataInput getDataInput()
Returns a `DataInput` object if one was provided via `setDataInput(DataInput)` or `null` otherwise.

Returns:
  the DataInput object

### getDataOutput

public DataOutput getDataOutput()
Returns a `DataOutput` object if one was provided via `setDataOutput(DataOutput)` or `null` otherwise.

Returns:
  the DataInput object

### getDpiX

public int getDpiX()
Returns the horizontal physical resolution of the image associated with this codec. This resolution value was either retrieved from an image file or set via `setDpi(int, int)`.

Returns:
  horizontal physical resolution in dpi
See Also:
  - `getDpiY()`

### getDpiY

public int getDpiY()
Returns the vertical physical resolution of the image associated with this codec. This resolution value was either retrieved from an image file or set via `setDpi(int, int)`.

Returns:
  horizontal physical resolution in dpi
See Also:
  - `getDpiX()`

### getFileExtensions

public String[] getFileExtensions()
Returns all file extensions that are typical for this file format. The default implementation in ImageCodec returns `null`. The file extension strings should include a leading dot and are supposed to be lower case (if that is allowed for the given file format). Example: `{".jpg", ".jpeg"}` for the JPEG file format.

Returns:
  String array with typical file extensions

### getFormatName

public abstract String getFormatName()
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)`.

Returns:
  name of the file format supported by this codec

### getImage

public PixelImage getImage()
Returns the image object stored in this codec. This is either an image given to this object via `setImage(PixelImage)` or it was created by the codec itself during a loading operation.

Returns:
  PixelImage object stored in this codec

### getImageIndex

public int getImageIndex()
Returns the zero-based index of the image to be loaded. Default is zero.

Returns:
  zero-based image index value

### getInputAsDataInput

public DataInput getInputAsDataInput()
Returns a `DataInput` object if one was specified using `setDataInput(DataInput)`, or creates a `DataInputStream` if an `InputStream` was specified, or returns a `RandomAccessFile` if one was specified (RandomAccessFile implements DataInput). If neither of those has been given to this object, `null` is returned.

Returns:
  DataInput object or `null`

### getInputStream

public InputStream getInputStream()
Returns an `InputStream` object that was given to this codec via `setInputStream(InputStream)` (or `null` otherwise).

Returns:
  InputStream object

### getMimeTypes

public abstract String[] getMimeTypes()
Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, or `null` if none are available.

Returns:
  MIME type strings or null

### getMode

public CodecMode getMode()
Returns the mode this codec is in. Can be `null`, so that the codec will have to find out itself what to do.

Returns:
  codec mode (load or save)

### getNumComments

public int getNumComments()
Returns the current number of comments in the internal comment list.

Returns:
  number of comments in the internal comment list

### getOutputAsDataOutput

public DataOutput getOutputAsDataOutput()
Attempts to return an output object as a `DataOutput` object.

Returns:
  a DataOutput object or null if that was not possible

### getOutputStream

public OutputStream getOutputStream()
Returns an `OutputStream` object that was given to this codec via `setOutputStream(OutputStream)` (or `null` otherwise).

Returns:
  OutputStream object

### getRandomAccessFile

public RandomAccessFile getRandomAccessFile()
Returns a `RandomAccessFile` object that was given to this codec via `setRandomAccessFile(RandomAccessFile, CodecMode)` (or `null` otherwise).

Returns:
  RandomAccessFile object

### hasBounds

public boolean hasBounds()
Returns if bounds have been specified.

Returns:
  if bounds have been specified
See Also:
  - `removeBounds()`
  - `setBounds(int, int, int, int)`

### initModeFromIOObjects

protected void initModeFromIOObjects() throws MissingParameterException

Throws:
  `MissingParameterException`

### isLoadingSupported

public abstract boolean isLoadingSupported()
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.

Returns:
  if loading is supported

### isSavingSupported

public abstract boolean isSavingSupported()
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.

Returns:
  if saving is supported

### isRowRequired

public boolean isRowRequired(int row)
Returns if an image row given by its number (zero-based) must be loaded in the context of the current bounds.

Example: if vertical bounds have been set to 34 and 37, image rows 34 to 37 as arguments to this method would result in `true`, anything else (e.g. 12 or 45) would result in `false`.

Parameters:
  `row` - the number of the row to be checked
Returns:
  if row must be loaded, regarding the current bounds

### isTileRequired

public boolean isTileRequired(int x1, int y1, int x2, int y2)
Returns if the tile formed by the argument coordinates form a rectangle that overlaps with the bounds. If no bounds were defined, returns `true`.

Parameters:
  `x1` -
  `y1` -
  `x2` -
  `y2` -
Returns:
  if the argument tile is required

### removeAllComments

public void removeAllComments()
Removes all entries from the internal list of comments.

### removeBounds

public void removeBounds()
If bounds were set using `setBounds(int, int, int, int)`, these bounds are no longer regarded after the call to this method.

### setBounds

public void setBounds(int x1, int y1, int x2, int y2)
Sets the bounds of a rectangular part of the image that is to be loaded or saved, instead of the complete image.

### setBoundsIfNecessary

public void setBoundsIfNecessary(int width, int height)
If no bounds have been set (`hasBounds()` returns `false`), this method will set the bounds to `0, 0, width - 1, height - 1`. By calling this method somewhere in the codec, no distinction has to be made for the two cases bounds have been defined and bounds have not been defined.

Parameters:
  `width` - width of the image to be loaded or saved
  `height` - height of the image to be loaded or saved

### setDataInput

public void setDataInput(DataInput dataInput)
Specifies a DataInput object to be used for loading.

Parameters:
  `dataInput` - DataInput object to be used for loading an image

### setDataOutput

public void setDataOutput(DataOutput dataOutput)
Sets a `DataOutput` object to be used for saving an image.

Parameters:
  `dataOutput` - the object to be used for output

### setDpi

public void setDpi(int horizontalDpi, int verticalDpi)
Sets the DPI values to be stored in the file to the argument values.

Parameters:
  `horizontalDpi` - horizontal physical resolution in DPI (dots per inch)
  `verticalDpi` - vertical physical resolution in DPI (dots per inch)
See Also:
  - `getDpiX()`
  - `getDpiY()`

### setFile

public void setFile(File file, CodecMode codecMode) throws IOException, UnsupportedCodecModeException
Gives a File object and a codec mode to this codec and attempts to initialize the appropriate I/O objects. Simply calls `setFile(String, CodecMode)` with the absolute path of the File object.

Parameters:
  `file` - File object for the file to be used
  `codecMode` - defines whether an image is to be loaded from or saved to the file
Throws:
  `IOException`
  `UnsupportedCodecModeException`

### setFile

public void setFile(String fileName, CodecMode codecMode) throws IOException, UnsupportedCodecModeException
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).

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`

### setImage

public void setImage(PixelImage img)
Give an image to this codec to be used for loading an image into it or saving the image.

Parameters:
  `img` - image object to save or to load data into

### setImageIndex

public void setImageIndex(int index)
Sets the index of the image to be loaded to the argument value (which must be zero or larger).

Parameters:
  `index` - int index value (zero-based) of the image to be loaded
Throws:
  `IllegalArgumentException` - if the argument is negative

### setInputStream

public void setInputStream(InputStream inputStream)
An `InputStream` can be given to this codec using this method.

Parameters:
  `inputStream` - InputStream object to read from

### setOutputStream

public void setOutputStream(OutputStream outputStream)
A method to give an `OutputStream` to this codec to be used for saving an image.

Parameters:
  `outputStream` - the output stream to be used by this codec

### setRandomAccessFile

public void setRandomAccessFile(RandomAccessFile randomAccessFile, CodecMode codecMode)
A method to give a `RandomAccessFile` to this codec to be used for loading or saving an image. It is not possible to determine from a RandomAccessFile object whether it was opened in read-only or read-and-write mode. To let the codec know whether the object is to be used for loading or saving the second argument is of type CodecMode.

Parameters:
  `randomAccessFile` - the file to be used for loading or saving
  `codecMode` - tells the codec whether the file is to be used for loading or saving

### suggestFileExtension

public String suggestFileExtension(PixelImage image)
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`.

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