package org.jcodec.scale;
import java.nio.ByteBuffer;
/**
* This class is part of JCodec ( www.jcodec.org )
* This software is distributed under FreeBSD License
*
* @author The JCodec project
*
*/
public class ImageConvert {
private static final int SCALEBITS = 10;
private static final int ONE_HALF = (1 << (SCALEBITS - 1));
private final static int FIX(double x) {
return ((int) ((x) * (1 << SCALEBITS) + 0.5));
}
private static final int FIX_0_71414 = FIX(0.71414);
private static final int FIX_1_772 = FIX(1.77200);
private static final int _FIX_0_34414 = -FIX(0.34414);
private static final int FIX_1_402 = FIX(1.40200);
public final static int ycbcr_to_rgb24(int y, int cb, int cr) {
y = y << SCALEBITS;
cb = cb - 128;
cr = cr - 128;
int add_r = FIX_1_402 * cr + ONE_HALF;
int add_g = _FIX_0_34414 * cb - FIX_0_71414 * cr + ONE_HALF;
int add_b = FIX_1_772 * cb + ONE_HALF;
int r = (y + add_r) >> SCALEBITS;
int g = (y + add_g) >> SCALEBITS;
int b = (y + add_b) >> SCALEBITS;
r = crop(r);
g = crop(g);
b = crop(b);
return ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff);
}
private static final int CROP = 1024;
final static int Y_JPEG_TO_CCIR(final int y) {
return (((y) * FIX(219.0 / 255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS);
}
final static int Y_CCIR_TO_JPEG(final int y) {
return ((y) * FIX(255.0 / 219.0) + (ONE_HALF - 16 * FIX(255.0 / 219.0))) >> SCALEBITS;
}
private final static byte[] cropTable = new byte[CROP + 256 + CROP];
private final static int[] intCropTable = new int[CROP + 256 + CROP];
private final static byte[] _y_ccir_to_jpeg = new byte[256];
private final static byte[] _y_jpeg_to_ccir = new byte[256];
static {
for (int i = -CROP; i < 0; i++) {
cropTable[i + CROP] = 0;
intCropTable[i + CROP] = 0;
}
for (int i = 0; i < 256; i++) {
cropTable[i + CROP] = (byte) i;
intCropTable[i + CROP] = i;
}
for (int i = 256; i < CROP; i++) {
cropTable[i + CROP] = (byte) 255;
intCropTable[i + CROP] = 255;
}
for (int i = 0; i < 256; i++) {
_y_ccir_to_jpeg[i] = crop(Y_CCIR_TO_JPEG(i));
_y_jpeg_to_ccir[i] = crop(Y_JPEG_TO_CCIR(i));
}
}
public final static int icrop(final int i) {
return intCropTable[i + CROP];
}
public final static byte crop(final int i) {
return cropTable[i + CROP];
}
public final static byte y_ccir_to_jpeg(final byte y) {
return _y_ccir_to_jpeg[(y & 0xff)];
}
public final static byte y_jpeg_to_ccir(final byte y) {
return _y_jpeg_to_ccir[(y & 0xff)];
}
public static void YUV444toRGB888(final int y, final int u, final int v,
final ByteBuffer rgb) {
final int c = y - 16;
final int d = u - 128;
final int e = v - 128;
final int r = (298 * c + 409 * e + 128) >> 8;
final int g = (298 * c - 100 * d - 208 * e + 128) >> 8;
final int b = (298 * c + 516 * d + 128) >> 8;
rgb.put(crop(r));
rgb.put(crop(g));
rgb.put(crop(b));
}
public static void RGB888toYUV444(final ByteBuffer rgb, final ByteBuffer Y,
final ByteBuffer U, final ByteBuffer V) {
final int r = rgb.get() & 0xff;
final int g = rgb.get() & 0xff;
final int b = rgb.get() & 0xff;
int y = 66 * r + 129 * g + 25 * b;
int u = -38 * r - 74 * g + 112 * b;
int v = 112 * r - 94 * g - 18 * b;
y = (y + 128) >> 8;
u = (u + 128) >> 8;
v = (v + 128) >> 8;
Y.put(crop(y + 16));
U.put(crop(u + 128));
V.put(crop(v + 128));
}
public static byte RGB888toY4(final int r, final int g, final int b) {
int y = 66 * r + 129 * g + 25 * b;
y = (y + 128) >> 8;
return crop(y + 16);
}
public static byte RGB888toU4(final int r, final int g, final int b) {
int u = -38 * r - 74 * g + 112 * b;
u = (u + 128) >> 8;
return crop(u + 128);
}
public static byte RGB888toV4(final int r, final int g, final int b) {
int v = 112 * r - 94 * g - 18 * b;
v = (v + 128) >> 8;
return crop(v + 128);
}
}