www in docker support
This commit is contained in:
parent
539a848e95
commit
c227fce036
2145 changed files with 399596 additions and 58 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package org.jcodec.scale;
|
||||
|
||||
public enum InterpFilter {
|
||||
LANCZOS, BICUBIC;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue