169 lines
3.9 KiB
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);
|
|
}
|
|
|
|
} |