www in docker support

This commit is contained in:
MaddoScientisto 2026-04-22 18:41:37 +02:00
commit c227fce036
2145 changed files with 399596 additions and 58 deletions

View file

@ -0,0 +1,107 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
import org.jcodec.common.model.Size;
import org.jcodec.common.tools.MathUtil;
public abstract class BaseResampler {
private final ThreadLocal<int[]> tempBuffers;
private Size toSize;
private Size fromSize;
private final double scaleFactorX;
private final double scaleFactorY;
public BaseResampler(Size from, Size to) {
this.toSize = to;
this.fromSize = from;
this.scaleFactorX = (double)from.getWidth() / (double)to.getWidth();
this.scaleFactorY = (double)from.getHeight() / (double)to.getHeight();
this.tempBuffers = new ThreadLocal<>();
}
private static byte getPel(Picture pic, int plane, int x, int y) {
if (x < 0)
x = 0;
if (y < 0)
y = 0;
int w = pic.getPlaneWidth(plane);
if (x > w - 1)
x = w - 1;
int h = pic.getPlaneHeight(plane);
if (y > h - 1)
y = h - 1;
return pic.getData()[plane][x + y * w];
}
protected abstract short[] getTapsX(int paramInt);
protected abstract short[] getTapsY(int paramInt);
protected abstract int nTaps();
public static void normalizeAndGenerateFixedPrecision(double[] taps, int precBits, short[] out) {
double sum = 0.0D;
for (int i = 0; i < taps.length; i++)
sum += taps[i];
int sumFix = 0;
int precNum = 1 << precBits;
for (int j = 0; j < taps.length; j++) {
double d = taps[j] * (double)precNum / sum + (double)precNum;
int s = (int)d;
taps[j] = d - (double)s;
out[j] = (short)(s - precNum);
sumFix += out[j];
}
long tapsTaken = 0L;
while (sumFix < precNum) {
int maxI = -1;
for (int m = 0; m < taps.length; m++) {
if ((tapsTaken & (long)(1 << m)) == 0L && (maxI == -1 || taps[m] > taps[maxI]))
maxI = m;
}
out[maxI] = (short)(out[maxI] + 1);
sumFix++;
tapsTaken |= (long)(1 << maxI);
}
for (int k = 0; k < taps.length; k++) {
taps[k] = taps[k] + (double)out[k];
if ((tapsTaken & (long)(1 << k)) != 0L)
taps[k] = taps[k] - 1.0D;
}
}
public void resample(Picture src, Picture dst) {
int[] temp = this.tempBuffers.get();
int taps = nTaps();
if (temp == null) {
temp = new int[this.toSize.getWidth() * (this.fromSize.getHeight() + taps)];
this.tempBuffers.set(temp);
}
for (int p = 0; p < (src.getColor()).nComp; p++) {
for (int i = 0; i < src.getPlaneHeight(p) + taps; i++) {
for (int x = 0; x < dst.getPlaneWidth(p); x++) {
short[] tapsXs = getTapsX(x);
int srcX = (int)(this.scaleFactorX * (double)x) - taps / 2 + 1;
int sum = 0;
for (int j = 0; j < taps; j++)
sum += (getPel(src, p, srcX + j, i - taps / 2 + 1) + 128) * tapsXs[j];
temp[i * this.toSize.getWidth() + x] = sum;
}
}
for (int y = 0; y < dst.getPlaneHeight(p); y++) {
for (int x = 0; x < dst.getPlaneWidth(p); x++) {
short[] tapsYs = getTapsY(y);
int srcY = (int)(this.scaleFactorY * (double)y);
int sum = 0;
for (int j = 0; j < taps; j++)
sum += temp[x + (srcY + j) * this.toSize.getWidth()] * tapsYs[j];
dst.getPlaneData(p)[y * dst.getPlaneWidth(p) + x] = (byte)(MathUtil.clip(sum + 8192 >> 14, 0, 255) - 128);
}
}
}
}
}

View file

@ -0,0 +1,58 @@
package org.jcodec.scale;
import org.jcodec.common.model.Size;
public class BicubicResampler extends BaseResampler {
private short[][] horizontalTaps;
private short[][] verticalTaps;
private static double alpha = 0.6D;
public BicubicResampler(Size from, Size to) {
super(from, to);
this.horizontalTaps = buildFilterTaps(to.getWidth(), from.getWidth());
this.verticalTaps = buildFilterTaps(to.getHeight(), from.getHeight());
}
private static short[][] buildFilterTaps(int to, int from) {
double[] taps = new double[4];
short[][] tapsOut = new short[to][4];
double ratio = (double)from / (double)to;
double toByFrom = (double)to / (double)from;
double srcPos = 0.0D;
for (int i = 0; i < to; i++) {
double fraction = srcPos - (double)(int)srcPos;
for (int t = -1; t < 3; t++) {
double d = (double)t - fraction;
if (to < from)
d *= toByFrom;
double x = Math.abs(d);
double xx = x * x;
double xxx = xx * x;
if (d >= -1.0D && d <= 1.0D) {
taps[t + 1] = (2.0D - alpha) * xxx + (-3.0D + alpha) * xx + 1.0D;
} else if (d < -2.0D || d > 2.0D) {
taps[t + 1] = 0.0D;
} else {
taps[t + 1] = -alpha * xxx + 5.0D * alpha * xx - 8.0D * alpha * x + 4.0D * alpha;
}
}
normalizeAndGenerateFixedPrecision(taps, 7, tapsOut[i]);
srcPos += ratio;
}
return tapsOut;
}
protected short[] getTapsX(int dstX) {
return this.horizontalTaps[dstX];
}
protected short[] getTapsY(int dstY) {
return this.verticalTaps[dstY];
}
protected int nTaps() {
return 4;
}
}

View file

@ -0,0 +1,63 @@
package org.jcodec.scale;
import java.util.HashMap;
import java.util.Map;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;
public class ColorUtil {
private static Map<ColorSpace, Map<ColorSpace, Transform>> map = new HashMap<>();
static {
Map<ColorSpace, Transform> rgb = new HashMap<>();
rgb.put(ColorSpace.RGB, new Idential());
rgb.put(ColorSpace.YUV420J, new RgbToYuv420j());
rgb.put(ColorSpace.YUV420, new RgbToYuv420p());
rgb.put(ColorSpace.YUV422, new RgbToYuv422p());
map.put(ColorSpace.RGB, rgb);
Map<ColorSpace, Transform> yuv420 = new HashMap<>();
yuv420.put(ColorSpace.YUV420, new Idential());
yuv420.put(ColorSpace.YUV422, new Yuv420pToYuv422p());
yuv420.put(ColorSpace.RGB, new Yuv420pToRgb());
yuv420.put(ColorSpace.YUV420J, new Idential());
map.put(ColorSpace.YUV420, yuv420);
Map<ColorSpace, Transform> yuv422 = new HashMap<>();
yuv422.put(ColorSpace.YUV422, new Idential());
yuv422.put(ColorSpace.YUV420, new Yuv422pToYuv420p());
yuv422.put(ColorSpace.YUV420J, new Yuv422pToYuv420p());
yuv422.put(ColorSpace.RGB, new Yuv422pToRgb());
map.put(ColorSpace.YUV422, yuv422);
Map<ColorSpace, Transform> yuv444 = new HashMap<>();
yuv444.put(ColorSpace.YUV444, new Idential());
map.put(ColorSpace.YUV444, yuv444);
Map<ColorSpace, Transform> yuv444j = new HashMap<>();
yuv444j.put(ColorSpace.YUV444J, new Idential());
yuv444j.put(ColorSpace.YUV420J, new Yuv444jToYuv420j());
map.put(ColorSpace.YUV444J, yuv444j);
Map<ColorSpace, Transform> yuv420j = new HashMap<>();
yuv420j.put(ColorSpace.YUV420J, new Idential());
yuv420j.put(ColorSpace.YUV422, new Yuv420pToYuv422p());
yuv420j.put(ColorSpace.RGB, new Yuv420jToRgb());
yuv420j.put(ColorSpace.YUV420, new Idential());
map.put(ColorSpace.YUV420J, yuv420j);
}
public static Transform getTransform(ColorSpace from, ColorSpace to) {
Map<ColorSpace, Transform> map2 = map.get(from);
return (map2 == null) ? null : map2.get(to);
}
public static class Idential implements Transform {
public void transform(Picture src, Picture dst) {
for (int i = 0; i < Math.min((src.getData()).length, (dst.getData()).length); i++)
System.arraycopy(src.getPlaneData(i), 0, dst.getPlaneData(i), 0,
Math.min((src.getPlaneData(i)).length, (dst.getPlaneData(i)).length));
byte[][] srcLowBits = src.getLowBits();
byte[][] dstLowBits = dst.getLowBits();
if (srcLowBits != null && dstLowBits != null)
for (int j = 0; j < Math.min((src.getData()).length, (dst.getData()).length); j++)
System.arraycopy(srcLowBits[j], 0, dstLowBits[j], 0,
Math.min((src.getPlaneData(j)).length, (dst.getPlaneData(j)).length));
}
}
}

View file

@ -0,0 +1,135 @@
package org.jcodec.scale;
import java.nio.ByteBuffer;
public class ImageConvert {
private static final int SCALEBITS = 10;
private static final int ONE_HALF = 512;
private static final int FIX(double x) {
return (int)(x * 1024.0D + 0.5D);
}
private static final int FIX_0_71414 = FIX(0.71414D);
private static final int FIX_1_772 = FIX(1.772D);
private static final int _FIX_0_34414 = -FIX(0.34414D);
private static final int FIX_1_402 = FIX(1.402D);
private static final int CROP = 1024;
public static final int ycbcr_to_rgb24(int y, int cb, int cr) {
y <<= 10;
cb -= 128;
cr -= 128;
int add_r = FIX_1_402 * cr + 512;
int add_g = _FIX_0_34414 * cb - FIX_0_71414 * cr + 512;
int add_b = FIX_1_772 * cb + 512;
int r = y + add_r >> 10;
int g = y + add_g >> 10;
int b = y + add_b >> 10;
r = crop(r);
g = crop(g);
b = crop(b);
return (r & 0xFF) << 16 | (g & 0xFF) << 8 | b & 0xFF;
}
static final int Y_JPEG_TO_CCIR(int y) {
return y * FIX(0.8588235294117647D) + 16896 >> 10;
}
static final int Y_CCIR_TO_JPEG(int y) {
return y * FIX(1.1643835616438356D) + 512 - 16 * FIX(1.1643835616438356D) >> 10;
}
private static final byte[] cropTable = new byte[2304];
private static final int[] intCropTable = new int[2304];
private static final byte[] _y_ccir_to_jpeg = new byte[256];
private static final byte[] _y_jpeg_to_ccir = new byte[256];
static {
for (int m = -1024; m < 0; m++) {
cropTable[m + 1024] = 0;
intCropTable[m + 1024] = 0;
}
for (int k = 0; k < 256; k++) {
cropTable[k + 1024] = (byte)k;
intCropTable[k + 1024] = k;
}
for (int j = 256; j < 1024; j++) {
cropTable[j + 1024] = -1;
intCropTable[j + 1024] = 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 static final int icrop(int i) {
return intCropTable[i + 1024];
}
public static final byte crop(int i) {
return cropTable[i + 1024];
}
public static final byte y_ccir_to_jpeg(byte y) {
return _y_ccir_to_jpeg[y & 0xFF];
}
public static final byte y_jpeg_to_ccir(byte y) {
return _y_jpeg_to_ccir[y & 0xFF];
}
public static void YUV444toRGB888(int y, int u, int v, ByteBuffer rgb) {
int c = y - 16;
int d = u - 128;
int e = v - 128;
int r = 298 * c + 409 * e + 128 >> 8;
int g = 298 * c - 100 * d - 208 * e + 128 >> 8;
int b = 298 * c + 516 * d + 128 >> 8;
rgb.put(crop(r));
rgb.put(crop(g));
rgb.put(crop(b));
}
public static void RGB888toYUV444(ByteBuffer rgb, ByteBuffer Y, ByteBuffer U, ByteBuffer V) {
int r = rgb.get() & 0xFF;
int g = rgb.get() & 0xFF;
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(int r, int g, int b) {
int y = 66 * r + 129 * g + 25 * b;
y = y + 128 >> 8;
return crop(y + 16);
}
public static byte RGB888toU4(int r, int g, int b) {
int u = -38 * r - 74 * g + 112 * b;
u = u + 128 >> 8;
return crop(u + 128);
}
public static byte RGB888toV4(int r, int g, int b) {
int v = 112 * r - 94 * g - 18 * b;
v = v + 128 >> 8;
return crop(v + 128);
}
}

View file

@ -0,0 +1,5 @@
package org.jcodec.scale;
public enum InterpFilter {
LANCZOS, BICUBIC;
}

View file

@ -0,0 +1,61 @@
package org.jcodec.scale;
import org.jcodec.common.model.Size;
public class LanczosResampler extends BaseResampler {
private static final int _nTaps = 6;
private int precision = 256;
private short[][] tapsXs;
private short[][] tapsYs;
private double _scaleFactorX;
private double _scaleFactorY;
public LanczosResampler(Size from, Size to) {
super(from, to);
this._scaleFactorX = (double)to.getWidth() / (double)from.getWidth();
this._scaleFactorY = (double)to.getHeight() / (double)from.getHeight();
this.tapsXs = new short[this.precision][6];
this.tapsYs = new short[this.precision][6];
buildTaps(6, this.precision, this._scaleFactorX, this.tapsXs);
buildTaps(6, this.precision, this._scaleFactorY, this.tapsYs);
}
private static double sinc(double x) {
return (x == 0.0D) ? 1.0D : (Math.sin(x) / x);
}
private static void buildTaps(int nTaps, int precision, double scaleFactor, short[][] tapsOut) {
double[] taps = new double[nTaps];
for (int i = 0; i < precision; i++) {
double o = (double)i / (double)precision;
for (int j = -nTaps / 2 + 1, t = 0; j < nTaps / 2 + 1; j++, t++) {
double x = -o + (double)j;
double sinc_val = scaleFactor * sinc(scaleFactor * x * Math.PI);
double wnd_val = Math.sin(x * Math.PI / (double)(nTaps - 1) + 1.5707963267948966D);
taps[t] = sinc_val * wnd_val;
}
normalizeAndGenerateFixedPrecision(taps, 7, tapsOut[i]);
}
}
protected short[] getTapsX(int dstX) {
int oi = (int)((double)(float)(dstX * this.precision) / this._scaleFactorX);
int sub_pel = oi % this.precision;
return this.tapsXs[sub_pel];
}
protected short[] getTapsY(int dstY) {
int oy = (int)((double)(float)(dstY * this.precision) / this._scaleFactorY);
int sub_pel = oy % this.precision;
return this.tapsYs[sub_pel];
}
protected int nTaps() {
return 6;
}
}

View file

@ -0,0 +1,21 @@
package org.jcodec.scale;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.Picture;
public class RgbToBgr implements Transform {
public void transform(Picture src, Picture dst) {
if ((src.getColor() != ColorSpace.RGB && src.getColor() != ColorSpace.BGR) || (
dst.getColor() != ColorSpace.RGB && dst.getColor() != ColorSpace.BGR))
throw new IllegalArgumentException("Expected RGB or BGR inputs, was: " +
String.valueOf(src.getColor()) + ", " + String.valueOf(dst.getColor()));
byte[] dataSrc = src.getPlaneData(0);
byte[] dataDst = dst.getPlaneData(0);
for (int i = 0; i < dataSrc.length; i += 3) {
byte tmp = dataSrc[i + 2];
dataDst[i + 2] = dataSrc[i];
dataDst[i] = tmp;
dataDst[i + 1] = dataSrc[i + 1];
}
}
}

View file

@ -0,0 +1,50 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
import org.jcodec.common.tools.MathUtil;
public class RgbToYuv420j implements Transform {
public void transform(Picture img, Picture dst) {
byte[] y = img.getData()[0];
byte[][] dstData = dst.getData();
int[][] out = new int[4][3];
int offChr = 0, offLuma = 0, offSrc = 0, strideSrc = img.getWidth() * 3, strideDst = dst.getWidth();
for (int i = 0; i < img.getHeight() >> 1; i++) {
for (int j = 0; j < img.getWidth() >> 1; j++) {
dstData[1][offChr] = 0;
dstData[2][offChr] = 0;
rgb2yuv(y[offSrc], y[offSrc + 1], y[offSrc + 2], out[0]);
dstData[0][offLuma] = (byte)out[0][0];
rgb2yuv(y[offSrc + strideSrc], y[offSrc + strideSrc + 1], y[offSrc + strideSrc + 2], out[1]);
dstData[0][offLuma + strideDst] = (byte)out[1][0];
offLuma++;
rgb2yuv(y[offSrc + 3], y[offSrc + 4], y[offSrc + 5], out[2]);
dstData[0][offLuma] = (byte)out[2][0];
rgb2yuv(y[offSrc + strideSrc + 3], y[offSrc + strideSrc + 4], y[offSrc + strideSrc + 5], out[3]);
dstData[0][offLuma + strideDst] = (byte)out[3][0];
offLuma++;
dstData[1][offChr] = (byte)(out[0][1] + out[1][1] + out[2][1] + out[3][1] + 2 >> 2);
dstData[2][offChr] = (byte)(out[0][2] + out[1][2] + out[2][2] + out[3][2] + 2 >> 2);
offChr++;
offSrc += 6;
}
offLuma += strideDst;
offSrc += strideSrc;
}
}
public static final void rgb2yuv(byte r, byte g, byte b, int[] out) {
int rS = r + 128;
int gS = g + 128;
int bS = b + 128;
int y = 77 * rS + 150 * gS + 15 * bS;
int u = -43 * rS - 85 * gS + 128 * bS;
int v = 128 * rS - 107 * gS - 21 * bS;
y = y + 128 >> 8;
u = u + 128 >> 8;
v = v + 128 >> 8;
out[0] = MathUtil.clip(y - 128, -128, 127);
out[1] = MathUtil.clip(u, -128, 127);
out[2] = MathUtil.clip(v, -128, 127);
}
}

View file

@ -0,0 +1,50 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
import org.jcodec.common.tools.MathUtil;
public class RgbToYuv420p implements Transform {
public void transform(Picture img, Picture dst) {
byte[] y = img.getData()[0];
byte[][] dstData = dst.getData();
byte[][] out = new byte[4][3];
int offChr = 0, offLuma = 0, offSrc = 0, strideSrc = img.getWidth() * 3, strideDst = dst.getWidth();
for (int i = 0; i < img.getHeight() >> 1; i++) {
for (int j = 0; j < img.getWidth() >> 1; j++) {
dstData[1][offChr] = 0;
dstData[2][offChr] = 0;
rgb2yuv(y[offSrc], y[offSrc + 1], y[offSrc + 2], out[0]);
dstData[0][offLuma] = out[0][0];
rgb2yuv(y[offSrc + strideSrc], y[offSrc + strideSrc + 1], y[offSrc + strideSrc + 2], out[1]);
dstData[0][offLuma + strideDst] = out[1][0];
offLuma++;
rgb2yuv(y[offSrc + 3], y[offSrc + 4], y[offSrc + 5], out[2]);
dstData[0][offLuma] = out[2][0];
rgb2yuv(y[offSrc + strideSrc + 3], y[offSrc + strideSrc + 4], y[offSrc + strideSrc + 5], out[3]);
dstData[0][offLuma + strideDst] = out[3][0];
offLuma++;
dstData[1][offChr] = (byte)(out[0][1] + out[1][1] + out[2][1] + out[3][1] + 2 >> 2);
dstData[2][offChr] = (byte)(out[0][2] + out[1][2] + out[2][2] + out[3][2] + 2 >> 2);
offChr++;
offSrc += 6;
}
offLuma += strideDst;
offSrc += strideSrc;
}
}
public static final void rgb2yuv(byte r, byte g, byte b, byte[] out) {
int rS = r + 128;
int gS = g + 128;
int bS = b + 128;
int y = 66 * rS + 129 * gS + 25 * bS;
int u = -38 * rS - 74 * gS + 112 * bS;
int v = 112 * rS - 94 * gS - 18 * bS;
y = y + 128 >> 8;
u = u + 128 >> 8;
v = v + 128 >> 8;
out[0] = (byte)MathUtil.clip(y - 112, -128, 127);
out[1] = (byte)MathUtil.clip(u, -128, 127);
out[2] = (byte)MathUtil.clip(v, -128, 127);
}
}

View file

@ -0,0 +1,25 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
public class RgbToYuv422p implements Transform {
public void transform(Picture img, Picture dst) {
byte[] y = img.getData()[0];
byte[] out1 = new byte[3];
byte[] out2 = new byte[3];
byte[][] dstData = dst.getData();
int off = 0, offSrc = 0;
for (int i = 0; i < img.getHeight(); i++) {
for (int j = 0; j < img.getWidth() >> 1; j++) {
int offY = off << 1;
RgbToYuv420p.rgb2yuv(y[offSrc++], y[offSrc++], y[offSrc++], out1);
dstData[0][offY] = out1[0];
RgbToYuv420p.rgb2yuv(y[offSrc++], y[offSrc++], y[offSrc++], out2);
dstData[0][offY + 1] = out2[0];
dstData[1][off] = (byte)(out1[1] + out2[1] + 1 >> 1);
dstData[2][off] = (byte)(out1[2] + out2[2] + 1 >> 1);
off++;
}
}
}
}

View file

@ -0,0 +1,11 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
public interface Transform {
void transform(Picture paramPicture1, Picture paramPicture2);
public enum Levels {
STUDIO, PC;
}
}

View file

@ -0,0 +1,74 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
import org.jcodec.common.tools.MathUtil;
public class Yuv420jToRgb implements Transform {
private static final int SCALEBITS = 10;
private static final int ONE_HALF = 512;
public final void transform(Picture src, Picture dst) {
byte[] y = src.getPlaneData(0);
byte[] u = src.getPlaneData(1);
byte[] v = src.getPlaneData(2);
byte[] data = dst.getPlaneData(0);
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;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
YUVJtoRGB(y[offLuma + j + 1], u[offChroma], v[offChroma], data, (offLuma + j + 1) * 3);
YUVJtoRGB(y[offLuma + j + stride], u[offChroma], v[offChroma], data, (offLuma + j + stride) * 3);
YUVJtoRGB(y[offLuma + j + stride + 1], u[offChroma], v[offChroma], data, (offLuma + j + stride + 1) * 3);
offChroma++;
}
if ((dst.getWidth() & 0x1) != 0) {
int j = dst.getWidth() - 1;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
YUVJtoRGB(y[offLuma + j + stride], u[offChroma], v[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;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
YUVJtoRGB(y[offLuma + j + 1], u[offChroma], v[offChroma], data, (offLuma + j + 1) * 3);
offChroma++;
}
if ((dst.getWidth() & 0x1) != 0) {
int j = dst.getWidth() - 1;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
offChroma++;
}
}
}
private static final int FIX(double x) {
return (int)(x * 1024.0D + 0.5D);
}
private static final int FIX_0_71414 = FIX(0.71414D);
private static final int FIX_1_772 = FIX(1.772D);
private static final int _FIX_0_34414 = -FIX(0.34414D);
private static final int FIX_1_402 = FIX(1.402D);
public static final void YUVJtoRGB(byte y, byte cb, byte cr, byte[] data, int off) {
int y_ = y + 128 << 10;
int add_r = FIX_1_402 * cr + 512;
int add_g = _FIX_0_34414 * cb - FIX_0_71414 * cr + 512;
int add_b = FIX_1_772 * cb + 512;
int r = y_ + add_r >> 10;
int g = y_ + add_g >> 10;
int b = y_ + add_b >> 10;
data[off] = (byte)MathUtil.clip(r - 128, -128, 127);
data[off + 1] = (byte)MathUtil.clip(g - 128, -128, 127);
data[off + 2] = (byte)MathUtil.clip(b - 128, -128, 127);
}
}

View file

@ -0,0 +1,95 @@
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));
}
}

View file

@ -0,0 +1,57 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
public class Yuv420pToYuv422p implements Transform {
public void transform(Picture src, Picture dst) {
copy(src.getPlaneData(0), dst.getPlaneData(0), src.getWidth(), dst.getWidth(), dst.getHeight());
_copy(src.getPlaneData(1), dst.getPlaneData(1), 0, 0, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight());
_copy(src.getPlaneData(1), dst.getPlaneData(1), 0, 1, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight());
_copy(src.getPlaneData(2), dst.getPlaneData(2), 0, 0, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight());
_copy(src.getPlaneData(2), dst.getPlaneData(2), 0, 1, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight());
}
private static final void _copy(byte[] src, byte[] dest, int offX, int offY, int stepX, int stepY, int strideSrc, int strideDest, int heightSrc, int heightDst) {
int offD = offX + offY * strideDest, srcOff = 0;
for (int i = 0; i < heightSrc; i++) {
for (int k = 0; k < strideSrc; k++) {
dest[offD] = src[srcOff++];
offD += stepX;
}
int lastOff = offD - stepX;
for (int m = strideSrc * stepX; m < strideDest; m += stepX) {
dest[offD] = dest[lastOff];
offD += stepX;
}
offD += (stepY - 1) * strideDest;
}
int lastLine = offD - stepY * strideDest;
for (int j = heightSrc * stepY; j < heightDst; j += stepY) {
for (int k = 0; k < strideDest; k += stepX) {
dest[offD] = dest[lastLine + k];
offD += stepX;
}
offD += (stepY - 1) * strideDest;
}
}
private static void copy(byte[] src, byte[] dest, int srcWidth, int dstWidth, int dstHeight) {
int height = src.length / srcWidth;
int dstOff = 0, srcOff = 0;
for (int i = 0; i < height; i++) {
for (int m = 0; m < srcWidth; m++)
dest[dstOff++] = src[srcOff++];
for (int k = srcWidth; k < dstWidth; k++)
dest[dstOff++] = dest[srcWidth - 1];
}
int lastLine = (height - 1) * dstWidth;
for (int j = height; j < dstHeight; j++) {
for (int k = 0; k < dstWidth; k++)
dest[dstOff++] = dest[lastLine + k];
}
}
}

View file

@ -0,0 +1,34 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
import org.jcodec.common.tools.MathUtil;
public class Yuv422pToRgb implements Transform {
public void transform(Picture src, Picture dst) {
byte[] y = src.getPlaneData(0);
byte[] u = src.getPlaneData(1);
byte[] v = src.getPlaneData(2);
byte[] data = dst.getPlaneData(0);
int offLuma = 0, offChroma = 0;
for (int i = 0; i < dst.getHeight(); i++) {
for (int j = 0; j < dst.getWidth(); j += 2) {
YUV444toRGB888(y[offLuma], u[offChroma], v[offChroma], data, offLuma * 3);
YUV444toRGB888(y[offLuma + 1], u[offChroma], v[offChroma], data, (offLuma + 1) * 3);
offLuma += 2;
offChroma++;
}
}
}
public static final void YUV444toRGB888(byte y, byte u, byte v, byte[] data, int off) {
int c = y + 112;
int d = u;
int e = v;
int r = 298 * c + 409 * e + 128 >> 8;
int g = 298 * c - 100 * d - 208 * e + 128 >> 8;
int b = 298 * c + 516 * d + 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);
}
}

View file

@ -0,0 +1,21 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
public class Yuv422pToYuv420p implements Transform {
public void transform(Picture src, Picture dst) {
int lumaSize = src.getWidth() * src.getHeight();
System.arraycopy(src.getPlaneData(0), 0, dst.getPlaneData(0), 0, lumaSize);
copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1));
copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2));
}
private void copyAvg(byte[] src, byte[] dst, int width, int height) {
int offSrc = 0, offDst = 0;
for (int y = 0; y < height / 2; y++) {
for (int x = 0; x < width; x++, offDst++, offSrc++)
dst[offDst] = (byte)(src[offSrc] + src[offSrc + width] + 1 >> 1);
offSrc += width;
}
}
}

View file

@ -0,0 +1,19 @@
package org.jcodec.scale;
import org.jcodec.common.model.Picture;
public class Yuv444jToYuv420j implements Transform {
public void transform(Picture src, Picture dst) {
int size = src.getWidth() * src.getHeight();
System.arraycopy(src.getPlaneData(0), 0, dst.getPlaneData(0), 0, size);
for (int plane = 1; plane < 3; plane++) {
byte[] srcPl = src.getPlaneData(plane);
byte[] dstPl = dst.getPlaneData(plane);
int srcStride = src.getPlaneWidth(plane);
for (int y = 0, srcOff = 0, dstOff = 0; y < src.getHeight(); y += 2, srcOff += srcStride) {
for (int x = 0; x < src.getWidth(); x += 2, srcOff += 2, dstOff++)
dstPl[dstOff] = (byte)(srcPl[srcOff] + srcPl[srcOff + 1] + srcPl[srcOff + srcStride] + srcPl[srcOff + srcStride + 1] + 2 >> 2);
}
}
}
}

View file

@ -0,0 +1,78 @@
package org.jcodec.scale.highbd;
import java.util.HashMap;
import java.util.Map;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.PictureHiBD;
public class ColorUtilHiBD {
private static Map<ColorSpace, Map<ColorSpace, TransformHiBD>> map = new HashMap<>();
static {
Map<ColorSpace, TransformHiBD> rgb = new HashMap<>();
rgb.put(ColorSpace.RGB, new Idential());
rgb.put(ColorSpace.YUV420, new RgbToYuv420pHiBD(0, 0));
rgb.put(ColorSpace.YUV420J, new RgbToYuv420jHiBD());
rgb.put(ColorSpace.YUV422, new RgbToYuv422pHiBD(0, 0));
rgb.put(ColorSpace.YUV422_10, new RgbToYuv422pHiBD(2, 0));
map.put(ColorSpace.RGB, rgb);
Map<ColorSpace, TransformHiBD> yuv420 = new HashMap<>();
yuv420.put(ColorSpace.YUV420, new Idential());
yuv420.put(ColorSpace.RGB, new Yuv420pToRgbHiBD(0, 0));
yuv420.put(ColorSpace.YUV422, new Yuv420pToYuv422pHiBD(0, 0));
yuv420.put(ColorSpace.YUV422_10, new Yuv420pToYuv422pHiBD(0, 2));
map.put(ColorSpace.YUV420, yuv420);
Map<ColorSpace, TransformHiBD> yuv422 = new HashMap<>();
yuv422.put(ColorSpace.YUV422, new Idential());
yuv422.put(ColorSpace.RGB, new Yuv422pToRgbHiBD(0, 0));
yuv422.put(ColorSpace.YUV420, new Yuv422pToYuv420pHiBD(0, 0));
yuv422.put(ColorSpace.YUV420J, new Yuv422pToYuv420jHiBD(0, 0));
map.put(ColorSpace.YUV422, yuv422);
Map<ColorSpace, TransformHiBD> yuv422_10 = new HashMap<>();
yuv422_10.put(ColorSpace.YUV422_10, new Idential());
yuv422_10.put(ColorSpace.RGB, new Yuv422pToRgbHiBD(2, 0));
yuv422_10.put(ColorSpace.YUV420, new Yuv422pToYuv420pHiBD(0, 2));
yuv422_10.put(ColorSpace.YUV420J, new Yuv422pToYuv420jHiBD(0, 2));
map.put(ColorSpace.YUV422_10, yuv422_10);
Map<ColorSpace, TransformHiBD> yuv444 = new HashMap<>();
yuv444.put(ColorSpace.YUV444, new Idential());
yuv444.put(ColorSpace.RGB, new Yuv444pToRgb(0, 0));
yuv444.put(ColorSpace.YUV420, new Yuv444pToYuv420pHiBD(0, 0));
map.put(ColorSpace.YUV444, yuv444);
Map<ColorSpace, TransformHiBD> yuv444_10 = new HashMap<>();
yuv444_10.put(ColorSpace.YUV444_10, new Idential());
yuv444_10.put(ColorSpace.RGB, new Yuv444pToRgb(2, 0));
yuv444_10.put(ColorSpace.YUV420, new Yuv444pToYuv420pHiBD(0, 2));
map.put(ColorSpace.YUV444_10, yuv444_10);
Map<ColorSpace, TransformHiBD> yuv420j = new HashMap<>();
yuv420j.put(ColorSpace.YUV420J, new Idential());
yuv420j.put(ColorSpace.RGB, new Yuv420jToRgbHiBD());
yuv420j.put(ColorSpace.YUV420, new Yuv420jToYuv420HiBD());
map.put(ColorSpace.YUV420J, yuv420j);
Map<ColorSpace, TransformHiBD> yuv422j = new HashMap<>();
yuv422j.put(ColorSpace.YUV422J, new Idential());
yuv422j.put(ColorSpace.RGB, new Yuv422jToRgbHiBD());
yuv422j.put(ColorSpace.YUV420, new Yuv422jToYuv420pHiBD());
yuv422j.put(ColorSpace.YUV420J, new Yuv422pToYuv420pHiBD(0, 0));
map.put(ColorSpace.YUV422J, yuv422j);
Map<ColorSpace, TransformHiBD> yuv444j = new HashMap<>();
yuv444j.put(ColorSpace.YUV444J, new Idential());
yuv444j.put(ColorSpace.RGB, new Yuv444jToRgbHiBD());
yuv444j.put(ColorSpace.YUV420, new Yuv444jToYuv420pHiBD());
yuv444j.put(ColorSpace.YUV420J, new Yuv444pToYuv420pHiBD(0, 0));
map.put(ColorSpace.YUV444J, yuv444j);
}
public static TransformHiBD getTransform(ColorSpace from, ColorSpace to) {
Map<ColorSpace, TransformHiBD> map2 = map.get(from);
return (map2 == null) ? null : map2.get(to);
}
public static class Idential implements TransformHiBD {
public void transform(PictureHiBD src, PictureHiBD dst) {
for (int i = 0; i < 3; i++)
System.arraycopy(src.getPlaneData(i), 0, dst.getPlaneData(i), 0, Math.min(
src.getPlaneWidth(i) * src.getPlaneHeight(i), dst.getPlaneWidth(i) * dst.getPlaneHeight(i)));
}
}
}

View file

@ -0,0 +1,24 @@
package org.jcodec.scale.highbd;
import org.jcodec.api.NotSupportedException;
import org.jcodec.common.model.ColorSpace;
import org.jcodec.common.model.PictureHiBD;
@Deprecated
public class RgbToBgrHiBD implements TransformHiBD {
public void transform(PictureHiBD src, PictureHiBD dst) {
if ((src.getColor() != ColorSpace.RGB && src.getColor() != ColorSpace.BGR) || (
dst.getColor() != ColorSpace.RGB && dst.getColor() != ColorSpace.BGR))
throw new IllegalArgumentException("Expected RGB or BGR inputs, was: " +
String.valueOf(src.getColor()) + ", " + String.valueOf(dst.getColor()));
if (src.getCrop() != null || dst.getCrop() != null)
throw new NotSupportedException("Cropped images not supported");
int[] dataSrc = src.getPlaneData(0);
int[] dataDst = dst.getPlaneData(0);
for (int i = 0; i < dataSrc.length; i += 3) {
int tmp = dataSrc[i + 2];
dataDst[i + 2] = dataSrc[i];
dataDst[i] = tmp;
}
}
}

View file

@ -0,0 +1,49 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class RgbToYuv420jHiBD implements TransformHiBD {
public void transform(PictureHiBD img, PictureHiBD dst) {
int[] y = img.getData()[0];
int[][] dstData = dst.getData();
int offChr = 0, offLuma = 0, offSrc = 0, strideSrc = img.getWidth() * 3, strideDst = dst.getWidth();
for (int i = 0; i < img.getHeight() >> 1; i++) {
for (int j = 0; j < img.getWidth() >> 1; j++) {
dstData[1][offChr] = 0;
dstData[2][offChr] = 0;
rgb2yuv(y[offSrc], y[offSrc + 1], y[offSrc + 2], dstData[0], offLuma, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma] = dstData[0][offLuma];
rgb2yuv(y[offSrc + strideSrc], y[offSrc + strideSrc + 1], y[offSrc + strideSrc + 2], dstData[0], offLuma + strideDst, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma + strideDst] = dstData[0][offLuma + strideDst];
offLuma++;
rgb2yuv(y[offSrc + 3], y[offSrc + 4], y[offSrc + 5], dstData[0], offLuma, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma] = dstData[0][offLuma];
rgb2yuv(y[offSrc + strideSrc + 3], y[offSrc + strideSrc + 4], y[offSrc + strideSrc + 5], dstData[0], offLuma + strideDst, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma + strideDst] = dstData[0][offLuma + strideDst];
offLuma++;
dstData[1][offChr] = dstData[1][offChr] >> 2;
dstData[2][offChr] = dstData[2][offChr] >> 2;
offChr++;
offSrc += 6;
}
offLuma += strideDst;
offSrc += strideSrc;
}
}
public static final void rgb2yuv(int r, int g, int b, int[] Y, int offY, int[] U, int offU, int[] V, int offV) {
int y = 77 * r + 150 * g + 15 * b;
int u = -43 * r - 85 * g + 128 * b;
int v = 128 * r - 107 * g - 21 * b;
y = y + 128 >> 8;
u = u + 128 >> 8;
v = v + 128 >> 8;
Y[offY] = clip(y);
U[offU] = U[offU] + clip(u + 128);
V[offV] = V[offV] + clip(v + 128);
}
private static final int clip(int val) {
return (val < 0) ? 0 : ((val > 255) ? 255 : val);
}
}

View file

@ -0,0 +1,61 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class RgbToYuv420pHiBD implements TransformHiBD {
private int upShift;
private int downShift;
private int downShiftChr;
public RgbToYuv420pHiBD(int upShift, int downShift) {
this.upShift = upShift;
this.downShift = downShift;
this.downShiftChr = downShift + 2;
}
public void transform(PictureHiBD img, PictureHiBD dst) {
int[] y = img.getData()[0];
int[][] dstData = dst.getData();
int offChr = 0, offLuma = 0, offSrc = 0, strideSrc = img.getWidth() * 3, strideDst = dst.getWidth();
for (int i = 0; i < img.getHeight() >> 1; i++) {
for (int j = 0; j < img.getWidth() >> 1; j++) {
dstData[1][offChr] = 0;
dstData[2][offChr] = 0;
rgb2yuv(y[offSrc], y[offSrc + 1], y[offSrc + 2], dstData[0], offLuma, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma] = dstData[0][offLuma] << this.upShift >> this.downShift;
rgb2yuv(y[offSrc + strideSrc], y[offSrc + strideSrc + 1], y[offSrc + strideSrc + 2], dstData[0], offLuma + strideDst, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma + strideDst] = dstData[0][offLuma + strideDst] << this.upShift >> this.downShift;
offLuma++;
rgb2yuv(y[offSrc + 3], y[offSrc + 4], y[offSrc + 5], dstData[0], offLuma, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma] = dstData[0][offLuma] << this.upShift >> this.downShift;
rgb2yuv(y[offSrc + strideSrc + 3], y[offSrc + strideSrc + 4], y[offSrc + strideSrc + 5], dstData[0], offLuma + strideDst, dstData[1], offChr, dstData[2], offChr);
dstData[0][offLuma + strideDst] = dstData[0][offLuma + strideDst] << this.upShift >> this.downShift;
offLuma++;
dstData[1][offChr] = dstData[1][offChr] << this.upShift >> this.downShiftChr;
dstData[2][offChr] = dstData[2][offChr] << this.upShift >> this.downShiftChr;
offChr++;
offSrc += 6;
}
offLuma += strideDst;
offSrc += strideSrc;
}
}
public static final void rgb2yuv(int r, int g, int b, int[] Y, int offY, int[] U, int offU, int[] V, int offV) {
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[offY] = clip(y + 16);
U[offU] = U[offU] + clip(u + 128);
V[offV] = V[offV] + clip(v + 128);
}
private static final int clip(int val) {
return (val < 0) ? 0 : ((val > 255) ? 255 : val);
}
}

View file

@ -0,0 +1,37 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class RgbToYuv422pHiBD implements TransformHiBD {
private int upShift;
private int downShift;
private int downShiftChr;
public RgbToYuv422pHiBD(int upShift, int downShift) {
this.upShift = upShift;
this.downShift = downShift;
this.downShiftChr = downShift + 1;
}
public void transform(PictureHiBD img, PictureHiBD dst) {
int[] y = img.getData()[0];
int[][] dstData = dst.getData();
int off = 0, offSrc = 0;
for (int i = 0; i < img.getHeight(); i++) {
for (int j = 0; j < img.getWidth() >> 1; j++) {
dstData[1][off] = 0;
dstData[2][off] = 0;
int offY = off << 1;
RgbToYuv420pHiBD.rgb2yuv(y[offSrc++], y[offSrc++], y[offSrc++], dstData[0], offY, dstData[1], off, dstData[2], off);
dstData[0][offY] = dstData[0][offY] << this.upShift >> this.downShift;
RgbToYuv420pHiBD.rgb2yuv(y[offSrc++], y[offSrc++], y[offSrc++], dstData[0], offY + 1, dstData[1], off, dstData[2], off);
dstData[0][offY + 1] = dstData[0][offY + 1] << this.upShift >> this.downShift;
dstData[1][off] = dstData[1][off] << this.upShift >> this.downShiftChr;
dstData[2][off] = dstData[2][off] << this.upShift >> this.downShiftChr;
off++;
}
}
}
}

View file

@ -0,0 +1,11 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public interface TransformHiBD {
void transform(PictureHiBD paramPictureHiBD1, PictureHiBD paramPictureHiBD2);
public enum Levels {
STUDIO, PC;
}
}

View file

@ -0,0 +1,76 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
import org.jcodec.common.tools.MathUtil;
public class Yuv420jToRgbHiBD implements TransformHiBD {
private static final int SCALEBITS = 10;
private static final int ONE_HALF = 512;
public final void transform(PictureHiBD src, PictureHiBD dst) {
int[] y = src.getPlaneData(0);
int[] u = src.getPlaneData(1);
int[] v = src.getPlaneData(2);
int[] data = dst.getPlaneData(0);
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;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
YUVJtoRGB(y[offLuma + j + 1], u[offChroma], v[offChroma], data, (offLuma + j + 1) * 3);
YUVJtoRGB(y[offLuma + j + stride], u[offChroma], v[offChroma], data, (offLuma + j + stride) * 3);
YUVJtoRGB(y[offLuma + j + stride + 1], u[offChroma], v[offChroma], data, (offLuma + j + stride + 1) * 3);
offChroma++;
}
if ((dst.getWidth() & 0x1) != 0) {
int j = dst.getWidth() - 1;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
YUVJtoRGB(y[offLuma + j + stride], u[offChroma], v[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;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
YUVJtoRGB(y[offLuma + j + 1], u[offChroma], v[offChroma], data, (offLuma + j + 1) * 3);
offChroma++;
}
if ((dst.getWidth() & 0x1) != 0) {
int j = dst.getWidth() - 1;
YUVJtoRGB(y[offLuma + j], u[offChroma], v[offChroma], data, (offLuma + j) * 3);
offChroma++;
}
}
}
private static final int FIX(double x) {
return (int)(x * 1024.0D + 0.5D);
}
private static final int FIX_0_71414 = FIX(0.71414D);
private static final int FIX_1_772 = FIX(1.772D);
private static final int _FIX_0_34414 = -FIX(0.34414D);
private static final int FIX_1_402 = FIX(1.402D);
public static final void YUVJtoRGB(int y, int cb, int cr, int[] data, int off) {
y <<= 10;
cb -= 128;
cr -= 128;
int add_r = FIX_1_402 * cr + 512;
int add_g = _FIX_0_34414 * cb - FIX_0_71414 * cr + 512;
int add_b = FIX_1_772 * cb + 512;
int r = y + add_r >> 10;
int g = y + add_g >> 10;
int b = y + add_b >> 10;
data[off] = MathUtil.clip(r, 0, 255);
data[off + 1] = MathUtil.clip(g, 0, 255);
data[off + 2] = MathUtil.clip(b, 0, 255);
}
}

View file

@ -0,0 +1,22 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv420jToYuv420HiBD implements TransformHiBD {
public static int Y_COEFF = 7168;
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] sy = src.getPlaneData(0);
int[] dy = dst.getPlaneData(0);
for (int i = 0; i < src.getPlaneWidth(0) * src.getPlaneHeight(0); i++)
dy[i] = (sy[i] * Y_COEFF >> 13) + 16;
int[] su = src.getPlaneData(1);
int[] du = dst.getPlaneData(1);
for (int j = 0; j < src.getPlaneWidth(1) * src.getPlaneHeight(1); j++)
du[j] = ((su[j] - 128) * Y_COEFF >> 13) + 128;
int[] sv = src.getPlaneData(2);
int[] dv = dst.getPlaneData(2);
for (int k = 0; k < src.getPlaneWidth(2) * src.getPlaneHeight(2); k++)
dv[k] = ((sv[k] - 128) * Y_COEFF >> 13) + 128;
}
}

View file

@ -0,0 +1,53 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv420pToRgbHiBD implements TransformHiBD {
private final int downShift;
private final int upShift;
public Yuv420pToRgbHiBD(int upShift, int downShift) {
this.upShift = upShift;
this.downShift = downShift;
}
public final void transform(PictureHiBD src, PictureHiBD dst) {
int[] y = src.getPlaneData(0);
int[] u = src.getPlaneData(1);
int[] v = src.getPlaneData(2);
int[] data = dst.getPlaneData(0);
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;
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j) * 3);
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j + 1] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j + 1) * 3);
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j + stride] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j + stride) * 3);
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j + stride + 1] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j + stride + 1) * 3);
offChroma++;
}
if ((dst.getWidth() & 0x1) != 0) {
int j = dst.getWidth() - 1;
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j) * 3);
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j + stride] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, 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;
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j) * 3);
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j + 1] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j + 1) * 3);
offChroma++;
}
if ((dst.getWidth() & 0x1) != 0) {
int j = dst.getWidth() - 1;
Yuv422pToRgbHiBD.YUV444toRGB888(y[offLuma + j] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + j) * 3);
offChroma++;
}
}
}
}

View file

@ -0,0 +1,66 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv420pToYuv422pHiBD implements TransformHiBD {
private int shiftUp;
private int shiftDown;
public Yuv420pToYuv422pHiBD(int shiftUp, int shiftDown) {
this.shiftUp = shiftUp;
this.shiftDown = shiftDown;
}
public void transform(PictureHiBD src, PictureHiBD dst) {
copy(src.getPlaneData(0), dst.getPlaneData(0), src.getWidth(), dst.getWidth(), dst.getHeight(), this.shiftUp, this.shiftDown);
_copy(src.getPlaneData(1), dst.getPlaneData(1), 0, 0, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight(), this.shiftUp, this.shiftDown);
_copy(src.getPlaneData(1), dst.getPlaneData(1), 0, 1, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight(), this.shiftUp, this.shiftDown);
_copy(src.getPlaneData(2), dst.getPlaneData(2), 0, 0, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight(), this.shiftUp, this.shiftDown);
_copy(src.getPlaneData(2), dst.getPlaneData(2), 0, 1, 1, 2, src.getWidth() >> 1, dst.getWidth() >> 1,
src.getHeight() >> 1, dst.getHeight(), this.shiftUp, this.shiftDown);
}
private static final void _copy(int[] src, int[] dest, int offX, int offY, int stepX, int stepY, int strideSrc, int strideDest, int heightSrc, int heightDst, int upShift, int downShift) {
int offD = offX + offY * strideDest, srcOff = 0;
for (int i = 0; i < heightSrc; i++) {
for (int k = 0; k < strideSrc; k++) {
dest[offD] = (src[srcOff++] & 0xFF) << 2;
offD += stepX;
}
int lastOff = offD - stepX;
for (int m = strideSrc * stepX; m < strideDest; m += stepX) {
dest[offD] = dest[lastOff];
offD += stepX;
}
offD += (stepY - 1) * strideDest;
}
int lastLine = offD - stepY * strideDest;
for (int j = heightSrc * stepY; j < heightDst; j += stepY) {
for (int k = 0; k < strideDest; k += stepX) {
dest[offD] = dest[lastLine + k];
offD += stepX;
}
offD += (stepY - 1) * strideDest;
}
}
private static void copy(int[] src, int[] dest, int srcWidth, int dstWidth, int dstHeight, int shiftUp, int shiftDown) {
int height = src.length / srcWidth;
int dstOff = 0, srcOff = 0;
for (int i = 0; i < height; i++) {
for (int m = 0; m < srcWidth; m++)
dest[dstOff++] = (src[srcOff++] & 0xFF) << 2;
for (int k = srcWidth; k < dstWidth; k++)
dest[dstOff++] = dest[srcWidth - 1];
}
int lastLine = (height - 1) * dstWidth;
for (int j = height; j < dstHeight; j++) {
for (int k = 0; k < dstWidth; k++)
dest[dstOff++] = dest[lastLine + k];
}
}
}

View file

@ -0,0 +1,21 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv422jToRgbHiBD implements TransformHiBD {
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] y = src.getPlaneData(0);
int[] u = src.getPlaneData(1);
int[] v = src.getPlaneData(2);
int[] data = dst.getPlaneData(0);
int offLuma = 0, offChroma = 0;
for (int i = 0; i < dst.getHeight(); i++) {
for (int j = 0; j < dst.getWidth(); j += 2) {
Yuv420jToRgbHiBD.YUVJtoRGB(y[offLuma], u[offChroma], v[offChroma], data, offLuma * 3);
Yuv420jToRgbHiBD.YUVJtoRGB(y[offLuma + 1], u[offChroma], v[offChroma], data, (offLuma + 1) * 3);
offLuma += 2;
offChroma++;
}
}
}
}

View file

@ -0,0 +1,28 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv422jToYuv420pHiBD implements TransformHiBD {
public static int Y_COEFF = 7168;
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] sy = src.getPlaneData(0);
int[] dy = dst.getPlaneData(0);
for (int i = 0; i < src.getPlaneWidth(0) * src.getPlaneHeight(0); i++)
dy[i] = (sy[i] * Y_COEFF >> 13) + 16;
copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1));
copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2));
}
private void copyAvg(int[] src, int[] dst, int width, int height) {
int offSrc = 0, offDst = 0;
for (int y = 0; y < height / 2; y++) {
for (int x = 0; x < width; x++, offDst++, offSrc++) {
int a = ((src[offSrc] - 128) * Y_COEFF >> 13) + 128;
int b = ((src[offSrc + width] - 128) * Y_COEFF >> 13) + 128;
dst[offDst] = a + b + 1 >> 1;
}
offSrc += width;
}
}
}

View file

@ -0,0 +1,46 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv422pToRgbHiBD implements TransformHiBD {
private int downShift;
private int upShift;
public Yuv422pToRgbHiBD(int downShift, int upShift) {
this.downShift = downShift;
this.upShift = upShift;
}
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] y = src.getPlaneData(0);
int[] u = src.getPlaneData(1);
int[] v = src.getPlaneData(2);
int[] data = dst.getPlaneData(0);
int offLuma = 0, offChroma = 0;
for (int i = 0; i < dst.getHeight(); i++) {
for (int j = 0; j < dst.getWidth(); j += 2) {
YUV444toRGB888(y[offLuma] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, offLuma * 3);
YUV444toRGB888(y[offLuma + 1] << this.upShift >> this.downShift, u[offChroma] << this.upShift >> this.downShift, v[offChroma] << this.upShift >> this.downShift, data, (offLuma + 1) * 3);
offLuma += 2;
offChroma++;
}
}
}
public static final void YUV444toRGB888(int y, int u, int v, int[] data, int off) {
int c = y - 16;
int d = u - 128;
int e = v - 128;
int r = 298 * c + 409 * e + 128 >> 8;
int g = 298 * c - 100 * d - 208 * e + 128 >> 8;
int b = 298 * c + 516 * d + 128 >> 8;
data[off] = crop(r);
data[off + 1] = crop(g);
data[off + 2] = crop(b);
}
private static int crop(int val) {
return (val < 0) ? 0 : ((val > 255) ? 255 : val);
}
}

View file

@ -0,0 +1,42 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv422pToYuv420jHiBD implements TransformHiBD {
public static int COEFF = 9362;
private int shift;
private int halfSrc;
private int halfDst;
public Yuv422pToYuv420jHiBD(int upshift, int downshift) {
this.shift = downshift + 13 - upshift;
if (this.shift < 0)
throw new IllegalArgumentException("Maximum upshift allowed: " + downshift + 13);
this.halfSrc = 128 << Math.max(downshift - upshift, 0);
this.halfDst = 128 << Math.max(upshift - downshift, 0);
}
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] sy = src.getPlaneData(0);
int[] dy = dst.getPlaneData(0);
for (int i = 0; i < src.getPlaneWidth(0) * src.getPlaneHeight(0); i++)
dy[i] = (sy[i] - 16) * COEFF >> this.shift;
copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1));
copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2));
}
private void copyAvg(int[] src, int[] dst, int width, int height) {
int offSrc = 0, offDst = 0;
for (int y = 0; y < height / 2; y++) {
for (int x = 0; x < width; x++, offDst++, offSrc++) {
int a = ((src[offSrc] - this.halfSrc) * COEFF >> this.shift) + this.halfDst;
int b = ((src[offSrc + width] - this.halfSrc) * COEFF >> this.shift) + this.halfDst;
dst[offDst] = a + b + 1 >> 1;
}
offSrc += width;
}
}
}

View file

@ -0,0 +1,49 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv422pToYuv420pHiBD implements TransformHiBD {
private int shiftUp;
private int shiftDown;
public Yuv422pToYuv420pHiBD(int shiftUp, int shiftDown) {
this.shiftUp = shiftUp;
this.shiftDown = shiftDown;
}
public void transform(PictureHiBD src, PictureHiBD dst) {
int lumaSize = src.getWidth() * src.getHeight();
System.arraycopy(src.getPlaneData(0), 0, dst.getPlaneData(0), 0, lumaSize);
copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1));
copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2));
if (this.shiftUp > this.shiftDown) {
up(dst.getPlaneData(0), this.shiftUp - this.shiftDown);
up(dst.getPlaneData(1), this.shiftUp - this.shiftDown);
up(dst.getPlaneData(2), this.shiftUp - this.shiftDown);
} else if (this.shiftDown > this.shiftUp) {
down(dst.getPlaneData(0), this.shiftDown - this.shiftUp);
down(dst.getPlaneData(1), this.shiftDown - this.shiftUp);
down(dst.getPlaneData(2), this.shiftDown - this.shiftUp);
}
}
private void down(int[] dst, int down) {
for (int i = 0; i < dst.length; i++)
dst[i] = dst[i] >> down;
}
private void up(int[] dst, int up) {
for (int i = 0; i < dst.length; i++)
dst[i] = dst[i] << up;
}
private void copyAvg(int[] src, int[] dst, int width, int height) {
int offSrc = 0, offDst = 0;
for (int y = 0; y < height / 2; y++) {
for (int x = 0; x < width; x++, offDst++, offSrc++)
dst[offDst] = src[offSrc] + src[offSrc + width] + 1 >> 1;
offSrc += width;
}
}
}

View file

@ -0,0 +1,16 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv444jToRgbHiBD implements TransformHiBD {
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] y = src.getPlaneData(0);
int[] u = src.getPlaneData(1);
int[] v = src.getPlaneData(2);
int[] data = dst.getPlaneData(0);
for (int i = 0, srcOff = 0, dstOff = 0; i < dst.getHeight(); i++) {
for (int j = 0; j < dst.getWidth(); j++, srcOff++, dstOff += 3)
Yuv420jToRgbHiBD.YUVJtoRGB(y[srcOff], u[srcOff], v[srcOff], data, dstOff);
}
}
}

View file

@ -0,0 +1,30 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv444jToYuv420pHiBD implements TransformHiBD {
public static int Y_COEFF = 7168;
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] sy = src.getPlaneData(0);
int[] dy = dst.getPlaneData(0);
for (int i = 0; i < src.getPlaneWidth(0) * src.getPlaneHeight(0); i++)
dy[i] = (sy[i] * Y_COEFF >> 13) + 16;
copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1));
copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2));
}
private void copyAvg(int[] src, int[] dst, int width, int height) {
int offSrc = 0, offDst = 0;
for (int y = 0; y < height >> 1; y++) {
for (int x = 0; x < width; x += 2, offDst++, offSrc += 2) {
int a = ((src[offSrc] - 128) * Y_COEFF >> 13) + 128;
int b = ((src[offSrc + 1] - 128) * Y_COEFF >> 13) + 128;
int c = ((src[offSrc + width] - 128) * Y_COEFF >> 13) + 128;
int d = ((src[offSrc + width + 1] - 128) * Y_COEFF >> 13) + 128;
dst[offDst] = a + b + c + d + 2 >> 2;
}
offSrc += width;
}
}
}

View file

@ -0,0 +1,41 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv444pToRgb implements TransformHiBD {
private int downShift;
private int upShift;
public Yuv444pToRgb(int downShift, int upShift) {
this.downShift = downShift;
this.upShift = upShift;
}
public void transform(PictureHiBD src, PictureHiBD dst) {
int[] y = src.getPlaneData(0);
int[] u = src.getPlaneData(1);
int[] v = src.getPlaneData(2);
int[] data = dst.getPlaneData(0);
for (int i = 0, srcOff = 0, dstOff = 0; i < dst.getHeight(); i++) {
for (int j = 0; j < dst.getWidth(); j++, srcOff++, dstOff += 3)
YUV444toRGB888(y[srcOff] << this.upShift >> this.downShift, u[srcOff] << this.upShift >> this.downShift, v[srcOff] << this.upShift >> this.downShift, data, dstOff);
}
}
public static final void YUV444toRGB888(int y, int u, int v, int[] data, int off) {
int c = y - 16;
int d = u - 128;
int e = v - 128;
int r = 298 * c + 409 * e + 128 >> 8;
int g = 298 * c - 100 * d - 208 * e + 128 >> 8;
int b = 298 * c + 516 * d + 128 >> 8;
data[off] = crop(r);
data[off + 1] = crop(g);
data[off + 2] = crop(b);
}
private static int crop(int val) {
return (val < 0) ? 0 : ((val > 255) ? 255 : val);
}
}

View file

@ -0,0 +1,49 @@
package org.jcodec.scale.highbd;
import org.jcodec.common.model.PictureHiBD;
public class Yuv444pToYuv420pHiBD implements TransformHiBD {
private int shiftUp;
private int shiftDown;
public Yuv444pToYuv420pHiBD(int shiftUp, int shiftDown) {
this.shiftUp = shiftUp;
this.shiftDown = shiftDown;
}
public void transform(PictureHiBD src, PictureHiBD dst) {
int lumaSize = src.getWidth() * src.getHeight();
System.arraycopy(src.getPlaneData(0), 0, dst.getPlaneData(0), 0, lumaSize);
copyAvg(src.getPlaneData(1), dst.getPlaneData(1), src.getPlaneWidth(1), src.getPlaneHeight(1));
copyAvg(src.getPlaneData(2), dst.getPlaneData(2), src.getPlaneWidth(2), src.getPlaneHeight(2));
if (this.shiftUp > this.shiftDown) {
up(dst.getPlaneData(0), this.shiftUp - this.shiftDown);
up(dst.getPlaneData(1), this.shiftUp - this.shiftDown);
up(dst.getPlaneData(2), this.shiftUp - this.shiftDown);
} else if (this.shiftDown > this.shiftUp) {
down(dst.getPlaneData(0), this.shiftDown - this.shiftUp);
down(dst.getPlaneData(1), this.shiftDown - this.shiftUp);
down(dst.getPlaneData(2), this.shiftDown - this.shiftUp);
}
}
private void down(int[] dst, int down) {
for (int i = 0; i < dst.length; i++)
dst[i] = dst[i] >> down;
}
private void up(int[] dst, int up) {
for (int i = 0; i < dst.length; i++)
dst[i] = dst[i] << up;
}
private void copyAvg(int[] src, int[] dst, int width, int height) {
int offSrc = 0, offDst = 0;
for (int y = 0; y < height >> 1; y++) {
for (int x = 0; x < width; x += 2, offDst++, offSrc += 2)
dst[offDst] = src[offSrc] + src[offSrc + 1] + src[offSrc + width] + src[offSrc + width + 1] + 2 >> 2;
offSrc += width;
}
}
}