TileMangler/src/tm/colorcodecs/ColorCodec.java

186 lines
4.2 KiB
Java

/*
*
* Copyright (C) 2003 Kent Hansen.
*
* This file is part of Tile Mangler.
*
* Tile Mangler is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Tile Mangler is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
package tm.colorcodecs;
/**
*
* Abstract superclass for color codecs.
* A "color codec" defines how values of a particular format are translated
* to 32-bit ARGB pixel values (decoded), and back again (encoded).
*
**/
public abstract class ColorCodec {
public static final int LITTLE_ENDIAN=1;
public static final int BIG_ENDIAN=2;
public static final int MIDDLE_ENDIAN=3;
protected int bitsPerPixel;
protected int bytesPerPixel;
protected String id;
protected String description;
private static int endianness;
private int startShift;
private int shiftStep;
/**
*
* Creates a ColorCodec with the given id, bits per pixel and description.
*
**/
public ColorCodec(String id, int bitsPerPixel, String description) {
this.id = id;
this.bitsPerPixel = bitsPerPixel;
this.description = description;
bytesPerPixel = getBytesRequired(bitsPerPixel);
setEndianness(LITTLE_ENDIAN); // default
}
/**
* Sets the endianness.
* It determines the byte order related to methods toBytes() and fromBytes().
**/
public void setEndianness(int endianness) {
this.endianness = endianness;
if (endianness == LITTLE_ENDIAN) {
startShift = 0;
shiftStep = 8;
}
else {
// BIG_ENDIAN
startShift = (bytesPerPixel-1) * 8;
shiftStep = -8;
}
}
/**
*
* Gets the ID.
*
**/
public String getID() {
return id;
}
/**
*
* Gets the number of bits per pixel.
*
**/
public int getBitsPerPixel() {
return bitsPerPixel;
}
/**
*
* Gets the number of bytes required to hold one pixel.
*
**/
public int getBytesPerPixel() {
return bytesPerPixel;
}
/**
*
* Gets the description.
*
**/
public String getDescription() {
return description;
}
/**
*
* This method takes a value assumed to be in the color codec's native format
* and returns the equivalent 32-bit ARGB value.
*
**/
public abstract int decode(int value);
/**
*
* This method takes a value assumed to be in 32-bit ARGB format and returns
* the equivalent native format value.
*
**/
public abstract int encode(int argb);
/**
*
* Converts given value to a series of bytes, according to current endianness.
* @param bytes Array to store resulting bytes in
* @param offset Starting offset in array
*
**/
public byte[] toBytes(int value, byte[] bytes, int offset) {
int shift = startShift;
for (int i=0; i<bytesPerPixel; i++) {
bytes[offset+i] = (byte)(value >> shift);
shift += shiftStep;
}
return bytes;
}
/**
*
* Converts bytes from given array to a value, according to current endianness.
* @param offset Where to start reading the bytes that make up the value.
*
**/
public int fromBytes(byte[] bytes, int offset) {
int shift = startShift;
int value = 0;
for (int i=0; i<bytesPerPixel; i++) {
value |= (bytes[offset+i] & 0xFF) << shift;
shift += shiftStep;
}
return value;
}
/**
*
* Gets the least number of whole bytes that are required to store
* <code>bits</code> bits of information.
*
**/
private static int getBytesRequired(int bits) {
int bytes = bits / 8;
int extrabits = bits % 8;
if (extrabits != 0) bytes++;
return bytes;
}
public String toString() {
return description;
}
}