Update libjpeg-turbo to 1.5.3
Bug: 70203010
Test: Existing tests
Use commit at tag 1.5.3 (bf6c774305c9feb30cff7b99e1a475df61bfa008).
This includes a fix for decompressing grayscale JPEG images that were
compressed with a sampling factor other than 1 (b/70203010). The bug
manifested as black stripes appearing when using the region decoder.
ChangeLog.md contains more detailed changes.
Add -Wno-sign-compare to Android.bp to silence a warning in jmemnobs.c.
Change-Id: Ifefc70073fdff9c68e9b2cbcddf114c8bcb7d366
diff --git a/java/TJBench.java b/java/TJBench.java
index 19db789..ddc414c 100644
--- a/java/TJBench.java
+++ b/java/TJBench.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C)2009-2014, 2016 D. R. Commander. All Rights Reserved.
+ * Copyright (C)2009-2014, 2016-2017 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -34,8 +34,8 @@
class TJBench {
- static int flags = 0, quiet = 0, pf = TJ.PF_BGR, yuvpad = 1, warmup = 1;
- static boolean compOnly, decompOnly, doTile, doYUV, write;
+ static int flags = 0, quiet = 0, pf = TJ.PF_BGR, yuvpad = 1;
+ static boolean compOnly, decompOnly, doTile, doYUV, write = true;
static final String[] pixFormatStr = {
"RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY"
@@ -55,7 +55,7 @@
static TJScalingFactor sf;
static int xformOp = TJTransform.OP_NONE, xformOpt = 0;
- static double benchTime = 5.0;
+ static double benchTime = 5.0, warmup = 1.0;
static final double getTime() {
@@ -162,7 +162,7 @@
}
/* Benchmark */
- iter -= warmup;
+ iter = -1;
elapsed = elapsedDecode = 0.0;
while (true) {
int tile = 0;
@@ -184,11 +184,14 @@
tjd.decompress(dstBuf, x, y, width, pitch, height, pf, flags);
}
}
- iter++;
- if (iter >= 1) {
- elapsed += getTime() - start;
+ elapsed += getTime() - start;
+ if (iter >= 0) {
+ iter++;
if (elapsed >= benchTime)
break;
+ } else if (elapsed >= warmup) {
+ iter = 0;
+ elapsed = elapsedDecode = 0.0;
}
}
if(doYUV)
@@ -321,7 +324,7 @@
}
/* Benchmark */
- iter = -warmup;
+ iter = -1;
elapsed = elapsedEncode = 0.0;
while (true) {
int tile = 0;
@@ -346,11 +349,14 @@
totalJpegSize += jpegSize[tile];
}
}
- iter++;
- if (iter >= 1) {
- elapsed += getTime() - start;
+ elapsed += getTime() - start;
+ if (iter >= 0) {
+ iter++;
if (elapsed >= benchTime)
break;
+ } else if (elapsed >= warmup) {
+ iter = 0;
+ elapsed = elapsedEncode = 0.0;
}
}
if (doYUV)
@@ -541,17 +547,20 @@
}
}
- iter = -warmup;
+ iter = -1;
elapsed = 0.;
while (true) {
start = getTime();
tjt.transform(jpegBuf, t, flags);
jpegSize = tjt.getTransformedSizes();
- iter++;
- if (iter >= 1) {
- elapsed += getTime() - start;
+ elapsed += getTime() - start;
+ if (iter >= 0) {
+ iter++;
if (elapsed >= benchTime)
break;
+ } else if (elapsed >= warmup) {
+ iter = 0;
+ elapsed = 0.0;
}
}
t = null;
@@ -582,8 +591,8 @@
System.out.print("N/A N/A ");
jpegBuf = new byte[1][TJ.bufSize(_tilew, _tileh, subsamp)];
jpegSize = new int[1];
+ jpegBuf[0] = srcBuf;
jpegSize[0] = srcSize;
- System.arraycopy(srcBuf, 0, jpegBuf[0], 0, srcSize);
}
if (w == tilew)
@@ -659,8 +668,9 @@
System.out.println("-grayscale = Perform lossless grayscale conversion prior to decompression");
System.out.println(" test (can be combined with the other transforms above)");
System.out.println("-benchtime <t> = Run each benchmark for at least <t> seconds (default = 5.0)");
- System.out.println("-warmup <w> = Execute each benchmark <w> times to prime the cache before");
- System.out.println(" taking performance measurements (default = 1)");
+ System.out.println("-warmup <t> = Run each benchmark for <t> seconds (default = 1.0) prior to");
+ System.out.println(" starting the timer, in order to prime the caches and thus improve the");
+ System.out.println(" consistency of the results.");
System.out.println("-componly = Stop after running compression tests. Do not test decompression.");
System.out.println("-nowrite = Do not write reference or output images (improves consistency");
System.out.println(" of performance measurements.)\n");
@@ -711,37 +721,37 @@
if (argv[i].equalsIgnoreCase("-tile")) {
doTile = true; xformOpt |= TJTransform.OPT_CROP;
}
- if (argv[i].equalsIgnoreCase("-fastupsample")) {
+ else if (argv[i].equalsIgnoreCase("-fastupsample")) {
System.out.println("Using fast upsampling code\n");
flags |= TJ.FLAG_FASTUPSAMPLE;
}
- if (argv[i].equalsIgnoreCase("-fastdct")) {
+ else if (argv[i].equalsIgnoreCase("-fastdct")) {
System.out.println("Using fastest DCT/IDCT algorithm\n");
flags |= TJ.FLAG_FASTDCT;
}
- if (argv[i].equalsIgnoreCase("-accuratedct")) {
+ else if (argv[i].equalsIgnoreCase("-accuratedct")) {
System.out.println("Using most accurate DCT/IDCT algorithm\n");
flags |= TJ.FLAG_ACCURATEDCT;
}
- if (argv[i].equalsIgnoreCase("-rgb"))
+ else if (argv[i].equalsIgnoreCase("-rgb"))
pf = TJ.PF_RGB;
- if (argv[i].equalsIgnoreCase("-rgbx"))
+ else if (argv[i].equalsIgnoreCase("-rgbx"))
pf = TJ.PF_RGBX;
- if (argv[i].equalsIgnoreCase("-bgr"))
+ else if (argv[i].equalsIgnoreCase("-bgr"))
pf = TJ.PF_BGR;
- if (argv[i].equalsIgnoreCase("-bgrx"))
+ else if (argv[i].equalsIgnoreCase("-bgrx"))
pf = TJ.PF_BGRX;
- if (argv[i].equalsIgnoreCase("-xbgr"))
+ else if (argv[i].equalsIgnoreCase("-xbgr"))
pf = TJ.PF_XBGR;
- if (argv[i].equalsIgnoreCase("-xrgb"))
+ else if (argv[i].equalsIgnoreCase("-xrgb"))
pf = TJ.PF_XRGB;
- if (argv[i].equalsIgnoreCase("-bottomup"))
+ else if (argv[i].equalsIgnoreCase("-bottomup"))
flags |= TJ.FLAG_BOTTOMUP;
- if (argv[i].equalsIgnoreCase("-quiet"))
+ else if (argv[i].equalsIgnoreCase("-quiet"))
quiet = 1;
- if (argv[i].equalsIgnoreCase("-qq"))
+ else if (argv[i].equalsIgnoreCase("-qq"))
quiet = 2;
- if (argv[i].equalsIgnoreCase("-scale") && i < argv.length - 1) {
+ else if (argv[i].equalsIgnoreCase("-scale") && i < argv.length - 1) {
int temp1 = 0, temp2 = 0;
boolean match = false, scanned = true;
Scanner scanner = new Scanner(argv[++i]).useDelimiter("/");
@@ -764,25 +774,25 @@
} else
usage();
}
- if (argv[i].equalsIgnoreCase("-hflip"))
+ else if (argv[i].equalsIgnoreCase("-hflip"))
xformOp = TJTransform.OP_HFLIP;
- if (argv[i].equalsIgnoreCase("-vflip"))
+ else if (argv[i].equalsIgnoreCase("-vflip"))
xformOp = TJTransform.OP_VFLIP;
- if (argv[i].equalsIgnoreCase("-transpose"))
+ else if (argv[i].equalsIgnoreCase("-transpose"))
xformOp = TJTransform.OP_TRANSPOSE;
- if (argv[i].equalsIgnoreCase("-transverse"))
+ else if (argv[i].equalsIgnoreCase("-transverse"))
xformOp = TJTransform.OP_TRANSVERSE;
- if (argv[i].equalsIgnoreCase("-rot90"))
+ else if (argv[i].equalsIgnoreCase("-rot90"))
xformOp = TJTransform.OP_ROT90;
- if (argv[i].equalsIgnoreCase("-rot180"))
+ else if (argv[i].equalsIgnoreCase("-rot180"))
xformOp = TJTransform.OP_ROT180;
- if (argv[i].equalsIgnoreCase("-rot270"))
+ else if (argv[i].equalsIgnoreCase("-rot270"))
xformOp = TJTransform.OP_ROT270;
- if (argv[i].equalsIgnoreCase("-grayscale"))
+ else if (argv[i].equalsIgnoreCase("-grayscale"))
xformOpt |= TJTransform.OPT_GRAY;
- if (argv[i].equalsIgnoreCase("-nooutput"))
+ else if (argv[i].equalsIgnoreCase("-nooutput"))
xformOpt |= TJTransform.OPT_NOOUTPUT;
- if (argv[i].equalsIgnoreCase("-benchtime") && i < argv.length - 1) {
+ else if (argv[i].equalsIgnoreCase("-benchtime") && i < argv.length - 1) {
double temp = -1;
try {
temp = Double.parseDouble(argv[++i]);
@@ -792,11 +802,11 @@
else
usage();
}
- if (argv[i].equalsIgnoreCase("-yuv")) {
+ else if (argv[i].equalsIgnoreCase("-yuv")) {
System.out.println("Testing YUV planar encoding/decoding\n");
doYUV = true;
}
- if (argv[i].equalsIgnoreCase("-yuvpad") && i < argv.length - 1) {
+ else if (argv[i].equalsIgnoreCase("-yuvpad") && i < argv.length - 1) {
int temp = 0;
try {
temp = Integer.parseInt(argv[++i]);
@@ -804,7 +814,7 @@
if (temp >= 1)
yuvpad = temp;
}
- if (argv[i].equalsIgnoreCase("-subsamp") && i < argv.length - 1) {
+ else if (argv[i].equalsIgnoreCase("-subsamp") && i < argv.length - 1) {
i++;
if (argv[i].toUpperCase().startsWith("G"))
subsamp = TJ.SAMP_GRAY;
@@ -819,22 +829,22 @@
else if (argv[i].equals("411"))
subsamp = TJ.SAMP_411;
}
- if (argv[i].equalsIgnoreCase("-componly"))
+ else if (argv[i].equalsIgnoreCase("-componly"))
compOnly = true;
- if (argv[i].equalsIgnoreCase("-nowrite"))
+ else if (argv[i].equalsIgnoreCase("-nowrite"))
write = false;
- if (argv[i].equalsIgnoreCase("-warmup") && i < argv.length - 1) {
- int temp = -1;
+ else if (argv[i].equalsIgnoreCase("-warmup") && i < argv.length - 1) {
+ double temp = -1;
try {
- temp = Integer.parseInt(argv[++i]);
+ temp = Double.parseDouble(argv[++i]);
} catch (NumberFormatException e) {}
- if (temp >= 0) {
+ if (temp >= 0.0) {
warmup = temp;
- System.out.format("Warmup runs = %d\n\n", warmup);
- }
+ System.out.format("Warmup time = %.1f seconds\n\n", warmup);
+ } else
+ usage();
}
- if (argv[i].equalsIgnoreCase("-?"))
- usage();
+ else usage();
}
}
diff --git a/java/TJExample.java b/java/TJExample.java
index da09807..835a5b9 100644
--- a/java/TJExample.java
+++ b/java/TJExample.java
@@ -1,5 +1,6 @@
/*
- * Copyright (C)2011-2012, 2014-2015 D. R. Commander. All Rights Reserved.
+ * Copyright (C)2011-2012, 2014-2015, 2017 D. R. Commander.
+ * All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -94,7 +95,7 @@
}
private static final String[] sampName = {
- "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0"
+ "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1"
};
public static void main(String[] argv) {
@@ -117,114 +118,114 @@
int outSubsamp = -1, outQual = 95;
boolean display = false;
- if (argv.length > 1) {
- for (int i = 1; i < argv.length; i++) {
- if (argv[i].length() < 2)
- continue;
- if (argv[i].length() > 2 &&
- argv[i].substring(0, 3).equalsIgnoreCase("-sc")) {
- int match = 0;
- if (i < argv.length - 1) {
- String[] scaleArg = argv[++i].split("/");
- if (scaleArg.length == 2) {
- TJScalingFactor tempsf =
- new TJScalingFactor(Integer.parseInt(scaleArg[0]),
- Integer.parseInt(scaleArg[1]));
- for (int j = 0; j < sf.length; j++) {
- if (tempsf.equals(sf[j])) {
- scaleFactor = sf[j];
- match = 1;
- break;
- }
+ if (argv[1].substring(0, 2).equalsIgnoreCase("-d"))
+ display = true;
+
+ for (int i = 2; i < argv.length; i++) {
+ if (argv[i].length() < 2)
+ continue;
+ else if (argv[i].length() > 2 &&
+ argv[i].substring(0, 3).equalsIgnoreCase("-sc")) {
+ int match = 0;
+ if (i < argv.length - 1) {
+ String[] scaleArg = argv[++i].split("/");
+ if (scaleArg.length == 2) {
+ TJScalingFactor tempsf =
+ new TJScalingFactor(Integer.parseInt(scaleArg[0]),
+ Integer.parseInt(scaleArg[1]));
+ for (int j = 0; j < sf.length; j++) {
+ if (tempsf.equals(sf[j])) {
+ scaleFactor = sf[j];
+ match = 1;
+ break;
}
}
}
- if (match != 1) usage();
}
- if (argv[i].equalsIgnoreCase("-h") || argv[i].equalsIgnoreCase("-?"))
- usage();
- if (argv[i].length() > 2 &&
- argv[i].substring(0, 3).equalsIgnoreCase("-sa")) {
- if (i < argv.length - 1) {
- i++;
- if (argv[i].substring(0, 1).equalsIgnoreCase("g"))
- outSubsamp = TJ.SAMP_GRAY;
- else if (argv[i].equals("444"))
- outSubsamp = TJ.SAMP_444;
- else if (argv[i].equals("422"))
- outSubsamp = TJ.SAMP_422;
- else if (argv[i].equals("420"))
- outSubsamp = TJ.SAMP_420;
- else
- usage();
- } else
- usage();
- }
- if (argv[i].substring(0, 2).equalsIgnoreCase("-q")) {
- if (i < argv.length - 1) {
- int qual = Integer.parseInt(argv[++i]);
- if (qual >= 1 && qual <= 100)
- outQual = qual;
- else
- usage();
- } else
- usage();
- }
- if (argv[i].substring(0, 2).equalsIgnoreCase("-g"))
- xform.options |= TJTransform.OPT_GRAY;
- if (argv[i].equalsIgnoreCase("-hflip"))
- xform.op = TJTransform.OP_HFLIP;
- if (argv[i].equalsIgnoreCase("-vflip"))
- xform.op = TJTransform.OP_VFLIP;
- if (argv[i].equalsIgnoreCase("-transpose"))
- xform.op = TJTransform.OP_TRANSPOSE;
- if (argv[i].equalsIgnoreCase("-transverse"))
- xform.op = TJTransform.OP_TRANSVERSE;
- if (argv[i].equalsIgnoreCase("-rot90"))
- xform.op = TJTransform.OP_ROT90;
- if (argv[i].equalsIgnoreCase("-rot180"))
- xform.op = TJTransform.OP_ROT180;
- if (argv[i].equalsIgnoreCase("-rot270"))
- xform.op = TJTransform.OP_ROT270;
- if (argv[i].equalsIgnoreCase("-custom"))
- xform.cf = new TJExample();
- else if (argv[i].length() > 2 &&
- argv[i].substring(0, 2).equalsIgnoreCase("-c")) {
- if (i >= argv.length - 1)
- usage();
- String[] cropArg = argv[++i].split(",");
- if (cropArg.length != 3)
- usage();
- String[] dimArg = cropArg[2].split("[xX]");
- if (dimArg.length != 2)
- usage();
- int tempx = Integer.parseInt(cropArg[0]);
- int tempy = Integer.parseInt(cropArg[1]);
- int tempw = Integer.parseInt(dimArg[0]);
- int temph = Integer.parseInt(dimArg[1]);
- if (tempx < 0 || tempy < 0 || tempw < 0 || temph < 0)
- usage();
- xform.x = tempx;
- xform.y = tempy;
- xform.width = tempw;
- xform.height = temph;
- xform.options |= TJTransform.OPT_CROP;
- }
- if (argv[i].substring(0, 2).equalsIgnoreCase("-d"))
- display = true;
- if (argv[i].equalsIgnoreCase("-fastupsample")) {
- System.out.println("Using fast upsampling code");
- flags |= TJ.FLAG_FASTUPSAMPLE;
- }
- if (argv[i].equalsIgnoreCase("-fastdct")) {
- System.out.println("Using fastest DCT/IDCT algorithm");
- flags |= TJ.FLAG_FASTDCT;
- }
- if (argv[i].equalsIgnoreCase("-accuratedct")) {
- System.out.println("Using most accurate DCT/IDCT algorithm");
- flags |= TJ.FLAG_ACCURATEDCT;
- }
+ if (match != 1) usage();
}
+ else if (argv[i].length() > 2 &&
+ argv[i].substring(0, 3).equalsIgnoreCase("-sa")) {
+ if (i < argv.length - 1) {
+ i++;
+ if (argv[i].substring(0, 1).equalsIgnoreCase("g"))
+ outSubsamp = TJ.SAMP_GRAY;
+ else if (argv[i].equals("444"))
+ outSubsamp = TJ.SAMP_444;
+ else if (argv[i].equals("422"))
+ outSubsamp = TJ.SAMP_422;
+ else if (argv[i].equals("420"))
+ outSubsamp = TJ.SAMP_420;
+ else
+ usage();
+ } else
+ usage();
+ }
+ else if (argv[i].substring(0, 2).equalsIgnoreCase("-q")) {
+ if (i < argv.length - 1) {
+ int qual = Integer.parseInt(argv[++i]);
+ if (qual >= 1 && qual <= 100)
+ outQual = qual;
+ else
+ usage();
+ } else
+ usage();
+ }
+ else if (argv[i].substring(0, 2).equalsIgnoreCase("-g"))
+ xform.options |= TJTransform.OPT_GRAY;
+ else if (argv[i].equalsIgnoreCase("-hflip"))
+ xform.op = TJTransform.OP_HFLIP;
+ else if (argv[i].equalsIgnoreCase("-vflip"))
+ xform.op = TJTransform.OP_VFLIP;
+ else if (argv[i].equalsIgnoreCase("-transpose"))
+ xform.op = TJTransform.OP_TRANSPOSE;
+ else if (argv[i].equalsIgnoreCase("-transverse"))
+ xform.op = TJTransform.OP_TRANSVERSE;
+ else if (argv[i].equalsIgnoreCase("-rot90"))
+ xform.op = TJTransform.OP_ROT90;
+ else if (argv[i].equalsIgnoreCase("-rot180"))
+ xform.op = TJTransform.OP_ROT180;
+ else if (argv[i].equalsIgnoreCase("-rot270"))
+ xform.op = TJTransform.OP_ROT270;
+ else if (argv[i].equalsIgnoreCase("-custom"))
+ xform.cf = new TJExample();
+ else if (argv[i].length() > 2 &&
+ argv[i].substring(0, 2).equalsIgnoreCase("-c")) {
+ if (i >= argv.length - 1)
+ usage();
+ String[] cropArg = argv[++i].split(",");
+ if (cropArg.length != 3)
+ usage();
+ String[] dimArg = cropArg[2].split("[xX]");
+ if (dimArg.length != 2)
+ usage();
+ int tempx = Integer.parseInt(cropArg[0]);
+ int tempy = Integer.parseInt(cropArg[1]);
+ int tempw = Integer.parseInt(dimArg[0]);
+ int temph = Integer.parseInt(dimArg[1]);
+ if (tempx < 0 || tempy < 0 || tempw < 0 || temph < 0)
+ usage();
+ xform.x = tempx;
+ xform.y = tempy;
+ xform.width = tempw;
+ xform.height = temph;
+ xform.options |= TJTransform.OPT_CROP;
+ }
+ else if (argv[i].substring(0, 2).equalsIgnoreCase("-d"))
+ display = true;
+ else if (argv[i].equalsIgnoreCase("-fastupsample")) {
+ System.out.println("Using fast upsampling code");
+ flags |= TJ.FLAG_FASTUPSAMPLE;
+ }
+ else if (argv[i].equalsIgnoreCase("-fastdct")) {
+ System.out.println("Using fastest DCT/IDCT algorithm");
+ flags |= TJ.FLAG_FASTDCT;
+ }
+ else if (argv[i].equalsIgnoreCase("-accuratedct")) {
+ System.out.println("Using most accurate DCT/IDCT algorithm");
+ flags |= TJ.FLAG_ACCURATEDCT;
+ }
+ else usage();
}
String[] inFileTokens = argv[0].split("\\.");
if (inFileTokens.length > 1)
diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java
index 444e798..47ff7bb 100644
--- a/java/TJUnitTest.java
+++ b/java/TJUnitTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C)2011-2016 D. R. Commander. All Rights Reserved.
+ * Copyright (C)2011-2017 D. R. Commander. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -44,10 +44,10 @@
private static void usage() {
System.out.println("\nUSAGE: java " + classname + " [options]\n");
- System.out.println("Options:\n");
- System.out.println("-yuv = test YUV encoding/decoding support\n");
- System.out.println("-noyuvpad = do not pad each line of each Y, U, and V plane to the nearest\n");
- System.out.println(" 4-byte boundary\n");
+ System.out.println("Options:");
+ System.out.println("-yuv = test YUV encoding/decoding support");
+ System.out.println("-noyuvpad = do not pad each line of each Y, U, and V plane to the nearest");
+ System.out.println(" 4-byte boundary");
System.out.println("-bi = test BufferedImage support\n");
System.exit(1);
}
@@ -109,21 +109,12 @@
case BufferedImage.TYPE_BYTE_GRAY:
return TJ.PF_GRAY;
case BufferedImage.TYPE_INT_BGR:
- if (byteOrder == ByteOrder.BIG_ENDIAN)
- return TJ.PF_XBGR;
- else
- return TJ.PF_RGBX;
+ return TJ.PF_RGBX;
case BufferedImage.TYPE_INT_RGB:
- if (byteOrder == ByteOrder.BIG_ENDIAN)
- return TJ.PF_XRGB;
- else
- return TJ.PF_BGRX;
+ return TJ.PF_BGRX;
case BufferedImage.TYPE_INT_ARGB:
case BufferedImage.TYPE_INT_ARGB_PRE:
- if (byteOrder == ByteOrder.BIG_ENDIAN)
- return TJ.PF_ARGB;
- else
- return TJ.PF_BGRA;
+ return TJ.PF_BGRA;
}
return 0;
}
@@ -911,15 +902,13 @@
for (int i = 0; i < argv.length; i++) {
if (argv[i].equalsIgnoreCase("-yuv"))
doYUV = true;
- if (argv[i].equalsIgnoreCase("-noyuvpad"))
+ else if (argv[i].equalsIgnoreCase("-noyuvpad"))
pad = 1;
- if (argv[i].substring(0, 1).equalsIgnoreCase("-h") ||
- argv[i].equalsIgnoreCase("-?"))
- usage();
- if (argv[i].equalsIgnoreCase("-bi")) {
+ else if (argv[i].equalsIgnoreCase("-bi")) {
bi = true;
testName = "javabitest";
- }
+ } else
+ usage();
}
if (doYUV)
_4byteFormats[4] = -1;
diff --git a/java/org/libjpegturbo/turbojpeg/YUVImage.java b/java/org/libjpegturbo/turbojpeg/YUVImage.java
index 1a05e62..d123e37 100644
--- a/java/org/libjpegturbo/turbojpeg/YUVImage.java
+++ b/java/org/libjpegturbo/turbojpeg/YUVImage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C)2014 D. R. Commander. All Rights Reserved.
+ * Copyright (C)2014, 2017 D. R. Commander. All Rights Reserved.
* Copyright (C)2015 Viktor Szathmáry. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -220,10 +220,13 @@
throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
int nc = (subsamp == TJ.SAMP_GRAY ? 1 : 3);
- if (planes.length != nc || (offsets != null && offsets.length != nc) ||
+ if ((planes != null && planes.length != nc) ||
+ (offsets != null && offsets.length != nc) ||
(strides != null && strides.length != nc))
throw new IllegalArgumentException("YUVImage::setBuf(): planes, offsets, or strides array is the wrong size");
+ if (planes == null)
+ planes = new byte[nc][];
if (offsets == null)
offsets = new int[nc];
if (strides == null)