diff --git a/java/TJBench.java b/java/TJBench.java index f1de27a0..07338169 100644 --- a/java/TJBench.java +++ b/java/TJBench.java @@ -63,6 +63,26 @@ class TJBench { } + static String tjErrorMsg; + static int tjErrorCode = -1; + + static void handleTJException(TJException e) throws TJException { + String _tjErrorMsg = e.getMessage(); + int _tjErrorCode = e.getErrorCode(); + + if ((flags & TJ.FLAG_STOPONWARNING) == 0 && + _tjErrorCode == TJ.ERR_WARNING) { + if (tjErrorMsg == null || !tjErrorMsg.equals(_tjErrorMsg) || + tjErrorCode != _tjErrorCode) { + tjErrorMsg = _tjErrorMsg; + tjErrorCode = _tjErrorCode; + System.out.println("WARNING: " + _tjErrorMsg); + } + } else + throw e; + } + + static String formatName(int subsamp, int cs) { if (cs == TJ.CS_YCbCr) return subNameLong[subsamp]; @@ -174,14 +194,21 @@ class TJBench { tjd.setSourceImage(jpegBuf[tile], jpegSize[tile]); if (doYUV) { yuvImage.setBuf(yuvImage.getBuf(), width, yuvpad, height, subsamp); - tjd.decompressToYUV(yuvImage, flags); + try { + tjd.decompressToYUV(yuvImage, flags); + } catch (TJException e) { handleTJException(e); } double startDecode = getTime(); tjd.setSourceImage(yuvImage); - tjd.decompress(dstBuf, x, y, width, pitch, height, pf, flags); + try { + tjd.decompress(dstBuf, x, y, width, pitch, height, pf, flags); + } catch (TJException e) { handleTJException(e); } if (iter >= 0) elapsedDecode += getTime() - startDecode; - } else - tjd.decompress(dstBuf, x, y, width, pitch, height, pf, flags); + } else { + try { + tjd.decompress(dstBuf, x, y, width, pitch, height, pf, flags); + } catch (TJException e) { handleTJException(e); } + } } } elapsed += getTime() - start; diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html index a544179d..d5691268 100644 --- a/java/doc/org/libjpegturbo/turbojpeg/TJ.html +++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html @@ -995,7 +995,12 @@ public static final int FLAG_FORCESSE3
+ NOTE: due to the design of the TurboJPEG Java API, only certain methods
+ (specifically, TJDecompressor.decompress*() methods
+ with a void return type) will complete and leave the output image in a
+ fully recoverable state after a non-fatal error occurs.
public static final int ERR_WARNING
+ NOTE: due to the design of the TurboJPEG Java API, only certain methods
+ (specifically, TJDecompressor.decompress*() methods
+ with a void return type) will complete and leave the output image in a
+ fully recoverable state after a non-fatal error occurs.
+ NOTE: The output image is fully recoverable if this method throws a
+ non-fatal TJException (unless
+ TJ.FLAG_STOPONWARNING is specified.)
dstBuf - buffer that will receive the decompressed/decoded image.
If the source image is a JPEG image, then this buffer should normally be
pitch * scaledHeight bytes in size, where
@@ -895,7 +899,11 @@ public void decompress(byte[] dstBuf,
YUVImage instance. This method performs JPEG decompression
but leaves out the color conversion step, so a planar YUV image is
generated instead of an RGB or grayscale image. This method cannot be
- used to decompress JPEG source images with the CMYK or YCCK colorspace.
+ used to decompress JPEG source images with the CMYK or YCCK colorspace.
+
+ NOTE: The YUV planar output image is fully recoverable if this method
+ throws a non-fatal TJException (unless
+ TJ.FLAG_STOPONWARNING is specified.)
dstImage - YUVImage instance that will receive the YUV planar
image. The level of subsampling specified in this YUVImage
instance must match that of the JPEG image, and the width and height
@@ -1035,7 +1043,11 @@ public byte[] decompressToYUV(int flags)
throws TJException
+ NOTE: The output image is fully recoverable if this method throws a
+ non-fatal TJException (unless
+ TJ.FLAG_STOPONWARNING is specified.)
dstBuf - buffer that will receive the decompressed/decoded image.
If the source image is a JPEG image, then this buffer should normally be
stride * scaledHeight pixels in size, where
@@ -1092,7 +1104,11 @@ public byte[] decompressToYUV(int flags)
throws TJException
BufferedImage instance.BufferedImage instance.
+
+ NOTE: The output image is fully recoverable if this method throws a
+ non-fatal TJException (unless
+ TJ.FLAG_STOPONWARNING is specified.)
dstImage - a BufferedImage instance that will receive
the decompressed/decoded image. If the source image is a JPEG image, then
the width and height of the BufferedImage instance must match
diff --git a/java/org/libjpegturbo/turbojpeg/TJ.java b/java/org/libjpegturbo/turbojpeg/TJ.java
index 045e8295..ee000a90 100644
--- a/java/org/libjpegturbo/turbojpeg/TJ.java
+++ b/java/org/libjpegturbo/turbojpeg/TJ.java
@@ -391,6 +391,11 @@ public final class TJ {
* operation if the underlying codec throws a warning (non-fatal error). The
* default behavior is to allow the operation to complete unless a fatal
* error is encountered.
+ * + * NOTE: due to the design of the TurboJPEG Java API, only certain methods + * (specifically, {@link TJDecompressor TJDecompressor.decompress*()} methods + * with a void return type) will complete and leave the output image in a + * fully recoverable state after a non-fatal error occurs. */ public static final int FLAG_STOPONWARNING = 8192; /** @@ -409,6 +414,11 @@ public final class TJ { /** * The error was non-fatal and recoverable, but the image may still be * corrupt. + *
+ * NOTE: due to the design of the TurboJPEG Java API, only certain methods + * (specifically, {@link TJDecompressor TJDecompressor.decompress*()} methods + * with a void return type) will complete and leave the output image in a + * fully recoverable state after a non-fatal error occurs. */ public static final int ERR_WARNING = 0; /** diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java index bd0e6943..be71cb08 100644 --- a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java +++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java @@ -308,6 +308,10 @@ public class TJDecompressor implements Closeable { * Decompress the JPEG source image or decode the YUV source image associated * with this decompressor instance and output a grayscale, RGB, or CMYK image * to the given destination buffer. + *
+ * NOTE: The output image is fully recoverable if this method throws a + * non-fatal {@link TJException} (unless + * {@link TJ#FLAG_STOPONWARNING TJ.FLAG_STOPONWARNING} is specified.) * * @param dstBuf buffer that will receive the decompressed/decoded image. * If the source image is a JPEG image, then this buffer should normally be @@ -451,6 +455,10 @@ public class TJDecompressor implements Closeable { * but leaves out the color conversion step, so a planar YUV image is * generated instead of an RGB or grayscale image. This method cannot be * used to decompress JPEG source images with the CMYK or YCCK colorspace. + *
+ * NOTE: The YUV planar output image is fully recoverable if this method
+ * throws a non-fatal {@link TJException} (unless
+ * {@link TJ#FLAG_STOPONWARNING TJ.FLAG_STOPONWARNING} is specified.)
*
* @param dstImage {@link YUVImage} instance that will receive the YUV planar
* image. The level of subsampling specified in this YUVImage
@@ -618,6 +626,10 @@ public class TJDecompressor implements Closeable {
* Decompress the JPEG source image or decode the YUV source image associated
* with this decompressor instance and output a grayscale, RGB, or CMYK image
* to the given destination buffer.
+ *
+ * NOTE: The output image is fully recoverable if this method throws a
+ * non-fatal {@link TJException} (unless
+ * {@link TJ#FLAG_STOPONWARNING TJ.FLAG_STOPONWARNING} is specified.)
*
* @param dstBuf buffer that will receive the decompressed/decoded image.
* If the source image is a JPEG image, then this buffer should normally be
@@ -699,6 +711,10 @@ public class TJDecompressor implements Closeable {
* Decompress the JPEG source image or decode the YUV source image associated
* with this decompressor instance and output a decompressed/decoded image to
* the given BufferedImage instance.
+ *
+ * NOTE: The output image is fully recoverable if this method throws a
+ * non-fatal {@link TJException} (unless
+ * {@link TJ#FLAG_STOPONWARNING TJ.FLAG_STOPONWARNING} is specified.)
*
* @param dstImage a BufferedImage instance that will receive
* the decompressed/decoded image. If the source image is a JPEG image, then
diff --git a/tjbench.c b/tjbench.c
index 450e1280..a6275101 100644
--- a/tjbench.c
+++ b/tjbench.c
@@ -38,15 +38,44 @@
#include "./turbojpeg.h"
-#define _throw(op, err) { \
+#define _throw(op, err) \
+{ \
printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err); \
- retval=-1; goto bailout;}
+ retval=-1; goto bailout; \
+}
#define _throwunix(m) _throw(m, strerror(errno))
-#define _throwtj(m) { \
- printf("%s in line %d while %s:\n%s\n", \
- tjGetErrorCode(handle)==TJERR_WARNING ? "WARNING" : "ERROR", __LINE__, \
- m, tjGetErrorStr2(handle)); \
- retval=-1; goto bailout;}
+
+char tjErrorStr[JMSG_LENGTH_MAX]="\0", tjErrorMsg[JMSG_LENGTH_MAX]="\0";
+int tjErrorLine=-1, tjErrorCode=-1;
+
+#define _throwtj(m) \
+{ \
+ int _tjErrorCode=tjGetErrorCode(handle); \
+ char *_tjErrorStr=tjGetErrorStr2(handle); \
+ \
+ if(!(flags&TJFLAG_STOPONWARNING) && _tjErrorCode==TJERR_WARNING) \
+ { \
+ if(strncmp(tjErrorStr, _tjErrorStr, JMSG_LENGTH_MAX) || \
+ strncmp(tjErrorMsg, m, JMSG_LENGTH_MAX) || \
+ tjErrorCode!=_tjErrorCode || tjErrorLine!=__LINE__) \
+ { \
+ strncpy(tjErrorStr, _tjErrorStr, JMSG_LENGTH_MAX); \
+ strncpy(tjErrorMsg, m, JMSG_LENGTH_MAX); \
+ tjErrorCode=_tjErrorCode; \
+ tjErrorLine=__LINE__; \
+ printf("WARNING in line %d while %s:\n%s\n", __LINE__, m, \
+ _tjErrorStr); \
+ } \
+ } \
+ else \
+ { \
+ printf("%s in line %d while %s:\n%s\n", \
+ _tjErrorCode==TJERR_WARNING ? "WARNING" : "ERROR", __LINE__, m, \
+ _tjErrorStr); \
+ retval=-1; goto bailout; \
+ } \
+}
+
#define _throwbmp(m) _throw(m, bmpgeterr())
int flags=TJFLAG_NOREALLOC, componly=0, decomponly=0, doyuv=0, quiet=0,