Package net.sourceforge.jiu.codecs

# Class PalmCodec

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

public class PalmCodec extends ImageCodec
A codec to read and write image files in the native image file format of Palm OS, an operating system for handheld devices.

### Supported file types when loading

This codec reads uncompressed, scan line compressed and RLE compressed Palm files with bit depths of 1, 2, 4, 8 and 16 bits per pixel. Not supported are the Packbits compression algorithm or any color depths other then the aforementioned.

### Supported image types when saving

Compression types Uncompressed, Scan line and RLE are written. When saving an image as a Palm, the image data classes will be mapped to file types as follows:

- `BilevelImage`: will be saved as a 1 bit per pixel, monochrome file.
- `Gray8Image`: will be saved as an 8 bits per pixel file with a custom palette which will contain the 256 shades of gray from black - (0, 0, 0) - to white - (255, 255, 255).
- `Paletted8Image`: it is first checked if the image is using the Palm system 8 bits per pixel palette. If so, an 8 bits per pixel file with no custom palette is written, otherwise an 8 bits per pixel file with a custom palette (of the original length) is written.
- `RGB24Image`: will be saved as a 16 bits per pixel, direct color file. Some information will get lost when converting from 24 to 16 bits per pixel. Instead of 256 shades for each red, green and blue (and thus, 2563 = 16,777,216 possible colors) the resulting file will only use 32 shades of red and blue and 64 shades of green (65,536 possible colors).

### I/O objects

This codec supports all the I/O classes that are considered in ImageCodec. If you save images and want a correct compressed size field in the resulting Palm file, make sure to give a RandomAccessFile object to the codec. Or simply use `setFile(java.lang.String, net.sourceforge.jiu.codecs.CodecMode)` which does that automatically.

### File extension

This codec suggests `.palm` as file extension for this file format. This is by no means official, but I find it helpful.

### Transparency information

The transparency index in a Palm file is saved and loaded, but a loaded index is not stored in the image object as there is no support for transparency information of any kind in PixelImage yet. The RGB transparency color that is present in a file only in direct color mode is read but not written.

### Bounds

The bounds concept of ImageCodec is supported so that you can load or save only part of an image.

### Open questions on the Palm file format

- How does Packbits compression work? Where can I get sample files or a Windows converter that writes those?
- How is FLAG_4_BYTE_FIELDS interpreted? When are four byte fields used?
- When loading a 4 bpp Palm image file without a custom palette, how is the decoder supposed to know whether to take the predefined color or grayscale palette with 16 entries?

### Known problems

- Unfortunately, the Palm image file format does not include a signature that makes it easy to identify such a file. Various checks on allowed combinations of color depth, compression type etc. will prevent the codec from trying to interpret all files as Palm image files, but there is still a probability of false identification.

### Usage examples

Load an image from a Palm image file:

     PalmCodec codec = new PalmCodec();
     codec.setFile("test.palm", CodecMode.LOAD);
     codec.process();
     PixelImage image = codec.getImage();
     codec.close();

Save an image to a Palm file using RLE compression:

     PalmCodec codec = new PalmCodec();
     codec.setImage(image);
     codec.setCompression(PalmCodec.COMPRESSION_RLE);
     codec.setFile("out.palm", CodecMode.SAVE);
     codec.process();
     codec.close();

### Background

The code is based on:

- the specification Palm Native Image Format,
- the source code of the utilities `pnmtopalm` and `palmtopnm` that are part of the Netpbm package,
- Palm OS Compressed Bitmaps by Ken Krugler, a Palm Developer Knowledge Base article on the scan line compression algorithm and
- Palm OS Bitmaps, also part of the Palm Developer Knowledge Base, contains general information on the structure of Palm images.

I also received helpful feedback and test images from Bill Janssen.

Author:
  Marco Schmidt

## Field Summary

Fields
Modifier and Type
Field
Description
`private int`
`bitsPerPixel`
`private int`
`blueBits`
`private int`
`bytesPerRow`
`private long`
`compressedDataOffset`
`private int`
`compression`
`static final int`
`COMPRESSION_NONE`
Constant for compression type Uncompressed.
`static final int`
`COMPRESSION_PACKBITS`
Constant for compression type Packbits.
`static final int`
`COMPRESSION_RLE`
Constant for compression type RLE (run length encoding).
`static final int`
`COMPRESSION_SCANLINE`
Constant for compression type Scanline.
`private static final int`
`FLAG_COLOR_TABLE`
`private static final int`
`FLAG_COMPRESSED`
`private static final int`
`FLAG_DIRECT_COLOR`
`private static final int`
`FLAG_TRANSPARENCY`
`private int`
`flags`
`private int`
`greenBits`
`private int`
`height`
`private Palette`
`palette`
`private static final short[][]`
`PALM_SYSTEM_PALETTE_16_COLOR`
`private static final short[][]`
`PALM_SYSTEM_PALETTE_16_GRAY`
`private static final short[][]`
`PALM_SYSTEM_PALETTE_256`
`private static final short[][]`
`PALM_SYSTEM_PALETTE_4_GRAY`
`private int`
`redBits`
`private byte[]`
`rgb`
`private byte[]`
`transColor`
`private int`
`transparencyIndex`
`private int`
`version`
`private int`
`width`

## Constructor Summary

Constructors
Constructor
Description
`PalmCodec()`

## Method Summary

Modifier and Type
Method
Description
`private static Palette`
`createPalette(short[][] data)`
`static Palette`
`createSystem2BitGrayscalePalette()`
Creates the 2 bits per pixel Palm system palette with grayscale values.
`static Palette`
`createSystem4BitColorPalette()`
Creates the 4 bits per pixel Palm system palette with color values.
`static Palette`
`createSystem4BitGrayscalePalette()`
Creates the 4 bits per pixel Palm system palette with grayscale values.
`static Palette`
`createSystem8BitPalette()`
Creates the 8 bits per pixel Palm system palette.
`int`
`getCompression()`
Returns the Palm compression method.
`String`
`getFormatName()`
Returns the name of the file format supported by this codec.
`String[]`
`getMimeTypes()`
Return the MIME (Multipurpose Internet Mail Extensions) type strings for this format, or `null` if none are available.
`int`
`getTransparencyIndex()`
Returns the transpareny index if one is available (`hasTransparencyIndex()` returns `true`) or an undefined value otherwise.
`boolean`
`hasTransparencyIndex()`
Returns whether a transpareny index is available and can be retrieved via `getTransparencyIndex()`.
`private void`
`invertBilevelData(byte[] row)`
`private static boolean`
`isEqualPalette(Palette palette, short[][] data)`
`boolean`
`isLoadingSupported()`
Returns if this codec is able to load images in the file format supported by this codec.
`static boolean`
`isPalmSystemPalette256(Palette palette)`
Returns if the argument palette is the Palm system palette with 256 colors.
`static boolean`
`isPalmSystemPaletteColor16(Palette palette)`
Returns if the argument palette is the Palm system color palette with 16 entries.
`static boolean`
`isPalmSystemPaletteGray16(Palette palette)`
Returns if the argument palette is the Palm system grayscale palette with 16 entries.
`static boolean`
`isPalmSystemPaletteGray4(Palette palette)`
Returns if the argument palette is the Palm system grayscale palette with 4 entries.
`boolean`
`isSavingSupported()`
Returns if this codec is able to save images in the file format supported by this codec.
`private void`
`load()`
`private void`
`loadHeader(DataInput in)`
`private void`
`loadImage(DataInput in)`
`private void`
`loadImageData(DataInput in)`
`private void`
`loadPalette(DataInput in)`
`void`
`process()`
This method does the actual work of the operation.
`void`
`removeTransparencyIndex()`
Removes the transparency index if one has been set.
`private void`
`save()`
`private void`
`save(DataOutput out, BilevelImage image)`
`private void`
`save(DataOutput out, Gray8Image image)`
`private void`
`save(DataOutput out, Paletted8Image image)`
`private void`
`save(DataOutput out, RGB24Image image)`
`private void`
`saveFinalCompressedSize(DataOutput out)`
`private void`
`saveHeader(DataOutput out)`
`private void`
`saveInitialCompressedSize(DataOutput out)`
`private void`
`savePalette(DataOutput out, Palette palette)`
`private void`
`saveRow(DataOutput out, boolean firstRow, byte[] row, byte[] prev)`
`private void`
`saveRowRLE(DataOutput out, byte[] row)`
`private void`
`saveRowScanLine(DataOutput out, boolean firstRow, byte[] row, byte[] prev)`
`void`
`setCompression(int newCompressionType)`
Sets the compression algorithm to be used for saving an image.
`private void`
`setCorrectVersion()`
`void`
`setFile(String fileName, CodecMode codecMode)`
Reuses super.setFile when used for CodecMode.LOAD, but creates a RandomAccessFile instead of a FileOutputStream in write mode so that the compressed size can be written correcly (requires a seek operation).
`void`
`setTransparencyIndex(int newIndex)`
Sets a new transparency index when saving an image.
`private void`
`store(PixelImage image, int y, byte[] row)`
`String`
`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`

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

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

## Field Details

### COMPRESSION_NONE

public static final int COMPRESSION_NONE
Constant for compression type Uncompressed.

See Also:
  - Constant Field Values

### COMPRESSION_PACKBITS

public static final int COMPRESSION_PACKBITS
Constant for compression type Packbits.

See Also:
  - Constant Field Values

### COMPRESSION_RLE

public static final int COMPRESSION_RLE
Constant for compression type RLE (run length encoding).

See Also:
  - Constant Field Values

### COMPRESSION_SCANLINE

public static final int COMPRESSION_SCANLINE
Constant for compression type Scanline.

See Also:
  - Constant Field Values

### FLAG_COMPRESSED

private static final int FLAG_COMPRESSED

See Also:
  - Constant Field Values

### FLAG_COLOR_TABLE

private static final int FLAG_COLOR_TABLE

See Also:
  - Constant Field Values

### FLAG_TRANSPARENCY

private static final int FLAG_TRANSPARENCY

See Also:
  - Constant Field Values

### FLAG_DIRECT_COLOR

private static final int FLAG_DIRECT_COLOR

See Also:
  - Constant Field Values

### PALM_SYSTEM_PALETTE_4_GRAY

private static final short[][] PALM_SYSTEM_PALETTE_4_GRAY

### PALM_SYSTEM_PALETTE_16_COLOR

private static final short[][] PALM_SYSTEM_PALETTE_16_COLOR

### PALM_SYSTEM_PALETTE_16_GRAY

private static final short[][] PALM_SYSTEM_PALETTE_16_GRAY

### PALM_SYSTEM_PALETTE_256

private static final short[][] PALM_SYSTEM_PALETTE_256

### bitsPerPixel

private int bitsPerPixel

### blueBits

private int blueBits

### bytesPerRow

private int bytesPerRow

### compression

private int compression

### compressedDataOffset

private long compressedDataOffset

### flags

private int flags

### greenBits

private int greenBits

### height

private int height

### palette

private Palette palette

### redBits

private int redBits

### rgb

private byte[] rgb

### transColor

private byte[] transColor

### transparencyIndex

private int transparencyIndex

### version

private int version

### width

private int width

## Constructor Details

### PalmCodec

public PalmCodec()

## Method Details

### createPalette

private static Palette createPalette(short[][] data)

### createSystem2BitGrayscalePalette

public static Palette createSystem2BitGrayscalePalette()
Creates the 2 bits per pixel Palm system palette with grayscale values. This palette is used when no custom palette is defined in a 2 bpp image.

Returns:
  Palm's default palette for 2 bits per pixel (grayscale), with 4 entries

### createSystem4BitColorPalette

public static Palette createSystem4BitColorPalette()
Creates the 4 bits per pixel Palm system palette with color values. This palette (or the 4 bpp grayscale palette) is used when no custom palette is defined in a 4 bpp image.

Returns:
  Palm's default palette for 4 bits per pixel (color), with 16 entries

### createSystem4BitGrayscalePalette

public static Palette createSystem4BitGrayscalePalette()
Creates the 4 bits per pixel Palm system palette with grayscale values. This palette (or the 4 bpp color palette) is used when no custom palette is defined in a 4 bpp image.

Returns:
  Palm's default palette for 4 bits per pixel (grayscale), with 16 entries

### createSystem8BitPalette

public static Palette createSystem8BitPalette()
Creates the 8 bits per pixel Palm system palette. This palette is used when no custom palette is defined in an 8 bpp image.

Returns:
  Palm's default palette for 8 bits per pixel, with 256 entries

### getCompression

public int getCompression()
Returns the Palm compression method. This should be one of the COMPRESSION_xyz constants of this class.

Returns:
  integer value with the compression method (found in a file when loading or to be used for saving)
See Also:
  - `setCompression(int)`

### 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

### getTransparencyIndex

public int getTransparencyIndex()
Returns the transpareny index if one is available (`hasTransparencyIndex()` returns `true`) or an undefined value otherwise.

See Also:
  - `hasTransparencyIndex()`
  - `removeTransparencyIndex()`
  - `setTransparencyIndex(int)`

### hasTransparencyIndex

public boolean hasTransparencyIndex()
Returns whether a transpareny index is available and can be retrieved via `getTransparencyIndex()`.

Returns:
  transparency index, a positive value that is a valid index into the palette
See Also:
  - `getTransparencyIndex()`
  - `removeTransparencyIndex()`
  - `setTransparencyIndex(int)`

### invertBilevelData

private void invertBilevelData(byte[] row)

### isEqualPalette

private static boolean isEqualPalette(Palette palette, short[][] data)

### 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

### isPalmSystemPaletteGray4

public static boolean isPalmSystemPaletteGray4(Palette palette)
Returns if the argument palette is the Palm system grayscale palette with 4 entries.

Parameters:
  `palette` - to be checked
See Also:
  - `createSystem2BitGrayscalePalette()`

### isPalmSystemPaletteGray16

public static boolean isPalmSystemPaletteGray16(Palette palette)
Returns if the argument palette is the Palm system grayscale palette with 16 entries.

Parameters:
  `palette` - to be checked
See Also:
  - `createSystem4BitGrayscalePalette()`

### isPalmSystemPaletteColor16

public static boolean isPalmSystemPaletteColor16(Palette palette)
Returns if the argument palette is the Palm system color palette with 16 entries.

Parameters:
  `palette` - to be checked
See Also:
  - `createSystem4BitColorPalette()`

### isPalmSystemPalette256

public static boolean isPalmSystemPalette256(Palette palette)
Returns if the argument palette is the Palm system palette with 256 colors.

Parameters:
  `palette` - to be checked
Returns:
  if the argument is an 8 bits per pixel Palm system palette
See Also:
  - `createSystem8BitPalette()`

### 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

private void load() throws InvalidFileStructureException, IOException, OperationFailedException, UnsupportedTypeException, WrongFileFormatException

Throws:
  `InvalidFileStructureException`
  `IOException`
  `OperationFailedException`
  `UnsupportedTypeException`
  `WrongFileFormatException`

### loadHeader

private void loadHeader(DataInput in) throws InvalidFileStructureException, IOException, UnsupportedTypeException, WrongFileFormatException

Throws:
  `InvalidFileStructureException`
  `IOException`
  `UnsupportedTypeException`
  `WrongFileFormatException`

### loadImage

private void loadImage(DataInput in) throws InvalidFileStructureException, IOException, UnsupportedTypeException, WrongFileFormatException, WrongParameterException

Throws:
  `InvalidFileStructureException`
  `IOException`
  `UnsupportedTypeException`
  `WrongFileFormatException`
  `WrongParameterException`

### loadImageData

private void loadImageData(DataInput in) throws InvalidFileStructureException, IOException

Throws:
  `InvalidFileStructureException`
  `IOException`

### loadPalette

private void loadPalette(DataInput in) throws InvalidFileStructureException, IOException, UnsupportedTypeException, WrongFileFormatException

Throws:
  `InvalidFileStructureException`
  `IOException`
  `UnsupportedTypeException`
  `WrongFileFormatException`

### process

public void process() throws InvalidFileStructureException, MissingParameterException, OperationFailedException, WrongParameterException
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`
  `WrongParameterException` - if at least one of the input parameters was not initialized appropriately (values out of the valid interval, etc.)
  `InvalidFileStructureException`

### removeTransparencyIndex

public void removeTransparencyIndex()
Removes the transparency index if one has been set.

See Also:
  - `getTransparencyIndex()`
  - `hasTransparencyIndex()`
  - `setTransparencyIndex(int)`

### save

private void save() throws IOException, OperationFailedException, UnsupportedTypeException

Throws:
  `IOException`
  `OperationFailedException`
  `UnsupportedTypeException`

### save

private void save(DataOutput out, BilevelImage image) throws IOException

Throws:
  `IOException`

### save

private void save(DataOutput out, Gray8Image image) throws IOException

Throws:
  `IOException`

### save

private void save(DataOutput out, Paletted8Image image) throws IOException

Throws:
  `IOException`

### save

private void save(DataOutput out, RGB24Image image) throws IOException

Throws:
  `IOException`

### saveFinalCompressedSize

private void saveFinalCompressedSize(DataOutput out) throws IOException

Throws:
  `IOException`

### saveHeader

private void saveHeader(DataOutput out) throws IOException

Throws:
  `IOException`

### saveInitialCompressedSize

private void saveInitialCompressedSize(DataOutput out) throws IOException

Throws:
  `IOException`

### savePalette

private void savePalette(DataOutput out, Palette palette) throws IOException

Throws:
  `IOException`

### saveRow

private void saveRow(DataOutput out, boolean firstRow, byte[] row, byte[] prev) throws IOException

Throws:
  `IOException`

### saveRowRLE

private void saveRowRLE(DataOutput out, byte[] row) throws IOException

Throws:
  `IOException`

### saveRowScanLine

private void saveRowScanLine(DataOutput out, boolean firstRow, byte[] row, byte[] prev) throws IOException

Throws:
  `IOException`

### setCompression

public void setCompression(int newCompressionType)
Sets the compression algorithm to be used for saving an image.

Parameters:
  `newCompressionType` - int value that is one of the COMPRESSION_xyz constants of this class
Throws:
  `IllegalArgumentException` - if the compression type is unsupported
See Also:
  - `getCompression()`

### setCorrectVersion

private void setCorrectVersion()

### setFile

public void setFile(String fileName, CodecMode codecMode) throws IOException, UnsupportedCodecModeException
Reuses super.setFile when used for CodecMode.LOAD, but creates a RandomAccessFile instead of a FileOutputStream in write mode so that the compressed size can be written correcly (requires a seek operation).

Overrides:
  `setFile` in class `ImageCodec`
Parameters:
  `fileName` - name of the file to be opened
  `codecMode` - defines whether this codec object is to be used for loading or saving
Throws:
  `IOException`
  `UnsupportedCodecModeException`

### setTransparencyIndex

public void setTransparencyIndex(int newIndex)
Sets a new transparency index when saving an image. If this method is called, the argument value is used as an index into the palette for a color that is supposed to be transparent. When the resulting Palm image file is drawn onto some background, all pixels in the color pointed to by the transparency index are not supposed to be overdrawn so that the background is visisble at those places.

Parameters:
  `newIndex` - the new transparency index, must be smaller than the number of entries in the palette
See Also:
  - `getTransparencyIndex()`
  - `hasTransparencyIndex()`
  - `removeTransparencyIndex()`

### store

private void store(PixelImage image, int y, byte[] row)

### 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