diff --git a/ChangeLog.txt b/ChangeLog.txt index f0c804ef..e1069f5e 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -15,6 +15,10 @@ to partially decode a JPEG image. See libjpeg.txt for more details. implement the Closeable interface, so those classes can be used with a try-with-resources statement. +[4] The TurboJPEG Java classes now throw unchecked idiomatic exceptions +(IllegalArgumentException, IllegalStateException) for unrecoverable errors +caused by incorrect API usage. + 1.4.1 ===== diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html index f8342f24..3ff9b89d 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJ.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html @@ -983,16 +983,13 @@ public static final int FLAG_FORCESSE3
public static int getMCUWidth(int subsamp) - throws java.lang.Exception+
public static int getMCUWidth(int subsamp)
subsamp - the level of chrominance subsampling (one of
SAMP_*)java.lang.Exceptionpublic static int getMCUHeight(int subsamp) - throws java.lang.Exception+
public static int getMCUHeight(int subsamp)
subsamp - the level of chrominance subsampling (one of
SAMP_*)java.lang.Exceptionpublic static int getPixelSize(int pixelFormat) - throws java.lang.Exception+
public static int getPixelSize(int pixelFormat)
pixelFormat - the pixel format (one of PF_*)java.lang.Exceptionpublic static int getRedOffset(int pixelFormat) - throws java.lang.Exception+
public static int getRedOffset(int pixelFormat)
TJ.PF_BGRX is stored in char pixel[],
then the red component will be
pixel[TJ.getRedOffset(TJ.PF_BGRX)].pixelFormat - the pixel format (one of PF_*)java.lang.Exceptionpublic static int getGreenOffset(int pixelFormat) - throws java.lang.Exception+
public static int getGreenOffset(int pixelFormat)
TJ.PF_BGRX is stored in char pixel[],
then the green component will be
pixel[TJ.getGreenOffset(TJ.PF_BGRX)].pixelFormat - the pixel format (one of PF_*)java.lang.Exceptionpublic static int getBlueOffset(int pixelFormat) - throws java.lang.Exception+
public static int getBlueOffset(int pixelFormat)
TJ.PF_BGRX is stored in char pixel[],
then the blue component will be
pixel[TJ.getBlueOffset(TJ.PF_BGRX)].pixelFormat - the pixel format (one of PF_*)java.lang.Exceptionpublic void setSubsamp(int newSubsamp) - throws java.lang.Exception+
public void setSubsamp(int newSubsamp)
TJ.CS_YCbCr) or from CMYK to YCCK (see TJ.CS_YCCK) as part
@@ -582,9 +581,7 @@ public void setSourceImage(byte[] srcImage,
destination.newSubsamp - the level of chrominance subsampling to use in
subsequent compress/encode oeprations (one of
- TJ.SAMP_*)java.lang.ExceptionTJ.SAMP_*)
public void setJPEGQuality(int quality) - throws java.lang.Exception+
public void setJPEGQuality(int quality)
quality - the new JPEG image quality level (1 to 100, 1 = worst,
- 100 = best)java.lang.Exceptionpublic int getWidth() - throws java.lang.Exception+
public int getWidth()
java.lang.Exceptionpublic int getHeight() - throws java.lang.Exception+
public int getHeight()
java.lang.Exceptionpublic int getSubsamp() - throws java.lang.Exception+
public int getSubsamp()
TJ.SAMP_*.java.lang.Exceptionpublic int getColorspace() - throws java.lang.Exception+
public int getColorspace()
TJ.CS_*. If the
source image is YUV, then this always returns TJ.CS_YCbCr.java.lang.Exceptionpublic byte[] getJPEGBuf() - throws java.lang.Exception+
public byte[] getJPEGBuf()
java.lang.Exceptionpublic int getJPEGSize() - throws java.lang.Exception+
public int getJPEGSize()
java.lang.Exceptionpublic TJScalingFactor(int num, - int denom) - throws java.lang.Exception-
java.lang.Exceptionpublic int[] getTransformedSizes() - throws java.lang.Exception+
public int[] getTransformedSizes()
java.lang.Exceptionpublic int getWidth() - throws java.lang.Exception+
public int getWidth()
java.lang.Exceptionpublic int getHeight() - throws java.lang.Exception+
public int getHeight()
java.lang.Exceptionpublic int getPad() - throws java.lang.Exception+
public int getPad()
java.lang.Exceptionpublic int[] getStrides() - throws java.lang.Exception+
public int[] getStrides()
java.lang.Exceptionpublic int[] getOffsets() - throws java.lang.Exception+
public int[] getOffsets()
java.lang.Exceptionpublic int getSubsamp() - throws java.lang.Exception+
public int getSubsamp()
TJ.SAMP_*.java.lang.Exceptionpublic byte[][] getPlanes() - throws java.lang.Exception+
public byte[][] getPlanes()
java.lang.Exceptionpublic byte[] getBuf() - throws java.lang.Exception+
public byte[] getBuf()
java.lang.Exceptionother have the same numerator and denominator.
*/
public boolean equals(TJScalingFactor other) {
- return (this.num == other.num && this.denom == other.denom);
+ return this.num == other.num && this.denom == other.denom;
}
/**
@@ -88,7 +88,7 @@ public class TJScalingFactor {
* 1/1.
*/
public boolean isOne() {
- return (num == 1 && denom == 1);
+ return num == 1 && denom == 1;
}
/**
@@ -100,4 +100,4 @@ public class TJScalingFactor {
* Denominator
*/
private int denom = 1;
-};
+}
diff --git a/java/org/libjpegturbo/turbojpeg/TJTransformer.java b/java/org/libjpegturbo/turbojpeg/TJTransformer.java
index 2e173445..6d3d81d3 100644
--- a/java/org/libjpegturbo/turbojpeg/TJTransformer.java
+++ b/java/org/libjpegturbo/turbojpeg/TJTransformer.java
@@ -96,7 +96,7 @@ public class TJTransformer extends TJDecompressor {
public void transform(byte[][] dstBufs, TJTransform[] transforms,
int flags) throws Exception {
if (jpegBuf == null)
- throw new Exception("JPEG buffer not initialized");
+ throw new IllegalStateException("JPEG buffer not initialized");
transformedSizes = transform(jpegBuf, jpegBufSize, dstBufs, transforms,
flags);
}
@@ -120,7 +120,7 @@ public class TJTransformer extends TJDecompressor {
throws Exception {
byte[][] dstBufs = new byte[transforms.length][];
if (jpegWidth < 1 || jpegHeight < 1)
- throw new Exception("JPEG buffer not initialized");
+ throw new IllegalStateException("JPEG buffer not initialized");
for (int i = 0; i < transforms.length; i++) {
int w = jpegWidth, h = jpegHeight;
if ((transforms[i].options & TJTransform.OPT_CROP) != 0) {
@@ -143,9 +143,9 @@ public class TJTransformer extends TJDecompressor {
* @return an array containing the sizes of the transformed JPEG images
* generated by the most recent transform operation.
*/
- public int[] getTransformedSizes() throws Exception {
+ public int[] getTransformedSizes() {
if (transformedSizes == null)
- throw new Exception("No image has been transformed yet");
+ throw new IllegalStateException("No image has been transformed yet");
return transformedSizes;
}
@@ -159,4 +159,4 @@ public class TJTransformer extends TJDecompressor {
}
private int[] transformedSizes = null;
-};
+}
diff --git a/java/org/libjpegturbo/turbojpeg/YUVImage.java b/java/org/libjpegturbo/turbojpeg/YUVImage.java
index 2d790e93..44a81c70 100644
--- a/java/org/libjpegturbo/turbojpeg/YUVImage.java
+++ b/java/org/libjpegturbo/turbojpeg/YUVImage.java
@@ -218,12 +218,12 @@ public class YUVImage {
int height, int subsamp, boolean alloc) throws Exception {
if ((planes == null && !alloc) || width < 1 || height < 1 || subsamp < 0 ||
subsamp >= TJ.NUMSAMP)
- throw new Exception("Invalid argument in YUVImage::setBuf()");
+ 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) ||
(strides != null && strides.length != nc))
- throw new Exception("YUVImage::setBuf(): planes, offsets, or strides array is the wrong size");
+ throw new IllegalArgumentException("YUVImage::setBuf(): planes, offsets, or strides array is the wrong size");
if (offsets == null)
offsets = new int[nc];
@@ -239,15 +239,15 @@ public class YUVImage {
strides[i] = pw;
if (alloc) {
if (strides[i] < pw)
- throw new Exception("Stride must be >= plane width when allocating a new YUV image");
+ throw new IllegalArgumentException("Stride must be >= plane width when allocating a new YUV image");
planes[i] = new byte[strides[i] * ph];
}
if (planes[i] == null || offsets[i] < 0)
- throw new Exception("Invalid argument in YUVImage::setBuf()");
+ throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
if (strides[i] < 0 && offsets[i] - planeSize + pw < 0)
- throw new Exception("Stride for plane " + i + " would cause memory to be accessed below plane boundary");
+ throw new IllegalArgumentException("Stride for plane " + i + " would cause memory to be accessed below plane boundary");
if (planes[i].length < offsets[i] + planeSize)
- throw new Exception("Image plane " + i + " is not large enough");
+ throw new IllegalArgumentException("Image plane " + i + " is not large enough");
}
yuvPlanes = planes;
@@ -282,10 +282,10 @@ public class YUVImage {
int subsamp) throws Exception {
if (yuvImage == null || width < 1 || pad < 1 || ((pad & (pad - 1)) != 0) ||
height < 1 || subsamp < 0 || subsamp >= TJ.NUMSAMP)
- throw new Exception("Invalid argument in YUVImage::setBuf()");
+ throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
if (yuvImage.length < TJ.bufSizeYUV(width, pad, height, subsamp))
- throw new Exception("YUV image buffer is not large enough");
-
+ throw new IllegalArgumentException("YUV image buffer is not large enough");
+
int nc = (subsamp == TJ.SAMP_GRAY ? 1 : 3);
byte[][] planes = new byte[nc][];
int[] strides = new int[nc];
@@ -311,9 +311,9 @@ public class YUVImage {
*
* @return the width of the YUV image (or subregion)
*/
- public int getWidth() throws Exception {
+ public int getWidth() {
if (yuvWidth < 1)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
return yuvWidth;
}
@@ -322,9 +322,9 @@ public class YUVImage {
*
* @return the height of the YUV image (or subregion)
*/
- public int getHeight() throws Exception {
+ public int getHeight() {
if (yuvHeight < 1)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
return yuvHeight;
}
@@ -334,11 +334,11 @@ public class YUVImage {
*
* @return the line padding used in the YUV image buffer
*/
- public int getPad() throws Exception {
+ public int getPad() {
if (yuvPlanes == null)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
if (yuvPad < 1 || ((yuvPad & (yuvPad - 1)) != 0))
- throw new Exception("Image is not stored in a unified buffer");
+ throw new IllegalStateException("Image is not stored in a unified buffer");
return yuvPad;
}
@@ -347,9 +347,9 @@ public class YUVImage {
*
* @return the number of bytes per line of each plane in the YUV image
*/
- public int[] getStrides() throws Exception {
+ public int[] getStrides() {
if (yuvStrides == null)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
return yuvStrides;
}
@@ -360,9 +360,9 @@ public class YUVImage {
* @return the offsets (in bytes) of each plane within the planes of a larger
* YUV image
*/
- public int[] getOffsets() throws Exception {
+ public int[] getOffsets() {
if (yuvOffsets == null)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
return yuvOffsets;
}
@@ -372,9 +372,9 @@ public class YUVImage {
*
* @return the level of chrominance subsampling used in the YUV image
*/
- public int getSubsamp() throws Exception {
+ public int getSubsamp() {
if (yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
return yuvSubsamp;
}
@@ -384,9 +384,9 @@ public class YUVImage {
*
* @return the YUV image planes
*/
- public byte[][] getPlanes() throws Exception {
+ public byte[][] getPlanes() {
if (yuvPlanes == null)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
return yuvPlanes;
}
@@ -396,13 +396,13 @@ public class YUVImage {
*
* @return the YUV image buffer
*/
- public byte[] getBuf() throws Exception {
+ public byte[] getBuf() {
if (yuvPlanes == null || yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
int nc = (yuvSubsamp == TJ.SAMP_GRAY ? 1 : 3);
for (int i = 1; i < nc; i++) {
if (yuvPlanes[i] != yuvPlanes[0])
- throw new Exception("Image is not stored in a unified buffer");
+ throw new IllegalStateException("Image is not stored in a unified buffer");
}
return yuvPlanes[0];
}
@@ -415,13 +415,13 @@ public class YUVImage {
*/
public int getSize() throws Exception {
if (yuvPlanes == null || yuvSubsamp < 0 || yuvSubsamp >= TJ.NUMSAMP)
- throw new Exception(NO_ASSOC_ERROR);
+ throw new IllegalStateException(NO_ASSOC_ERROR);
int nc = (yuvSubsamp == TJ.SAMP_GRAY ? 1 : 3);
if (yuvPad < 1)
- throw new Exception("Image is not stored in a unified buffer");
+ throw new IllegalStateException("Image is not stored in a unified buffer");
for (int i = 1; i < nc; i++) {
if (yuvPlanes[i] != yuvPlanes[0])
- throw new Exception("Image is not stored in a unified buffer");
+ throw new IllegalStateException("Image is not stored in a unified buffer");
}
return TJ.bufSizeYUV(yuvWidth, yuvPad, yuvHeight, yuvSubsamp);
}
@@ -438,4 +438,4 @@ public class YUVImage {
protected int yuvWidth = 0;
protected int yuvHeight = 0;
protected int yuvSubsamp = -1;
-};
+}
diff --git a/turbojpeg-jni.c b/turbojpeg-jni.c
index 04e2dc3a..0d0b80c5 100644
--- a/turbojpeg-jni.c
+++ b/turbojpeg-jni.c
@@ -39,30 +39,29 @@
#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
-#define _throw(msg) { \
- jclass _exccls=(*env)->FindClass(env, "java/lang/Exception"); \
- if(!_exccls) goto bailout; \
+#define _throw(msg, exceptionClass) { \
+ jclass _exccls=(*env)->FindClass(env, exceptionClass); \
+ if(!_exccls || (*env)->ExceptionCheck(env)) goto bailout; \
(*env)->ThrowNew(env, _exccls, msg); \
goto bailout; \
}
-#define _throwio(msg) { \
- jclass _exccls=(*env)->FindClass(env, "java/io/IOException"); \
- if(!_exccls) goto bailout; \
- (*env)->ThrowNew(env, _exccls, msg); \
- goto bailout; \
-}
+#define _throwio(msg) _throw(msg, "java/io/IOException")
-#define bailif0(f) {if(!(f)) { \
- char temps[80]; \
- snprintf(temps, 80, "Unexpected NULL condition in line %d", __LINE__); \
- _throw(temps); \
+#define _throwtj() _throw(tjGetErrorStr(), "java/lang/Exception")
+
+#define _throwarg(msg) _throw(msg, "java/lang/IllegalArgumentException")
+
+#define _throwmem() _throw("Memory allocation failure", "java/lang/OutOfMemoryError");
+
+#define bailif0(f) {if(!(f) || (*env)->ExceptionCheck(env)) { \
+ goto bailout; \
}}
#define gethandle() \
jclass _cls=(*env)->GetObjectClass(env, obj); \
jfieldID _fid; \
- if(!_cls) goto bailout; \
+ if(!_cls || (*env)->ExceptionCheck(env)) goto bailout; \
bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J")); \
handle=(tjhandle)(size_t)(*env)->GetLongField(env, obj, _fid); \
@@ -108,7 +107,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
(JNIEnv *env, jclass cls, jint width, jint height, jint jpegSubsamp)
{
jint retval=(jint)tjBufSize(width, height, jpegSubsamp);
- if(retval==-1) _throw(tjGetErrorStr());
+ if(retval==-1) _throwtj();
bailout:
return retval;
@@ -119,7 +118,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV__IIII
(JNIEnv *env, jclass cls, jint width, jint pad, jint height, jint subsamp)
{
jint retval=(jint)tjBufSizeYUV2(width, pad, height, subsamp);
- if(retval==-1) _throw(tjGetErrorStr());
+ if(retval==-1) _throwtj();
bailout:
return retval;
@@ -140,7 +139,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeSizeYUV__IIIII
{
jint retval=(jint)tjPlaneSizeYUV(componentID, width, stride, height,
subsamp);
- if(retval==-1) _throw(tjGetErrorStr());
+ if(retval==-1) _throwtj();
bailout:
return retval;
@@ -151,7 +150,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeWidth__III
(JNIEnv *env, jclass cls, jint componentID, jint width, jint subsamp)
{
jint retval=(jint)tjPlaneWidth(componentID, width, subsamp);
- if(retval==-1) _throw(tjGetErrorStr());
+ if(retval==-1) _throwtj();
bailout:
return retval;
@@ -162,7 +161,7 @@ JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_planeHeight__III
(JNIEnv *env, jclass cls, jint componentID, jint height, jint subsamp)
{
jint retval=(jint)tjPlaneHeight(componentID, height, subsamp);
- if(retval==-1) _throw(tjGetErrorStr());
+ if(retval==-1) _throwtj();
bailout:
return retval;
@@ -177,7 +176,7 @@ JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
tjhandle handle;
if((handle=tjInitCompress())==NULL)
- _throw(tjGetErrorStr());
+ _throwtj();
bailif0(cls=(*env)->GetObjectClass(env, obj));
bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
@@ -201,17 +200,17 @@ static jint TJCompressor_compress
if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
|| pitch<0)
- _throw("Invalid argument in compress()");
+ _throwarg("Invalid argument in compress()");
if(org_libjpegturbo_turbojpeg_TJ_NUMPF!=TJ_NUMPF)
- _throw("Mismatch between Java and C API");
+ _throwarg("Mismatch between Java and C API");
actualPitch=(pitch==0)? width*tjPixelSize[pf]:pitch;
arraySize=(y+height-1)*actualPitch + (x+width)*tjPixelSize[pf];
if((*env)->GetArrayLength(env, src)*srcElementSize