package ini.trakem2.imaging;
import ini.trakem2.utils.CachingThread;
public final class P {
public static final int[] blend(final byte[] pi, final byte[] pm) {
final int[] p = CachingThread.getOrCreateIntArray(pi.length); // new int[pi.length];
for (int i=0; i<p.length; ++i) {
final int c = (pi[i]&0xff);
p[i] = ((pm[i]&0xff) << 24) | (c << 16) | (c << 8) | c;
}
return p;
}
/** Puts the {@code pi} (the greyscale channel) into the R, G and B components of the returned {@code int[]}
* after having multiplied them by the {@code pm} (the alpha channel); the alpha channel gets inserted into
* the int[] as well. */
public static final int[] blendPre(final byte[] pi, final byte[] pm) {
final int[] p = CachingThread.getOrCreateIntArray(pi.length); // new int[pi.length];
for (int i=0; i<p.length; ++i) {
final int a = (pm[i]&0xff);
final double K = a / 255.0;
final int c = (int)((pi[i]&0xff) * K + 0.5);
p[i] = (a << 24) | (c << 16) | (c << 8) | c;
}
return p;
}
public static final int[] blend(final byte[] r, final byte[] g, final byte[] b, final byte[] a) {
final int[] p = CachingThread.getOrCreateIntArray(r.length); // new int[r.length];
for (int i=0; i<p.length; ++i) {
p[i] = ((a[i]&0xff) << 24) | ((r[i]&0xff) << 16) | ((g[i]&0xff) << 8) | (b[i]&0xff);
}
return p;
}
/** Pre-multiplies alpha. */
public static final int[] blendPre(final byte[] r, final byte[] g, final byte[] b, final byte[] alpha) {
final int[] p = CachingThread.getOrCreateIntArray(r.length); // new int[r.length];
for (int i=0; i<p.length; ++i) {
final int a = (alpha[i]&0xff);
final double K = a / 255.0;
p[i] = (a << 24)
| (((int)((r[i]&0xff) * K + 0.5)) << 16)
| (((int)((g[i]&0xff) * K + 0.5)) << 8)
| ((int)((b[i]&0xff) * K + 0.5));
}
return p;
}
public static final int[] blend(final byte[] r, final byte[] g, final byte[] b) {
final int[] p = CachingThread.getOrCreateIntArray(r.length); // new int[r.length];
for (int i=0; i<p.length; ++i) {
p[i] = ((r[i]&0xff) << 16) | ((g[i]&0xff) << 8) | (b[i]&0xff);
}
return p;
}
/** Merges into alpha if outside is null, otherwise returns alpha as is. */
static public final byte[] merge(final byte[] alpha, byte[] outside) {
if (null == outside) return alpha;
for (int i=0; i<alpha.length; ++i) {
alpha[i] = -1 == outside[i] ? alpha[i] : 0;
}
return alpha;
}
static public final byte[][] asRGBABytes(final int[] pixels, final byte[] alpha, byte[] outside) {
merge(alpha, outside); // into alpha
final byte[] r = CachingThread.getOrCreateByteArray(pixels.length), // new byte[pixels.length],
g = CachingThread.getOrCreateByteArray(pixels.length), // new byte[pixels.length],
b = CachingThread.getOrCreateByteArray(pixels.length); // new byte[pixels.length];
for (int i=0; i<pixels.length; ++i) {
final int x = pixels[i];
r[i] = (byte)((x >> 16)&0xff);
g[i] = (byte)((x >> 8)&0xff);
b[i] = (byte) (x &0xff);
}
return new byte[][]{r, g, b, alpha};
}
static public byte[][] asRGBBytes(final int[] pix) {
final byte[] r = CachingThread.getOrCreateByteArray(pix.length), // new byte[pix.length],
g = CachingThread.getOrCreateByteArray(pix.length), // new byte[pix.length],
b = CachingThread.getOrCreateByteArray(pix
.length); // new byte[pix.length];
for (int i=0; i<pix.length; ++i) {
final int x = pix[i];
r[i] = (byte)((x >> 16)&0xff);
g[i] = (byte)((x >> 8)&0xff);
b[i] = (byte) (x &0xff);
}
return new byte[][]{r, g, b};
}
}