TileMangler/src/tm/colorcodecs/DirectColorCodec.java

169 lines
3.9 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;
/**
*
* A DirectColorCodec translates pixels exactly the same way as
* a direct-color tile codec.
* The composition of a pixel is described by Red, Green,
* Blue and Alpha masks.
*
**/
public class DirectColorCodec extends ColorCodec {
private int rmask; // bitmask for Red component
private int gmask; // bitmask for Green component
private int bmask; // bitmask for Blue component
private int amask; // bitmask for Alpha component
// how much each component must be shifted to be transformed to a 32-bit ARGB int-packed Java pixel.
// these are pre-calculated in the constructor and used for decoding/encoding individual pixels.
private int rshift;
private int gshift;
private int bshift;
private int ashift;
public DirectColorCodec(String id, int bitsPerPixel, int rmask, int gmask, int bmask, int amask, String description) {
super(id, bitsPerPixel, description);
this.rmask = rmask;
this.gmask = gmask;
this.bmask = bmask;
this.amask = amask;
// calculate the shifts
rshift = 23 - msb(rmask);
gshift = 15 - msb(gmask);
bshift = 7 - msb(bmask);
ashift = 31 - msb(amask);
}
/**
* Gets the position of the most significant set bit in the given int.
**/
private static int msb(int mask) {
for (int i=31; i>=0; i--) {
if ((mask & 0x80000000) != 0) {
return i;
}
mask <<= 1;
}
return -1; // no bits set
}
/**
*
*
**/
public int decode(int value) {
int r, g, b, a;
// decode R component
r = value & rmask;
if (rshift < 0) {
r >>= -rshift;
}
else {
r <<= rshift;
}
// decode G component
g = value & gmask;
if (gshift < 0) {
g >>= -gshift;
}
else {
g <<= gshift;
}
// decode B component
b = value & bmask;
if (bshift < 0) {
b >>= -bshift;
}
else {
b <<= bshift;
}
// decode A component
a = value & amask;
if (ashift < 0) {
a >>= -ashift;
}
else {
a <<= ashift;
}
// final pixel
return (a | r | g | b);
}
/**
*
*
**/
public int encode(int argb) {
int r, g, b, a;
// encode R component
r = argb;
if (rshift < 0) {
r <<= -rshift;
}
else {
r >>= rshift;
}
r &= rmask;
// encode G component
g = argb;
if (gshift < 0) {
g <<= -gshift;
}
else {
g >>= gshift;
}
g &= gmask;
// encode B component
b = argb;
if (bshift < 0) {
b <<= -bshift;
}
else {
b >>= bshift;
}
b &= bmask;
// encode A component
a = argb;
if (ashift < 0) {
a <<= -ashift;
}
else {
a >>= ashift;
}
a &= amask;
// final value
return (a | r | g | b);
}
}