package Pixels;
public class Planes
{
static final int BLOCK_SIZE = 64; // for optimal cache utilization
public static byte[][] combine8(byte[] output, int width, int height, Object[] slicesObj)
{
final int area = width * height;
final int breadth = slicesObj.length;
byte[][] slices = new byte[breadth][];
for (int i = 0; i < breadth; i++)
slices[i] = (byte[])slicesObj[i];
for (int i = 0; i < area; i += BLOCK_SIZE) {
int block = Math.min(BLOCK_SIZE, area - i);
for (int k = 0; k < block; k++)
output[i+k] = (byte)(slices[0][i+k] >>> 31 | -slices[0][i+k] >>> 31);
for (int j = 1; j < breadth; j++) {
for (int k = 0; k < block; k++)
output[i+k] |= (slices[j][i+k] >>> 31 | -slices[j][i+k] >>> 31) << j;
}
}
return slices;
}
public static short[][] combine16(byte[] output, int width, int height, Object[] slicesObj)
{
final int area = width * height;
final int breadth = slicesObj.length;
short[][] slices = new short[breadth][];
for (int i = 0; i < breadth; i++)
slices[i] = (short[])slicesObj[i];
for (int i = 0; i < area; i += BLOCK_SIZE) {
int block = Math.min(BLOCK_SIZE, area - i);
for (int k = 0; k < block; k++)
output[i+k] = (byte)(slices[0][i+k] >>> 31 | -slices[0][i+k] >>> 31);
for (int j = 1; j < breadth; j++) {
for (int k = 0; k < block; k++)
output[i+k] |= (slices[j][i+k] >>> 31 | -slices[j][i+k] >>> 31) << j;
}
}
return slices;
}
public static int[][] combineRgb(byte[] output, int width, int height, Object[] slicesObj)
{
final int area = width * height;
final int breadth = slicesObj.length;
int[][] slices = new int[breadth][];
for (int i = 0; i < breadth; i++)
slices[i] = (int[])slicesObj[i];
for (int i = 0; i < area; i++) {
int rgb = slices[0][i];
output[i] = (byte)(
((rgb & 0xff0000) >>> 31 | -(rgb & 0xff0000) >>> 31) |
((rgb & 0xff00) >>> 31 | -(rgb & 0xff00) >>> 31) << 1 |
((rgb & 0xff) >>> 31 | -(rgb & 0xff) >>> 31) << 2
);
}
return slices;
}
public static float[][] combine32(byte[] output, int width, int height, Object[] slicesObj)
{
final int area = width * height;
final int breadth = slicesObj.length;
float[][] slices = new float[breadth][];
for (int i = 0; i < breadth; i++)
slices[i] = (float[])slicesObj[i];
for (int i = 0; i < area; i += BLOCK_SIZE) {
int block = Math.min(BLOCK_SIZE, area - i);
for (int k = 0; k < block; k++) {
int exp = (Float.floatToRawIntBits(slices[0][i+k]) >> 23) & 0xff;
output[i+k] = (byte)(-(exp - 0x76) >>> 31);
}
for (int j = 1; j < breadth; j++) {
for (int k = 0; k < block; k++) {
int exp = (Float.floatToRawIntBits(slices[j][i+k]) >> 23) & 0xff;
output[i+k] |= (-(exp - 0x76) >>> 31) << j;
}
}
}
return slices;
}
public static void split8(byte[][] output, int width, int height, byte[] planes)
{
final int area = width * height;
final int breadth = output.length;
for (int i = 0; i < area; i += BLOCK_SIZE) {
int block = Math.min(BLOCK_SIZE, area - i);
for (int j = 0; j < breadth; j++) {
for (int k = 0; k < block; k++)
output[j][i+k] = (byte)-((planes[i+k] >>> j) & 1);
}
}
}
public static void split16(short[][] output, int width, int height, byte[] planes)
{
final int area = width * height;
final int breadth = output.length;
for (int i = 0; i < area; i += BLOCK_SIZE) {
int block = Math.min(BLOCK_SIZE, area - i);
for (int j = 0; j < breadth; j++) {
for (int k = 0; k < block; k++)
output[j][i+k] = (short)-((planes[i+k] >>> j) & 1);
}
}
}
public static void splitRgb(int[][] output, int width, int height, byte[] planes)
{
final int area = width * height;
for (int i = 0; i < area; i++) {
int r = -(planes[i] & 1) & 0xff;
int g = -((planes[i] >>> 1) & 1) & 0xff;
int b = -((planes[i] >>> 2) & 1) & 0xff;
output[0][i] = (r << 16) | (g << 8) | b;
}
}
// using the lookup table "float[] {0.0f, 255.0f}" is 5x faster than using a ternary (ie. bit == 1 ? 255.0f : 0.0f)
// see FloatManipBenchmark.java
public static void split32(float[][] output, int width, int height, byte[] planes, float[] lut)
{
final int area = width * height;
final int breadth = output.length;
lut[0] = 0.0f;
lut[1] = 255.0f;
for (int i = 0; i < area; i += BLOCK_SIZE) {
int block = Math.min(BLOCK_SIZE, area - i);
for (int j = 0; j < breadth; j++) {
for (int k = 0; k < block; k++)
output[j][i+k] = lut[(planes[i+k] >>> j) & 1];
}
}
}
public static void copySingleChannelToMonoFloatArray(float[] output, int[] input, int width, int height, int selectedChannel)
{
int area = width * height;
for (int i = 0; i < area; i++)
output[i] = (float)((input[i] >> (8 * (2 - selectedChannel))) & 0xff);
}
}