95 lines
4.6 KiB
Java
95 lines
4.6 KiB
Java
package org.jcodec.scale;
|
|
|
|
import org.jcodec.common.model.Picture;
|
|
import org.jcodec.common.tools.MathUtil;
|
|
|
|
public class Yuv420pToRgb implements Transform {
|
|
public final void transform(Picture src, Picture dst) {
|
|
byte[] yh = src.getPlaneData(0);
|
|
byte[] uh = src.getPlaneData(1);
|
|
byte[] vh = src.getPlaneData(2);
|
|
byte[] yl = null;
|
|
byte[] ul = null;
|
|
byte[] vl = null;
|
|
byte[][] low = src.getLowBits();
|
|
if (low != null) {
|
|
yl = low[0];
|
|
ul = low[1];
|
|
vl = low[2];
|
|
}
|
|
byte[] data = dst.getPlaneData(0);
|
|
byte[] lowBits = (dst.getLowBits() == null) ? null : dst.getLowBits()[0];
|
|
boolean hbd = (src.isHiBD() && dst.isHiBD());
|
|
int lowBitsNumSrc = src.getLowBitsNum();
|
|
int lowBitsNumDst = dst.getLowBitsNum();
|
|
int offLuma = 0, offChroma = 0;
|
|
int stride = dst.getWidth();
|
|
for (int i = 0; i < dst.getHeight() >> 1; i++) {
|
|
for (int k = 0; k < dst.getWidth() >> 1; k++) {
|
|
int j = k << 1;
|
|
if (hbd) {
|
|
YUV420pToRGBH2H(yh[offLuma + j], yl[offLuma + j], uh[offChroma], ul[offChroma], vh[offChroma], vl[offChroma], lowBitsNumSrc, data, lowBits, lowBitsNumDst, (offLuma + j) * 3);
|
|
YUV420pToRGBH2H(yh[offLuma + j + 1], yl[offLuma + j + 1], uh[offChroma], ul[offChroma], vh[offChroma], vl[offChroma], lowBitsNumSrc, data, lowBits, lowBitsNumDst, (offLuma + j + 1) * 3);
|
|
YUV420pToRGBH2H(yh[offLuma + j + stride], yl[offLuma + j + stride], uh[offChroma], ul[offChroma], vh[offChroma], vl[offChroma], lowBitsNumSrc, data, lowBits, lowBitsNumDst, (offLuma + j + stride) * 3);
|
|
YUV420pToRGBH2H(yh[offLuma + j + stride + 1], yl[offLuma + j + stride + 1], uh[offChroma], ul[offChroma], vh[offChroma], vl[offChroma], lowBitsNumSrc, data, lowBits, lowBitsNumDst, (offLuma + j + stride + 1) * 3);
|
|
} else {
|
|
YUV420pToRGBN2N(yh[offLuma + j], uh[offChroma], vh[offChroma], data, (offLuma + j) * 3);
|
|
YUV420pToRGBN2N(yh[offLuma + j + 1], uh[offChroma], vh[offChroma], data, (offLuma + j + 1) * 3);
|
|
YUV420pToRGBN2N(yh[offLuma + j + stride], uh[offChroma], vh[offChroma], data, (offLuma + j + stride) * 3);
|
|
YUV420pToRGBN2N(yh[offLuma + j + stride + 1], uh[offChroma], vh[offChroma], data, (offLuma + j + stride + 1) * 3);
|
|
}
|
|
offChroma++;
|
|
}
|
|
if ((dst.getWidth() & 0x1) != 0) {
|
|
int j = dst.getWidth() - 1;
|
|
YUV420pToRGBN2N(yh[offLuma + j], uh[offChroma], vh[offChroma], data, (offLuma + j) * 3);
|
|
YUV420pToRGBN2N(yh[offLuma + j + stride], uh[offChroma], vh[offChroma], data, (offLuma + j + stride) * 3);
|
|
offChroma++;
|
|
}
|
|
offLuma += 2 * stride;
|
|
}
|
|
if ((dst.getHeight() & 0x1) != 0) {
|
|
for (int k = 0; k < dst.getWidth() >> 1; k++) {
|
|
int j = k << 1;
|
|
YUV420pToRGBN2N(yh[offLuma + j], uh[offChroma], vh[offChroma], data, (offLuma + j) * 3);
|
|
YUV420pToRGBN2N(yh[offLuma + j + 1], uh[offChroma], vh[offChroma], data, (offLuma + j + 1) * 3);
|
|
offChroma++;
|
|
}
|
|
if ((dst.getWidth() & 0x1) != 0) {
|
|
int j = dst.getWidth() - 1;
|
|
YUV420pToRGBN2N(yh[offLuma + j], uh[offChroma], vh[offChroma], data, (offLuma + j) * 3);
|
|
offChroma++;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void YUV420pToRGBN2N(byte y, byte u, byte v, byte[] data, int off) {
|
|
int c = y + 112;
|
|
int r = 298 * c + 409 * v + 128 >> 8;
|
|
int g = 298 * c - 100 * u - 208 * v + 128 >> 8;
|
|
int b = 298 * c + 516 * u + 128 >> 8;
|
|
data[off] = (byte)(MathUtil.clip(r, 0, 255) - 128);
|
|
data[off + 1] = (byte)(MathUtil.clip(g, 0, 255) - 128);
|
|
data[off + 2] = (byte)(MathUtil.clip(b, 0, 255) - 128);
|
|
}
|
|
|
|
public static void YUV420pToRGBH2H(byte yh, byte yl, byte uh, byte ul, byte vh, byte vl, int nlbi, byte[] data, byte[] lowBits, int nlbo, int off) {
|
|
int clipMax = (1 << nlbo << 8) - 1;
|
|
int round = 1 << nlbo >> 1;
|
|
int c = (yh + 128 << nlbi) + yl - 64;
|
|
int d = (uh + 128 << nlbi) + ul - 512;
|
|
int e = (vh + 128 << nlbi) + vl - 512;
|
|
int r = MathUtil.clip(298 * c + 409 * e + 128 >> 8, 0, clipMax);
|
|
int g = MathUtil.clip(298 * c - 100 * d - 208 * e + 128 >> 8, 0, clipMax);
|
|
int b = MathUtil.clip(298 * c + 516 * d + 128 >> 8, 0, clipMax);
|
|
int valR = MathUtil.clip(r + round >> nlbo, 0, 255);
|
|
data[off] = (byte)(valR - 128);
|
|
lowBits[off] = (byte)(r - (valR << nlbo));
|
|
int valG = MathUtil.clip(g + round >> nlbo, 0, 255);
|
|
data[off + 1] = (byte)(valG - 128);
|
|
lowBits[off + 1] = (byte)(g - (valG << nlbo));
|
|
int valB = MathUtil.clip(b + round >> nlbo, 0, 255);
|
|
data[off + 2] = (byte)(valB - 128);
|
|
lowBits[off + 2] = (byte)(b - (valB << nlbo));
|
|
}
|
|
}
|