Update libjpeg-turbo to 2.0.0

Bug: 78329453

Update to upstream at https://github.com/libjpeg-turbo/libjpeg-turbo/tree/2.0.0

This includes a fix for a bug that could result in an infinite loop.

ChangeLog.md contains detailed changes about the upstream library. Changes
I made are below:
- Remove files that are no longer in upstream, and include all current
  files from upstream.
- Update various references to the version.

Android.bp:
- Update to build new files/files in new locations.
- Run bpfmt

README.android:
- Remove cherry-pick references, as they are no longer needed.
- Remove modification in jsimdext.inc, which no longer appears to be
  necessary.

README.version:
- Use the github URL, as it is now the official upstream build
- Replace msarett as OWNER, as he no longer works on this project
- Update the version

Change-Id: Ie6cfee5a8f820f28656bbb305f500e75e7ce7915
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
index 0af8ae1..d51ada7 100644
--- a/java/CMakeLists.txt
+++ b/java/CMakeLists.txt
@@ -1,57 +1,78 @@
-set(JAR_FILE turbojpeg.jar)
-set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.MF)
+find_package(Java REQUIRED)
+find_package(JNI REQUIRED)
 
-set(JAVA_CLASSNAMES org/libjpegturbo/turbojpeg/TJ
-  org/libjpegturbo/turbojpeg/TJCompressor
-  org/libjpegturbo/turbojpeg/TJCustomFilter
-  org/libjpegturbo/turbojpeg/TJDecompressor
-  org/libjpegturbo/turbojpeg/TJException
-  org/libjpegturbo/turbojpeg/TJScalingFactor
-  org/libjpegturbo/turbojpeg/TJTransform
-  org/libjpegturbo/turbojpeg/TJTransformer
-  org/libjpegturbo/turbojpeg/YUVImage
-  TJUnitTest
-  TJExample
-  TJBench)
-
-if(MSVC_IDE)
-  set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}")
-else()
-  set(OBJDIR ${CMAKE_CURRENT_BINARY_DIR})
+# Allow the Java compiler flags to be set using an environment variable
+if(NOT DEFINED CMAKE_JAVA_COMPILE_FLAGS AND DEFINED ENV{JAVAFLAGS})
+  set(CMAKE_JAVA_COMPILE_FLAGS $ENV{JAVAFLAGS})
 endif()
 
+include(UseJava)
+
+set(CMAKE_JAVA_COMPILE_FLAGS "${CMAKE_JAVA_COMPILE_FLAGS} -J-Dfile.encoding=UTF8")
+message(STATUS "CMAKE_JAVA_COMPILE_FLAGS = ${CMAKE_JAVA_COMPILE_FLAGS}")
+string(REGEX REPLACE " " ";" CMAKE_JAVA_COMPILE_FLAGS "${CMAKE_JAVA_COMPILE_FLAGS}")
+
+set(JAVAARGS "" CACHE STRING "Additional arguments to pass to java when running unit tests (example: -d32)")
+message(STATUS "JAVAARGS = ${JAVAARGS}")
+
+set(JAVA_SOURCES org/libjpegturbo/turbojpeg/TJ.java
+  org/libjpegturbo/turbojpeg/TJCompressor.java
+  org/libjpegturbo/turbojpeg/TJCustomFilter.java
+  org/libjpegturbo/turbojpeg/TJDecompressor.java
+  org/libjpegturbo/turbojpeg/TJException.java
+  org/libjpegturbo/turbojpeg/TJScalingFactor.java
+  org/libjpegturbo/turbojpeg/TJTransform.java
+  org/libjpegturbo/turbojpeg/TJTransformer.java
+  org/libjpegturbo/turbojpeg/YUVImage.java
+  TJUnitTest.java
+  TJExample.java
+  TJBench.java)
+
 set(TURBOJPEG_DLL_NAME "turbojpeg")
 if(MINGW)
   set(TURBOJPEG_DLL_NAME "libturbojpeg")
 endif()
-configure_file(org/libjpegturbo/turbojpeg/TJLoader.java.in
-  ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
-
-set(JAVA_SOURCES "")
-set(JAVA_CLASSES "")
-set(JAVA_CLASSES_FULL "")
-foreach(class ${JAVA_CLASSNAMES})
-  set(JAVA_SOURCES ${JAVA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${class}.java)
-  set(JAVA_CLASSES ${JAVA_CLASSES} ${class}.class)
-  set(JAVA_CLASSES_FULL ${JAVA_CLASSES_FULL} ${OBJDIR}/${class}.class)
-endforeach()
-
+if(WIN32)
+  configure_file(org/libjpegturbo/turbojpeg/TJLoader-win.java.in
+    ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
+else()
+  configure_file(org/libjpegturbo/turbojpeg/TJLoader-unix.java.in
+    ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
+endif()
 set(JAVA_SOURCES ${JAVA_SOURCES}
   ${CMAKE_CURRENT_BINARY_DIR}/org/libjpegturbo/turbojpeg/TJLoader.java)
-set(JAVA_CLASSES ${JAVA_CLASSES}
-  org/libjpegturbo/turbojpeg/TJLoader.class)
-set(JAVA_CLASSES_FULL ${JAVA_CLASSES_FULL}
-  ${OBJDIR}/org/libjpegturbo/turbojpeg/TJLoader.class)
 
-string(REGEX REPLACE " " ";" JAVACFLAGS "${JAVACFLAGS}")
-add_custom_command(OUTPUT ${JAVA_CLASSES_FULL} DEPENDS ${JAVA_SOURCES}
-  COMMAND ${JAVA_COMPILE} ARGS ${JAVACFLAGS} -d ${OBJDIR} ${JAVA_SOURCES})
+if(MSYS)
+  # UGLY HACK ALERT: If we don't do this, then UseJava.cmake will separate
+  # class path members with a semicolon, which is interpreted as a command
+  # separator by the MSYS shell.
+  set(CMAKE_HOST_SYSTEM_NAME_BAK ${CMAKE_HOST_SYSTEM_NAME})
+  set(CMAKE_HOST_SYSTEM_NAME "MSYS")
+endif()
+add_jar(turbojpeg-java ${JAVA_SOURCES} OUTPUT_NAME turbojpeg
+  ENTRY_POINT TJExample)
+if(MSYS)
+  set(CMAKE_HOST_SYSTEM_NAME ${CMAKE_HOST_SYSTEM_NAME_BAK})
+endif()
 
-add_custom_command(OUTPUT ${JAR_FILE} DEPENDS ${JAVA_CLASSES_FULL}
-  ${MANIFEST_FILE}
-  COMMAND ${JAVA_ARCHIVE} cfm ${JAR_FILE} ${MANIFEST_FILE} ${JAVA_CLASSES}
-  WORKING_DIRECTORY ${OBJDIR})
+add_custom_target(javadoc COMMAND
+  javadoc -notimestamp -d ${CMAKE_CURRENT_SOURCE_DIR}/doc -sourcepath ${CMAKE_CURRENT_SOURCE_DIR} org.libjpegturbo.turbojpeg)
+set(JAVACLASSPATH ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/turbojpeg-java.dir)
+add_custom_target(javah
+  COMMAND javah -d ${CMAKE_CURRENT_SOURCE_DIR} -classpath ${JAVACLASSPATH} org.libjpegturbo.turbojpeg.TJ
+  COMMAND javah -d ${CMAKE_CURRENT_SOURCE_DIR} -classpath ${JAVACLASSPATH} org.libjpegturbo.turbojpeg.TJCompressor
+  COMMAND javah -d ${CMAKE_CURRENT_SOURCE_DIR} -classpath ${JAVACLASSPATH} org.libjpegturbo.turbojpeg.TJDecompressor
+  COMMAND javah -d ${CMAKE_CURRENT_SOURCE_DIR} -classpath ${JAVACLASSPATH} org.libjpegturbo.turbojpeg.TJTransformer)
 
-add_custom_target(java ALL DEPENDS ${JAR_FILE})
-
-install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${JAR_FILE} DESTINATION classes)
+if(NOT DEFINED CMAKE_INSTALL_DEFAULT_JAVADIR)
+  set(CMAKE_INSTALL_DEFAULT_JAVADIR "<CMAKE_INSTALL_DATAROOTDIR>/java")
+endif()
+GNUInstallDirs_set_install_dir(JAVADIR
+  "The directory into which Java classes should be installed")
+GNUInstallDirs_get_absolute_install_dir(CMAKE_INSTALL_FULL_JAVADIR
+  CMAKE_INSTALL_JAVADIR)
+set(CMAKE_INSTALL_JAVADIR ${CMAKE_INSTALL_JAVADIR} PARENT_SCOPE)
+set(CMAKE_INSTALL_FULL_JAVADIR ${CMAKE_INSTALL_FULL_JAVADIR} PARENT_SCOPE)
+report_directory(JAVADIR)
+install_jar(turbojpeg-java ${CMAKE_INSTALL_JAVADIR})
+mark_as_advanced(CLEAR CMAKE_INSTALL_JAVADIR)
diff --git a/java/Makefile.am b/java/Makefile.am
deleted file mode 100644
index d3fc59c..0000000
--- a/java/Makefile.am
+++ /dev/null
@@ -1,75 +0,0 @@
-JAVAROOT = .
-
-org/libjpegturbo/turbojpeg/TJLoader.java: $(srcdir)/org/libjpegturbo/turbojpeg/TJLoader.java.tmpl
-	mkdir -p org/libjpegturbo/turbojpeg; \
-	cat $(srcdir)/org/libjpegturbo/turbojpeg/TJLoader.java.tmpl | \
-		sed s@%{__libdir}@$(libdir)@g > org/libjpegturbo/turbojpeg/TJLoader.java
-
-
-JAVASOURCES = org/libjpegturbo/turbojpeg/TJ.java \
-	org/libjpegturbo/turbojpeg/TJCompressor.java \
-	org/libjpegturbo/turbojpeg/TJCustomFilter.java \
-	org/libjpegturbo/turbojpeg/TJDecompressor.java \
-	org/libjpegturbo/turbojpeg/TJException.java \
-	org/libjpegturbo/turbojpeg/TJScalingFactor.java \
-	org/libjpegturbo/turbojpeg/TJTransform.java \
-	org/libjpegturbo/turbojpeg/TJTransformer.java \
-	org/libjpegturbo/turbojpeg/YUVImage.java \
-	TJExample.java \
-	TJUnitTest.java \
-	TJBench.java
-
-JNIHEADERS = org_libjpegturbo_turbojpeg_TJ.h \
-	org_libjpegturbo_turbojpeg_TJCompressor.h \
-	org_libjpegturbo_turbojpeg_TJDecompressor.h \
-	org_libjpegturbo_turbojpeg_TJTransformer.h
-
-if WITH_JAVA
-
-nodist_noinst_JAVA = ${JAVASOURCES} org/libjpegturbo/turbojpeg/TJLoader.java
-
-JAVA_CLASSES = org/libjpegturbo/turbojpeg/TJ.class \
-	org/libjpegturbo/turbojpeg/TJCompressor.class \
-	org/libjpegturbo/turbojpeg/TJCustomFilter.class \
-	org/libjpegturbo/turbojpeg/TJDecompressor.class \
-	org/libjpegturbo/turbojpeg/TJException.class \
-	org/libjpegturbo/turbojpeg/TJLoader.class \
-	org/libjpegturbo/turbojpeg/TJScalingFactor.class \
-	org/libjpegturbo/turbojpeg/TJTransform.class \
-	org/libjpegturbo/turbojpeg/TJTransformer.class \
-	org/libjpegturbo/turbojpeg/YUVImage.class \
-	TJExample.class \
-	TJUnitTest.class \
-	TJBench.class
-
-all: all-am turbojpeg.jar
-
-turbojpeg.jar: classnoinst.stamp ${srcdir}/MANIFEST.MF
-	$(JAR) cfm turbojpeg.jar ${srcdir}/MANIFEST.MF $(JAVA_CLASSES)
-
-clean-local:
-	rm -f turbojpeg.jar
-
-install-exec-local: turbojpeg.jar
-	mkdir -p $(DESTDIR)/$(datadir)/classes
-	$(INSTALL) -m 644 turbojpeg.jar $(DESTDIR)/$(datadir)/classes/
-
-uninstall-local:
-	rm -f $(DESTDIR)/$(datadir)/classes/turbojpeg.jar
-	if [ -d $(DESTDIR)/$(datadir)/classes ]; then rmdir $(DESTDIR)/$(datadir)/classes; fi
-
-headers: all
-	javah -d ${srcdir} org.libjpegturbo.turbojpeg.TJ; \
-	javah -d ${srcdir} org.libjpegturbo.turbojpeg.TJCompressor; \
-	javah -d ${srcdir} org.libjpegturbo.turbojpeg.TJDecompressor; \
-	javah -d ${srcdir} org.libjpegturbo.turbojpeg.TJTransformer
-
-docs: all
-	mkdir -p ${srcdir}/doc; \
-	javadoc -notimestamp -d ${srcdir}/doc -sourcepath ${srcdir} org.libjpegturbo.turbojpeg
-
-endif
-
-EXTRA_DIST = MANIFEST.MF ${JAVASOURCES} ${JNIHEADERS} doc CMakeLists.txt \
-	org/libjpegturbo/turbojpeg/TJLoader.java.tmpl \
-	org/libjpegturbo/turbojpeg/TJLoader.java.in
diff --git a/java/TJBench.java b/java/TJBench.java
index ddc414c..bd55562 100644
--- a/java/TJBench.java
+++ b/java/TJBench.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2009-2014, 2016-2017 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2009-2014, 2016-2018 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:
@@ -32,50 +32,73 @@
 import java.util.*;
 import org.libjpegturbo.turbojpeg.*;
 
-class TJBench {
+final class TJBench {
 
-  static int flags = 0, quiet = 0, pf = TJ.PF_BGR, yuvpad = 1;
-  static boolean compOnly, decompOnly, doTile, doYUV, write = true;
+  private TJBench() {}
 
-  static final String[] pixFormatStr = {
+  private static int flags = 0, quiet = 0, pf = TJ.PF_BGR, yuvPad = 1;
+  private static boolean compOnly, decompOnly, doTile, doYUV, write = true;
+
+  static final String[] PIXFORMATSTR = {
     "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "GRAY"
   };
 
-  static final String[] subNameLong = {
+  static final String[] SUBNAME_LONG = {
     "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1"
   };
 
-  static final String[] subName = {
+  static final String[] SUBNAME = {
     "444", "422", "420", "GRAY", "440", "411"
   };
 
-  static final String[] csName = {
+  static final String[] CSNAME = {
     "RGB", "YCbCr", "GRAY", "CMYK", "YCCK"
   };
 
-  static TJScalingFactor sf;
-  static int xformOp = TJTransform.OP_NONE, xformOpt = 0;
-  static double benchTime = 5.0, warmup = 1.0;
+  private static TJScalingFactor sf;
+  private static int xformOp = TJTransform.OP_NONE, xformOpt = 0;
+  private static double benchTime = 5.0, warmup = 1.0;
 
 
-  static final double getTime() {
+  static double getTime() {
     return (double)System.nanoTime() / 1.0e9;
   }
 
 
+  private static String tjErrorMsg;
+  private static int tjErrorCode = -1;
+
+  static void handleTJException(TJException e) throws TJException {
+    String errorMsg = e.getMessage();
+    int errorCode = e.getErrorCode();
+
+    if ((flags & TJ.FLAG_STOPONWARNING) == 0 &&
+        errorCode == TJ.ERR_WARNING) {
+      if (tjErrorMsg == null || !tjErrorMsg.equals(errorMsg) ||
+          tjErrorCode != errorCode) {
+        tjErrorMsg = errorMsg;
+        tjErrorCode = errorCode;
+        System.out.println("WARNING: " + errorMsg);
+      }
+    } else
+      throw e;
+  }
+
+
   static String formatName(int subsamp, int cs) {
     if (cs == TJ.CS_YCbCr)
-      return subNameLong[subsamp];
+      return SUBNAME_LONG[subsamp];
     else if (cs == TJ.CS_YCCK)
-      return csName[cs] + " " + subNameLong[subsamp];
+      return CSNAME[cs] + " " + SUBNAME_LONG[subsamp];
     else
-      return csName[cs];
+      return CSNAME[cs];
   }
 
 
   static String sigFig(double val, int figs) {
     String format;
     int digitsAfterDecimal = figs - (int)Math.ceil(Math.log10(Math.abs(val)));
+
     if (digitsAfterDecimal < 1)
       format = new String("%.0f");
     else
@@ -87,10 +110,12 @@
   static byte[] loadImage(String fileName, int[] w, int[] h, int pixelFormat)
                           throws Exception {
     BufferedImage img = ImageIO.read(new File(fileName));
+
     if (img == null)
       throw new Exception("Could not read " + fileName);
     w[0] = img.getWidth();
     h[0] = img.getHeight();
+
     int[] rgb = img.getRGB(0, 0, w[0], h[0], null, 0, w[0]);
     int ps = TJ.getPixelSize(pixelFormat);
     int rindex = TJ.getRedOffset(pixelFormat);
@@ -98,6 +123,7 @@
     int bindex = TJ.getBlueOffset(pixelFormat);
     byte[] dstBuf = new byte[w[0] * h[0] * ps];
     int pixels = w[0] * h[0], dstPtr = 0, rgbPtr = 0;
+
     while (pixels-- > 0) {
       dstBuf[dstPtr + rindex] = (byte)((rgb[rgbPtr] >> 16) & 0xff);
       dstBuf[dstPtr + gindex] = (byte)((rgb[rgbPtr] >> 8) & 0xff);
@@ -117,11 +143,13 @@
     int rindex = TJ.getRedOffset(pixelFormat);
     int gindex = TJ.getGreenOffset(pixelFormat);
     int bindex = TJ.getBlueOffset(pixelFormat);
+
     for (int y = 0; y < h; y++) {
       for (int x = 0; x < w; x++, srcPtr += ps) {
         int pixel = (srcBuf[srcPtr + rindex] & 0xff) << 16 |
                     (srcBuf[srcPtr + gindex] & 0xff) << 8 |
                     (srcBuf[srcPtr + bindex] & 0xff);
+
         img.setRGB(x, y, pixel);
       }
     }
@@ -157,7 +185,8 @@
     if (doYUV) {
       int width = doTile ? tilew : scaledw;
       int height = doTile ? tileh : scaledh;
-      yuvImage = new YUVImage(width, yuvpad, height, subsamp);
+
+      yuvImage = new YUVImage(width, yuvPad, height, subsamp);
       Arrays.fill(yuvImage.getBuf(), (byte)127);
     }
 
@@ -167,21 +196,30 @@
     while (true) {
       int tile = 0;
       double start = getTime();
+
       for (int y = 0; y < h; y += tileh) {
         for (int x = 0; x < w; x += tilew, tile++) {
           int width = doTile ? Math.min(tilew, w - x) : scaledw;
           int height = doTile ? Math.min(tileh, h - y) : scaledh;
+
           tjd.setSourceImage(jpegBuf[tile], jpegSize[tile]);
           if (doYUV) {
-            yuvImage.setBuf(yuvImage.getBuf(), width, yuvpad, height, subsamp);
-            tjd.decompressToYUV(yuvImage, flags);
+            yuvImage.setBuf(yuvImage.getBuf(), width, yuvPad, height, subsamp);
+            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;
@@ -194,7 +232,7 @@
         elapsed = elapsedDecode = 0.0;
       }
     }
-    if(doYUV)
+    if (doYUV)
       elapsed -= elapsedDecode;
 
     tjd = null;
@@ -205,16 +243,18 @@
 
     if (quiet != 0) {
       System.out.format("%-6s%s",
-        sigFig((double)(w * h) / 1000000. * (double)iter / elapsed, 4),
-        quiet == 2 ? "\n" : "  ");
+                        sigFig((double)(w * h) / 1000000. *
+                               (double)iter / elapsed, 4),
+                        quiet == 2 ? "\n" : "  ");
       if (doYUV)
         System.out.format("%s\n",
-          sigFig((double)(w * h) / 1000000. * (double)iter / elapsedDecode, 4));
+                          sigFig((double)(w * h) / 1000000. *
+                                 (double)iter / elapsedDecode, 4));
       else if (quiet != 2)
         System.out.print("\n");
     } else {
       System.out.format("%s --> Frame rate:         %f fps\n",
-                        (doYUV ? "Decomp to YUV":"Decompress   "),
+                        (doYUV ? "Decomp to YUV" : "Decompress   "),
                         (double)iter / elapsed);
       System.out.format("                  Throughput:         %f Megapixels/sec\n",
                         (double)(w * h) / 1000000. * (double)iter / elapsed);
@@ -222,7 +262,8 @@
         System.out.format("YUV Decode    --> Frame rate:         %f fps\n",
                           (double)iter / elapsedDecode);
         System.out.format("                  Throughput:         %f Megapixels/sec\n",
-                          (double)(w * h) / 1000000. * (double)iter / elapsedDecode);
+                          (double)(w * h) / 1000000. *
+                          (double)iter / elapsedDecode);
       }
     }
 
@@ -237,7 +278,7 @@
     if (decompOnly)
       tempStr = new String(fileName + "_" + sizeStr + ".bmp");
     else
-      tempStr = new String(fileName + "_" + subName[subsamp] + qualStr +
+      tempStr = new String(fileName + "_" + SUBNAME[subsamp] + qualStr +
                            "_" + sizeStr + ".bmp");
 
     saveImage(tempStr, dstBuf, scaledw, scaledh, pf);
@@ -255,6 +296,7 @@
             int lum = (int)((double)(srcBuf[rindex] & 0xff) * 0.299 +
                             (double)(srcBuf[gindex] & 0xff) * 0.587 +
                             (double)(srcBuf[bindex] & 0xff) * 0.114 + 0.5);
+
             if (lum > 255) lum = 255;
             if (lum < 0) lum = 0;
             dstBuf[rindex] = (byte)Math.abs((dstBuf[rindex] & 0xff) - lum);
@@ -284,15 +326,16 @@
     int totalJpegSize = 0, tilew, tileh, i, iter;
     int ps = TJ.getPixelSize(pf);
     int ntilesw = 1, ntilesh = 1, pitch = w * ps;
-    String pfStr = pixFormatStr[pf];
+    String pfStr = PIXFORMATSTR[pf];
     YUVImage yuvImage = null;
 
     tmpBuf = new byte[pitch * h];
 
     if (quiet == 0)
       System.out.format(">>>>>  %s (%s) <--> JPEG %s Q%d  <<<<<\n", pfStr,
-        (flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down",
-        subNameLong[subsamp], jpegQual);
+                        (flags & TJ.FLAG_BOTTOMUP) != 0 ?
+                        "Bottom-up" : "Top-down",
+                        SUBNAME_LONG[subsamp], jpegQual);
 
     tjc = new TJCompressor();
 
@@ -312,14 +355,14 @@
       if (quiet == 1)
         System.out.format("%-4s (%s)  %-5s    %-3d   ", pfStr,
                           (flags & TJ.FLAG_BOTTOMUP) != 0 ? "BU" : "TD",
-                          subNameLong[subsamp], jpegQual);
+                          SUBNAME_LONG[subsamp], jpegQual);
       for (i = 0; i < h; i++)
         System.arraycopy(srcBuf, w * ps * i, tmpBuf, pitch * i, w * ps);
       tjc.setJPEGQuality(jpegQual);
       tjc.setSubsamp(subsamp);
 
       if (doYUV) {
-        yuvImage = new YUVImage(tilew, yuvpad, tileh, subsamp);
+        yuvImage = new YUVImage(tilew, yuvPad, tileh, subsamp);
         Arrays.fill(yuvImage.getBuf(), (byte)127);
       }
 
@@ -328,16 +371,19 @@
       elapsed = elapsedEncode = 0.0;
       while (true) {
         int tile = 0;
+
         totalJpegSize = 0;
         start = getTime();
         for (int y = 0; y < h; y += tileh) {
           for (int x = 0; x < w; x += tilew, tile++) {
             int width = Math.min(tilew, w - x);
             int height = Math.min(tileh, h - y);
+
             tjc.setSourceImage(srcBuf, x, y, width, pitch, height, pf);
             if (doYUV) {
               double startEncode = getTime();
-              yuvImage.setBuf(yuvImage.getBuf(), width, yuvpad, height,
+
+              yuvImage.setBuf(yuvImage.getBuf(), width, yuvPad, height,
                               subsamp);
               tjc.encodeYUV(yuvImage, flags);
               if (iter >= 0)
@@ -367,14 +413,17 @@
       if (quiet != 0) {
         if (doYUV)
           System.out.format("%-6s%s",
-            sigFig((double)(w * h) / 1000000. * (double)iter / elapsedEncode, 4),
-            quiet == 2 ? "\n" : "  ");
+                            sigFig((double)(w * h) / 1000000. *
+                                   (double)iter / elapsedEncode, 4),
+                            quiet == 2 ? "\n" : "  ");
         System.out.format("%-6s%s",
-          sigFig((double)(w * h) / 1000000. * (double)iter / elapsed, 4),
-          quiet == 2 ? "\n" : "  ");
+                          sigFig((double)(w * h) / 1000000. *
+                                 (double)iter / elapsed, 4),
+                          quiet == 2 ? "\n" : "  ");
         System.out.format("%-6s%s",
-          sigFig((double)(w * h * ps) / (double)totalJpegSize, 4),
-          quiet == 2 ? "\n" : "  ");
+                          sigFig((double)(w * h * ps) / (double)totalJpegSize,
+                                 4),
+                          quiet == 2 ? "\n" : "  ");
       } else {
         System.out.format("\n%s size: %d x %d\n", doTile ? "Tile" : "Image",
                           tilew, tileh);
@@ -386,9 +435,11 @@
           System.out.format("                  Compression ratio:  %f:1\n",
                             (double)(w * h * ps) / (double)yuvImage.getSize());
           System.out.format("                  Throughput:         %f Megapixels/sec\n",
-                            (double)(w * h) / 1000000. * (double)iter / elapsedEncode);
+                            (double)(w * h) / 1000000. *
+                            (double)iter / elapsedEncode);
           System.out.format("                  Output bit stream:  %f Megabits/sec\n",
-            (double)yuvImage.getSize() * 8. / 1000000. * (double)iter / elapsedEncode);
+                            (double)yuvImage.getSize() * 8. / 1000000. *
+                            (double)iter / elapsedEncode);
         }
         System.out.format("%s --> Frame rate:         %f fps\n",
                           doYUV ? "Comp from YUV" : "Compress     ",
@@ -400,12 +451,14 @@
         System.out.format("                  Throughput:         %f Megapixels/sec\n",
                           (double)(w * h) / 1000000. * (double)iter / elapsed);
         System.out.format("                  Output bit stream:  %f Megabits/sec\n",
-          (double)totalJpegSize * 8. / 1000000. * (double)iter / elapsed);
+                          (double)totalJpegSize * 8. / 1000000. *
+                          (double)iter / elapsed);
       }
       if (tilew == w && tileh == h && write) {
-        String tempStr = fileName + "_" + subName[subsamp] + "_" + "Q" +
+        String tempStr = fileName + "_" + SUBNAME[subsamp] + "_" + "Q" +
                          jpegQual + ".jpg";
         FileOutputStream fos = new FileOutputStream(tempStr);
+
         fos.write(jpegBuf[0], 0, jpegSize[0]);
         fos.close();
         if (quiet == 0)
@@ -428,11 +481,12 @@
     byte[] srcBuf;
     int[] jpegSize = null;
     int totalJpegSize;
-    int w = 0, h = 0, subsamp = -1, cs = -1, _w, _h, _tilew, _tileh,
-      _ntilesw, _ntilesh, _subsamp, x, y, iter;
-    int ntilesw = 1, ntilesh = 1;
     double start, elapsed;
-    int ps = TJ.getPixelSize(pf), tile;
+    int ps = TJ.getPixelSize(pf), tile, x, y, iter;
+    // Original image
+    int w = 0, h = 0, ntilesw = 1, ntilesh = 1, subsamp = -1, cs = -1;
+    // Transformed image
+    int tw, th, ttilew, ttileh, tntilesw, tntilesh, tsubsamp;
 
     FileInputStream fis = new FileInputStream(fileName);
     int srcSize = (int)fis.getChannel().size();
@@ -466,8 +520,9 @@
       System.out.println("\n");
     } else if (quiet == 0)
       System.out.format(">>>>>  JPEG %s --> %s (%s)  <<<<<\n",
-        formatName(subsamp, cs), pixFormatStr[pf],
-        (flags & TJ.FLAG_BOTTOMUP) != 0 ? "Bottom-up" : "Top-down");
+                        formatName(subsamp, cs), PIXFORMATSTR[pf],
+                        (flags & TJ.FLAG_BOTTOMUP) != 0 ?
+                        "Bottom-up" : "Top-down");
 
     for (int tilew = doTile ? 16 : w, tileh = doTile ? 16 : h; ;
          tilew *= 2, tileh *= 2) {
@@ -478,65 +533,66 @@
       ntilesw = (w + tilew - 1) / tilew;
       ntilesh = (h + tileh - 1) / tileh;
 
-      _w = w;  _h = h;  _tilew = tilew;  _tileh = tileh;
+      tw = w;  th = h;  ttilew = tilew;  ttileh = tileh;
       if (quiet == 0) {
         System.out.format("\n%s size: %d x %d", (doTile ? "Tile" : "Image"),
-                          _tilew, _tileh);
+                          ttilew, ttileh);
         if (sf.getNum() != 1 || sf.getDenom() != 1)
-          System.out.format(" --> %d x %d", sf.getScaled(_w),
-                            sf.getScaled(_h));
+          System.out.format(" --> %d x %d", sf.getScaled(tw),
+                            sf.getScaled(th));
         System.out.println("");
       } else if (quiet == 1) {
-        System.out.format("%-4s (%s)  %-5s  %-5s    ", pixFormatStr[pf],
+        System.out.format("%-4s (%s)  %-5s  %-5s    ", PIXFORMATSTR[pf],
                           (flags & TJ.FLAG_BOTTOMUP) != 0 ? "BU" : "TD",
-                          csName[cs], subNameLong[subsamp]);
+                          CSNAME[cs], SUBNAME_LONG[subsamp]);
         System.out.format("%-5d  %-5d   ", tilew, tileh);
       }
 
-      _subsamp = subsamp;
+      tsubsamp = subsamp;
       if (doTile || xformOp != TJTransform.OP_NONE || xformOpt != 0) {
         if (xformOp == TJTransform.OP_TRANSPOSE ||
             xformOp == TJTransform.OP_TRANSVERSE ||
             xformOp == TJTransform.OP_ROT90 ||
             xformOp == TJTransform.OP_ROT270) {
-          _w = h;  _h = w;  _tilew = tileh;  _tileh = tilew;
+          tw = h;  th = w;  ttilew = tileh;  ttileh = tilew;
         }
 
         if ((xformOpt & TJTransform.OPT_GRAY) != 0)
-          _subsamp = TJ.SAMP_GRAY;
+          tsubsamp = TJ.SAMP_GRAY;
         if (xformOp == TJTransform.OP_HFLIP ||
             xformOp == TJTransform.OP_ROT180)
-          _w = _w - (_w % TJ.getMCUWidth(_subsamp));
+          tw = tw - (tw % TJ.getMCUWidth(tsubsamp));
         if (xformOp == TJTransform.OP_VFLIP ||
             xformOp == TJTransform.OP_ROT180)
-          _h = _h - (_h % TJ.getMCUHeight(_subsamp));
+          th = th - (th % TJ.getMCUHeight(tsubsamp));
         if (xformOp == TJTransform.OP_TRANSVERSE ||
             xformOp == TJTransform.OP_ROT90)
-          _w = _w - (_w % TJ.getMCUHeight(_subsamp));
+          tw = tw - (tw % TJ.getMCUHeight(tsubsamp));
         if (xformOp == TJTransform.OP_TRANSVERSE ||
             xformOp == TJTransform.OP_ROT270)
-          _h = _h - (_h % TJ.getMCUWidth(_subsamp));
-        _ntilesw = (_w + _tilew - 1) / _tilew;
-        _ntilesh = (_h + _tileh - 1) / _tileh;
+          th = th - (th % TJ.getMCUWidth(tsubsamp));
+        tntilesw = (tw + ttilew - 1) / ttilew;
+        tntilesh = (th + ttileh - 1) / ttileh;
 
         if (xformOp == TJTransform.OP_TRANSPOSE ||
             xformOp == TJTransform.OP_TRANSVERSE ||
             xformOp == TJTransform.OP_ROT90 ||
             xformOp == TJTransform.OP_ROT270) {
-            if (_subsamp == TJ.SAMP_422)
-              _subsamp = TJ.SAMP_440;
-            else if (_subsamp == TJ.SAMP_440)
-              _subsamp = TJ.SAMP_422;
+          if (tsubsamp == TJ.SAMP_422)
+            tsubsamp = TJ.SAMP_440;
+          else if (tsubsamp == TJ.SAMP_440)
+            tsubsamp = TJ.SAMP_422;
         }
 
-        TJTransform[] t = new TJTransform[_ntilesw * _ntilesh];
-        jpegBuf = new byte[_ntilesw * _ntilesh][TJ.bufSize(_tilew, _tileh, subsamp)];
+        TJTransform[] t = new TJTransform[tntilesw * tntilesh];
+        jpegBuf =
+          new byte[tntilesw * tntilesh][TJ.bufSize(ttilew, ttileh, subsamp)];
 
-        for (y = 0, tile = 0; y < _h; y += _tileh) {
-          for (x = 0; x < _w; x += _tilew, tile++) {
+        for (y = 0, tile = 0; y < th; y += ttileh) {
+          for (x = 0; x < tw; x += ttilew, tile++) {
             t[tile] = new TJTransform();
-            t[tile].width = Math.min(_tilew, _w - x);
-            t[tile].height = Math.min(_tileh, _h - y);
+            t[tile].width = Math.min(ttilew, tw - x);
+            t[tile].height = Math.min(ttileh, th - y);
             t[tile].x = x;
             t[tile].y = y;
             t[tile].op = xformOp;
@@ -565,15 +621,16 @@
         }
         t = null;
 
-        for (tile = 0, totalJpegSize = 0; tile < _ntilesw * _ntilesh; tile++)
+        for (tile = 0, totalJpegSize = 0; tile < tntilesw * tntilesh; tile++)
           totalJpegSize += jpegSize[tile];
 
         if (quiet != 0) {
           System.out.format("%-6s%s%-6s%s",
-            sigFig((double)(w * h) / 1000000. / elapsed, 4),
-            quiet == 2 ? "\n" : "  ",
-            sigFig((double)(w * h * ps) / (double)totalJpegSize, 4),
-            quiet == 2 ? "\n" : "  ");
+                            sigFig((double)(w * h) / 1000000. / elapsed, 4),
+                            quiet == 2 ? "\n" : "  ",
+                            sigFig((double)(w * h * ps) /
+                                   (double)totalJpegSize, 4),
+                            quiet == 2 ? "\n" : "  ");
         } else if (quiet == 0) {
           System.out.format("Transform     --> Frame rate:         %f fps\n",
                             1.0 / elapsed);
@@ -589,19 +646,19 @@
       } else {
         if (quiet == 1)
           System.out.print("N/A     N/A     ");
-        jpegBuf = new byte[1][TJ.bufSize(_tilew, _tileh, subsamp)];
+        jpegBuf = new byte[1][TJ.bufSize(ttilew, ttileh, subsamp)];
         jpegSize = new int[1];
         jpegBuf[0] = srcBuf;
         jpegSize[0] = srcSize;
       }
 
       if (w == tilew)
-        _tilew = _w;
+        ttilew = tw;
       if (h == tileh)
-        _tileh = _h;
+        ttileh = th;
       if ((xformOpt & TJTransform.OPT_NOOUTPUT) == 0)
-        decomp(null, jpegBuf, jpegSize, null, _w, _h, _subsamp, 0,
-               fileName, _tilew, _tileh);
+        decomp(null, jpegBuf, jpegSize, null, tw, th, tsubsamp, 0,
+               fileName, ttilew, ttileh);
       else if (quiet == 1)
         System.out.println("N/A");
 
@@ -636,6 +693,8 @@
     System.out.println("     codec");
     System.out.println("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the");
     System.out.println("     underlying codec");
+    System.out.println("-progressive = Use progressive entropy coding in JPEG images generated by");
+    System.out.println("     compression and transform operations.");
     System.out.println("-subsamp <s> = When testing JPEG compression, this option specifies the level");
     System.out.println("     of chrominance subsampling to use (<s> = 444, 422, 440, 420, 411, or");
     System.out.println("     GRAY).  The default is to test Grayscale, 4:2:0, 4:2:2, and 4:4:4 in");
@@ -667,13 +726,18 @@
     System.out.println("     decompression (these options are mutually exclusive)");
     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("-copynone = Do not copy any extra markers (including EXIF and ICC profile data)");
+    System.out.println("     when transforming the image.");
     System.out.println("-benchtime <t> = Run each benchmark for at least <t> seconds (default = 5.0)");
     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");
+    System.out.println("     of performance measurements.)");
+    System.out.println("-stoponwarning = Immediately discontinue the current");
+    System.out.println("     compression/decompression/transform operation if the underlying codec");
+    System.out.println("     throws a warning (non-fatal error)\n");
     System.out.println("NOTE:  If the quality is specified as a range (e.g. 90-100), a separate");
     System.out.println("test will be performed for all quality values in the range.\n");
     System.exit(1);
@@ -681,9 +745,9 @@
 
 
   public static void main(String[] argv) {
-    byte[] srcBuf = null;  int w = 0, h = 0;
-    int minQual = -1, maxQual = -1;
-    int minArg = 1;  int retval = 0;
+    byte[] srcBuf = null;
+    int w = 0, h = 0, minQual = -1, maxQual = -1;
+    int minArg = 1, retval = 0;
     int subsamp = -1;
 
     try {
@@ -720,20 +784,19 @@
         for (int i = minArg; i < argv.length; i++) {
           if (argv[i].equalsIgnoreCase("-tile")) {
             doTile = true;  xformOpt |= TJTransform.OPT_CROP;
-          }
-          else if (argv[i].equalsIgnoreCase("-fastupsample")) {
+          } else if (argv[i].equalsIgnoreCase("-fastupsample")) {
             System.out.println("Using fast upsampling code\n");
             flags |= TJ.FLAG_FASTUPSAMPLE;
-          }
-          else if (argv[i].equalsIgnoreCase("-fastdct")) {
+          } else if (argv[i].equalsIgnoreCase("-fastdct")) {
             System.out.println("Using fastest DCT/IDCT algorithm\n");
             flags |= TJ.FLAG_FASTDCT;
-          }
-          else 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;
-          }
-          else if (argv[i].equalsIgnoreCase("-rgb"))
+          } else if (argv[i].equalsIgnoreCase("-progressive")) {
+            System.out.println("Using progressive entropy coding\n");
+            flags |= TJ.FLAG_PROGRESSIVE;
+          } else if (argv[i].equalsIgnoreCase("-rgb"))
             pf = TJ.PF_RGB;
           else if (argv[i].equalsIgnoreCase("-rgbx"))
             pf = TJ.PF_RGBX;
@@ -755,26 +818,27 @@
             int temp1 = 0, temp2 = 0;
             boolean match = false, scanned = true;
             Scanner scanner = new Scanner(argv[++i]).useDelimiter("/");
+
             try {
               temp1 = scanner.nextInt();
               temp2 = scanner.nextInt();
-            } catch(Exception e) {}
+            } catch (Exception e) {}
             if (temp2 <= 0) temp2 = 1;
             if (temp1 > 0) {
               TJScalingFactor[] scalingFactors = TJ.getScalingFactors();
+
               for (int j = 0; j < scalingFactors.length; j++) {
                 if ((double)temp1 / (double)temp2 ==
                     (double)scalingFactors[j].getNum() /
                     (double)scalingFactors[j].getDenom()) {
                   sf = scalingFactors[j];
-                  match = true;   break;
+                  match = true;  break;
                 }
               }
               if (!match) usage();
             } else
               usage();
-          }
-          else if (argv[i].equalsIgnoreCase("-hflip"))
+          } else if (argv[i].equalsIgnoreCase("-hflip"))
             xformOp = TJTransform.OP_HFLIP;
           else if (argv[i].equalsIgnoreCase("-vflip"))
             xformOp = TJTransform.OP_VFLIP;
@@ -792,8 +856,12 @@
             xformOpt |= TJTransform.OPT_GRAY;
           else if (argv[i].equalsIgnoreCase("-nooutput"))
             xformOpt |= TJTransform.OPT_NOOUTPUT;
-          else if (argv[i].equalsIgnoreCase("-benchtime") && i < argv.length - 1) {
+          else if (argv[i].equalsIgnoreCase("-copynone"))
+            xformOpt |= TJTransform.OPT_COPYNONE;
+          else if (argv[i].equalsIgnoreCase("-benchtime") &&
+                   i < argv.length - 1) {
             double temp = -1;
+
             try {
               temp = Double.parseDouble(argv[++i]);
             } catch (NumberFormatException e) {}
@@ -801,20 +869,32 @@
               benchTime = temp;
             else
               usage();
-          }
-          else if (argv[i].equalsIgnoreCase("-yuv")) {
+          } else if (argv[i].equalsIgnoreCase("-warmup") &&
+                     i < argv.length - 1) {
+            double temp = -1;
+
+            try {
+              temp = Double.parseDouble(argv[++i]);
+            } catch (NumberFormatException e) {}
+            if (temp >= 0.0) {
+              warmup = temp;
+              System.out.format("Warmup time = %.1f seconds\n\n", warmup);
+            } else
+              usage();
+          } else if (argv[i].equalsIgnoreCase("-yuv")) {
             System.out.println("Testing YUV planar encoding/decoding\n");
             doYUV = true;
-          }
-          else 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]);
+              temp = Integer.parseInt(argv[++i]);
             } catch (NumberFormatException e) {}
             if (temp >= 1)
-              yuvpad = temp;
-          }
-          else if (argv[i].equalsIgnoreCase("-subsamp") && i < argv.length - 1) {
+              yuvPad = temp;
+          } else if (argv[i].equalsIgnoreCase("-subsamp") &&
+                     i < argv.length - 1) {
             i++;
             if (argv[i].toUpperCase().startsWith("G"))
               subsamp = TJ.SAMP_GRAY;
@@ -828,22 +908,12 @@
               subsamp = TJ.SAMP_420;
             else if (argv[i].equals("411"))
               subsamp = TJ.SAMP_411;
-          }
-          else if (argv[i].equalsIgnoreCase("-componly"))
+          } else if (argv[i].equalsIgnoreCase("-componly"))
             compOnly = true;
           else if (argv[i].equalsIgnoreCase("-nowrite"))
             write = false;
-          else if (argv[i].equalsIgnoreCase("-warmup") && i < argv.length - 1) {
-            double temp = -1;
-            try {
-             temp = Double.parseDouble(argv[++i]);
-            } catch (NumberFormatException e) {}
-            if (temp >= 0.0) {
-              warmup = temp;
-              System.out.format("Warmup time = %.1f seconds\n\n", warmup);
-            } else
-              usage();
-          }
+          else if (argv[i].equalsIgnoreCase("-stoponwarning"))
+            flags |= TJ.FLAG_STOPONWARNING;
           else usage();
         }
       }
@@ -859,6 +929,7 @@
 
       if (!decompOnly) {
         int[] width = new int[1], height = new int[1];
+
         srcBuf = loadImage(argv[0], width, height, pf);
         w = width[0];  h = height[0];
         int index = -1;
@@ -869,7 +940,8 @@
       if (quiet == 1 && !decompOnly) {
         System.out.println("All performance values in Mpixels/sec\n");
         System.out.format("Bitmap     JPEG     JPEG  %s  %s   ",
-          (doTile ? "Tile " : "Image"), (doTile ? "Tile " : "Image"));
+                          (doTile ? "Tile " : "Image"),
+                          (doTile ? "Tile " : "Image"));
         if (doYUV)
           System.out.print("Encode  ");
         System.out.print("Comp    Comp    Decomp  ");
@@ -915,7 +987,13 @@
       }
 
     } catch (Exception e) {
-      System.out.println("ERROR: " + e.getMessage());
+      if (e instanceof TJException) {
+        TJException tje = (TJException)e;
+
+        System.out.println((tje.getErrorCode() == TJ.ERR_WARNING ?
+                            "WARNING: " : "ERROR: ") + tje.getMessage());
+      } else
+        System.out.println("ERROR: " + e.getMessage());
       e.printStackTrace();
       retval = -1;
     }
diff --git a/java/TJExample.java b/java/TJExample.java
index 835a5b9..7859886 100644
--- a/java/TJExample.java
+++ b/java/TJExample.java
@@ -1,6 +1,6 @@
 /*
- * Copyright (C)2011-2012, 2014-2015, 2017 D. R. Commander.
- *                                         All Rights Reserved.
+ * Copyright (C)2011-2012, 2014-2015, 2017-2018 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:
@@ -28,8 +28,8 @@
  */
 
 /*
- * This program demonstrates how to compress and decompress JPEG files using
- * the TurboJPEG JNI wrapper
+ * This program demonstrates how to compress, decompress, and transform JPEG
+ * images using the TurboJPEG Java API
  */
 
 import java.io.*;
@@ -40,138 +40,178 @@
 import javax.swing.*;
 import org.libjpegturbo.turbojpeg.*;
 
-public class TJExample implements TJCustomFilter {
 
-  public static final String classname = new TJExample().getClass().getName();
+@SuppressWarnings("checkstyle:JavadocType")
+class TJExample implements TJCustomFilter {
 
-  private static void usage() throws Exception {
-    System.out.println("\nUSAGE: java " + classname + " <Input file> <Output file> [options]\n");
-    System.out.println("Input and output files can be any image format that the Java Image I/O");
+  static final String CLASS_NAME =
+    new TJExample().getClass().getName();
+
+  static final int DEFAULT_SUBSAMP = TJ.SAMP_444;
+  static final int DEFAULT_QUALITY = 95;
+
+
+  static final String[] SUBSAMP_NAME = {
+    "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1"
+  };
+
+  static final String[] COLORSPACE_NAME = {
+    "RGB", "YCbCr", "GRAY", "CMYK", "YCCK"
+  };
+
+
+  /* DCT filter example.  This produces a negative of the image. */
+
+  @SuppressWarnings("checkstyle:JavadocMethod")
+  public void customFilter(ShortBuffer coeffBuffer, Rectangle bufferRegion,
+                           Rectangle planeRegion, int componentIndex,
+                           int transformIndex, TJTransform transform)
+                           throws TJException {
+    for (int i = 0; i < bufferRegion.width * bufferRegion.height; i++) {
+      coeffBuffer.put(i, (short)(-coeffBuffer.get(i)));
+    }
+  }
+
+
+  static void usage() throws Exception {
+    System.out.println("\nUSAGE: java [Java options] " + CLASS_NAME +
+                       " <Input image> <Output image> [options]\n");
+
+    System.out.println("Input and output images can be in any image format that the Java Image I/O");
     System.out.println("extensions understand.  If either filename ends in a .jpg extension, then");
-    System.out.println("TurboJPEG will be used to compress or decompress the file.\n");
-    System.out.println("Options:\n");
-    System.out.println("-scale M/N = if the input image is a JPEG file, scale the width/height of the");
-    System.out.print("             output image by a factor of M/N (M/N = ");
-    for (int i = 0; i < sf.length; i++) {
-      System.out.print(sf[i].getNum() + "/" + sf[i].getDenom());
-      if (sf.length == 2 && i != sf.length - 1)
+    System.out.println("the TurboJPEG API will be used to compress or decompress the image.\n");
+
+    System.out.println("Compression Options (used if the output image is a JPEG image)");
+    System.out.println("--------------------------------------------------------------\n");
+
+    System.out.println("-subsamp <444|422|420|gray> = Apply this level of chrominance subsampling when");
+    System.out.println("     compressing the output image.  The default is to use the same level of");
+    System.out.println("     subsampling as in the input image, if the input image is also a JPEG");
+    System.out.println("     image, or to use grayscale if the input image is a grayscale non-JPEG");
+    System.out.println("     image, or to use " +
+                       SUBSAMP_NAME[DEFAULT_SUBSAMP] +
+                       " subsampling otherwise.\n");
+
+    System.out.println("-q <1-100> = Compress the output image with this JPEG quality level");
+    System.out.println("     (default = " + DEFAULT_QUALITY + ").\n");
+
+    System.out.println("Decompression Options (used if the input image is a JPEG image)");
+    System.out.println("---------------------------------------------------------------\n");
+
+    System.out.println("-scale M/N = Scale the input image by a factor of M/N when decompressing it.");
+    System.out.print("(M/N = ");
+    for (int i = 0; i < SCALING_FACTORS.length; i++) {
+      System.out.print(SCALING_FACTORS[i].getNum() + "/" +
+                       SCALING_FACTORS[i].getDenom());
+      if (SCALING_FACTORS.length == 2 && i != SCALING_FACTORS.length - 1)
         System.out.print(" or ");
-      else if (sf.length > 2) {
-        if (i != sf.length - 1)
+      else if (SCALING_FACTORS.length > 2) {
+        if (i != SCALING_FACTORS.length - 1)
           System.out.print(", ");
-        if (i == sf.length - 2)
+        if (i == SCALING_FACTORS.length - 2)
           System.out.print("or ");
       }
     }
     System.out.println(")\n");
-    System.out.println("-samp <444|422|420|gray> = If the output image is a JPEG file, this specifies");
-    System.out.println("                           the level of chrominance subsampling to use when");
-    System.out.println("                           recompressing it.  Default is to use the same level");
-    System.out.println("                           of subsampling as the input, if the input is a JPEG");
-    System.out.println("                           file, or 4:4:4 otherwise.\n");
-    System.out.println("-q <1-100> = If the output image is a JPEG file, this specifies the JPEG");
-    System.out.println("             quality to use when recompressing it (default = 95).\n");
+
     System.out.println("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =");
-    System.out.println("     If the input image is a JPEG file, perform the corresponding lossless");
-    System.out.println("     transform prior to decompression (these options are mutually exclusive)\n");
-    System.out.println("-grayscale = If the input image is a JPEG file, perform lossless grayscale");
-    System.out.println("     conversion prior to decompression (can be combined with the other");
-    System.out.println("     transforms above)\n");
-    System.out.println("-crop X,Y,WxH = If the input image is a JPEG file, perform lossless cropping");
-    System.out.println("     prior to decompression.  X,Y specifies the upper left corner of the");
-    System.out.println("     cropping region, and WxH specifies its width and height.  X,Y must be");
-    System.out.println("     evenly divible by the MCU block size (8x8 if the source image was");
-    System.out.println("     compressed using no subsampling or grayscale, or 16x8 for 4:2:2 or 16x16");
-    System.out.println("     for 4:2:0.)\n");
-    System.out.println("-display = Display output image (Output file need not be specified in this");
+    System.out.println("     Perform one of these lossless transform operations on the input image");
+    System.out.println("     prior to decompressing it (these options are mutually exclusive.)\n");
+
+    System.out.println("-grayscale = Perform lossless grayscale conversion on the input image prior");
+    System.out.println("     to decompressing it (can be combined with the other transform operations");
+    System.out.println("     above.)\n");
+
+    System.out.println("-crop WxH+X+Y = Perform lossless cropping on the input image prior to");
+    System.out.println("     decompressing it.  X and Y specify the upper left corner of the cropping");
+    System.out.println("     region, and W and H specify the width and height of the cropping region.");
+    System.out.println("     X and Y must be evenly divible by the MCU block size (8x8 if the input");
+    System.out.println("     image was compressed using no subsampling or grayscale, 16x8 if it was");
+    System.out.println("     compressed using 4:2:2 subsampling, or 16x16 if it was compressed using");
+    System.out.println("     4:2:0 subsampling.)\n");
+
+    System.out.println("General Options");
+    System.out.println("---------------\n");
+
+    System.out.println("-display = Display output image (Output filename need not be specified in this");
     System.out.println("     case.)\n");
+
     System.out.println("-fastupsample = Use the fastest chrominance upsampling algorithm available in");
-    System.out.println("     the underlying codec\n");
+    System.out.println("     the underlying codec.\n");
+
     System.out.println("-fastdct = Use the fastest DCT/IDCT algorithms available in the underlying");
-    System.out.println("     codec\n");
+    System.out.println("     codec.\n");
+
     System.out.println("-accuratedct = Use the most accurate DCT/IDCT algorithms available in the");
-    System.out.println("     underlying codec\n");
+    System.out.println("     underlying codec.\n");
+
     System.exit(1);
   }
 
-  private static final String[] sampName = {
-    "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0", "4:1:1"
-  };
 
   public static void main(String[] argv) {
 
-    BufferedImage img = null;
-    byte[] bmpBuf = null;
-    TJTransform xform = new TJTransform();
-    int flags = 0;
-
     try {
 
-      sf = TJ.getScalingFactors();
-
-      if (argv.length < 2) {
-        usage();
-      }
-
-      TJScalingFactor scaleFactor = new TJScalingFactor(1, 1);
-      String inFormat = "jpg", outFormat = "jpg";
-      int outSubsamp = -1, outQual = 95;
+      TJScalingFactor scalingFactor = new TJScalingFactor(1, 1);
+      int outSubsamp = -1, outQual = -1;
+      TJTransform xform = new TJTransform();
       boolean display = false;
+      int flags = 0;
+      int width, height;
+      String inFormat = "jpg", outFormat = "jpg";
+      BufferedImage img = null;
+      byte[] imgBuf = null;
+
+      if (argv.length < 2)
+        usage();
 
       if (argv[1].substring(0, 2).equalsIgnoreCase("-d"))
         display = true;
 
+      /* Parse arguments. */
       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")) {
+                 argv[i].substring(0, 3).equalsIgnoreCase("-sc") &&
+                 i < argv.length - 1) {
           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;
-                }
+          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 < SCALING_FACTORS.length; j++) {
+              if (tempsf.equals(SCALING_FACTORS[j])) {
+                scalingFactor = SCALING_FACTORS[j];
+                match = 1;
+                break;
               }
             }
           }
-          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
+          if (match != 1)
             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
+        } else if (argv[i].length() > 2 &&
+                   argv[i].substring(0, 3).equalsIgnoreCase("-su") &&
+                   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 if (argv[i].substring(0, 2).equalsIgnoreCase("-g"))
+        } else if (argv[i].substring(0, 2).equalsIgnoreCase("-q") &&
+                   i < argv.length - 1) {
+          outQual = Integer.parseInt(argv[++i]);
+          if (outQual < 1 || outQual > 100)
+            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;
@@ -190,43 +230,34 @@
         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)
+                 argv[i].substring(0, 2).equalsIgnoreCase("-c") &&
+                 i < argv.length - 1) {
+          String[] cropArg = argv[++i].split("[x\\+]");
+          if (cropArg.length != 4)
             usage();
-          String[] cropArg = argv[++i].split(",");
-          if (cropArg.length != 3)
+          xform.width = Integer.parseInt(cropArg[0]);
+          xform.height = Integer.parseInt(cropArg[1]);
+          xform.x = Integer.parseInt(cropArg[2]);
+          xform.y = Integer.parseInt(cropArg[3]);
+          if (xform.x < 0 || xform.y < 0 || xform.width < 1 ||
+              xform.height < 1)
             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"))
+        } 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")) {
+        } else if (argv[i].equalsIgnoreCase("-fastdct")) {
           System.out.println("Using fastest DCT/IDCT algorithm");
           flags |= TJ.FLAG_FASTDCT;
-        }
-        else if (argv[i].equalsIgnoreCase("-accuratedct")) {
+        } else if (argv[i].equalsIgnoreCase("-accuratedct")) {
           System.out.println("Using most accurate DCT/IDCT algorithm");
           flags |= TJ.FLAG_ACCURATEDCT;
-        }
-        else usage();
+        } else usage();
       }
+
+      /* Determine input and output image formats based on file extensions. */
       String[] inFileTokens = argv[0].split("\\.");
       if (inFileTokens.length > 1)
         inFormat = inFileTokens[inFileTokens.length - 1];
@@ -239,61 +270,75 @@
           outFormat = outFileTokens[outFileTokens.length - 1];
       }
 
-      File file = new File(argv[0]);
-      int width, height;
-
       if (inFormat.equalsIgnoreCase("jpg")) {
-        FileInputStream fis = new FileInputStream(file);
-        int inputSize = fis.available();
-        if (inputSize < 1) {
+        /* Input image is a JPEG image.  Decompress and/or transform it. */
+        boolean doTransform = (xform.op != TJTransform.OP_NONE ||
+                               xform.options != 0 || xform.cf != null);
+
+        /* Read the JPEG file into memory. */
+        File jpegFile = new File(argv[0]);
+        FileInputStream fis = new FileInputStream(jpegFile);
+        int jpegSize = fis.available();
+        if (jpegSize < 1) {
           System.out.println("Input file contains no data");
           System.exit(1);
         }
-        byte[] inputBuf = new byte[inputSize];
-        fis.read(inputBuf);
+        byte[] jpegBuf = new byte[jpegSize];
+        fis.read(jpegBuf);
         fis.close();
 
         TJDecompressor tjd;
-        if (xform.op != TJTransform.OP_NONE || xform.options != 0 ||
-            xform.cf != null) {
-          TJTransformer tjt = new TJTransformer(inputBuf);
-          TJTransform[] t = new TJTransform[1];
-          t[0] = xform;
-          t[0].options |= TJTransform.OPT_TRIM;
-          TJDecompressor[] tjdx = tjt.transform(t, 0);
-          tjd = tjdx[0];
+        if (doTransform) {
+          /* Transform it. */
+          TJTransformer tjt = new TJTransformer(jpegBuf);
+          TJTransform[] xforms = new TJTransform[1];
+          xforms[0] = xform;
+          xforms[0].options |= TJTransform.OPT_TRIM;
+          TJDecompressor[] tjds = tjt.transform(xforms, 0);
+          tjd = tjds[0];
+          tjt.close();
         } else
-          tjd = new TJDecompressor(inputBuf);
+          tjd = new TJDecompressor(jpegBuf);
 
         width = tjd.getWidth();
         height = tjd.getHeight();
         int inSubsamp = tjd.getSubsamp();
-        System.out.println("Source Image: " + width + " x " + height +
-                           " pixels, " + sampName[inSubsamp] + " subsampling");
-        if (outSubsamp < 0)
-          outSubsamp = inSubsamp;
+        int inColorspace = tjd.getColorspace();
 
-        if (outFormat.equalsIgnoreCase("jpg") &&
-            (xform.op != TJTransform.OP_NONE || xform.options != 0) &&
-            scaleFactor.isOne()) {
-          file = new File(argv[1]);
-          FileOutputStream fos = new FileOutputStream(file);
+        System.out.println((doTransform ? "Transformed" : "Input") +
+                           " Image (jpg):  " + width + " x " + height +
+                           " pixels, " + SUBSAMP_NAME[inSubsamp] +
+                           " subsampling, " + COLORSPACE_NAME[inColorspace]);
+
+        if (outFormat.equalsIgnoreCase("jpg") && doTransform &&
+            scalingFactor.isOne() && outSubsamp < 0 && outQual < 0) {
+          /* Input image has been transformed, and no re-compression options
+             have been selected.  Write the transformed image to disk and
+             exit. */
+          File outFile = new File(argv[1]);
+          FileOutputStream fos = new FileOutputStream(outFile);
           fos.write(tjd.getJPEGBuf(), 0, tjd.getJPEGSize());
           fos.close();
           System.exit(0);
         }
 
-        width = scaleFactor.getScaled(width);
-        height = scaleFactor.getScaled(height);
+        /* Scaling and/or a non-JPEG output image format and/or compression
+           options have been selected, so we need to decompress the
+           input/transformed image. */
+        width = scalingFactor.getScaled(width);
+        height = scalingFactor.getScaled(height);
+        if (outSubsamp < 0)
+          outSubsamp = inSubsamp;
 
         if (!outFormat.equalsIgnoreCase("jpg"))
           img = tjd.decompress(width, height, BufferedImage.TYPE_INT_RGB,
                                flags);
         else
-          bmpBuf = tjd.decompress(width, 0, height, TJ.PF_BGRX, flags);
+          imgBuf = tjd.decompress(width, 0, height, TJ.PF_BGRX, flags);
         tjd.close();
       } else {
-        img = ImageIO.read(file);
+        /* Input image is not a JPEG image.  Load it into memory. */
+        img = ImageIO.read(new File(argv[0]));
         if (img == null)
           throw new Exception("Input image type not supported.");
         width = img.getWidth();
@@ -302,61 +347,59 @@
           if (img.getType() == BufferedImage.TYPE_BYTE_GRAY)
             outSubsamp = TJ.SAMP_GRAY;
           else
-            outSubsamp = TJ.SAMP_444;
+            outSubsamp = DEFAULT_SUBSAMP;
         }
+        System.out.println("Input Image:  " + width + " x " + height +
+                           " pixels");
       }
       System.gc();
       if (!display)
-        System.out.print("Dest. Image (" + outFormat + "):  " + width + " x " +
-                         height + " pixels");
+        System.out.print("Output Image (" + outFormat + "):  " + width +
+                         " x " + height + " pixels");
 
       if (display) {
+        /* Display the uncompressed image */
         ImageIcon icon = new ImageIcon(img);
         JLabel label = new JLabel(icon, JLabel.CENTER);
         JOptionPane.showMessageDialog(null, label, "Output Image",
                                       JOptionPane.PLAIN_MESSAGE);
       } else if (outFormat.equalsIgnoreCase("jpg")) {
-        System.out.println(", " + sampName[outSubsamp] +
+        /* Output image format is JPEG.  Compress the uncompressed image. */
+        if (outQual < 0)
+          outQual = DEFAULT_QUALITY;
+        System.out.println(", " + SUBSAMP_NAME[outSubsamp] +
                            " subsampling, quality = " + outQual);
-        TJCompressor tjc = new TJCompressor();
-        int jpegSize;
-        byte[] jpegBuf;
 
+        TJCompressor tjc = new TJCompressor();
         tjc.setSubsamp(outSubsamp);
         tjc.setJPEGQuality(outQual);
         if (img != null)
           tjc.setSourceImage(img, 0, 0, 0, 0);
-        else {
-          tjc.setSourceImage(bmpBuf, 0, 0, width, 0, height, TJ.PF_BGRX);
-        }
-        jpegBuf = tjc.compress(flags);
-        jpegSize = tjc.getCompressedSize();
+        else
+          tjc.setSourceImage(imgBuf, 0, 0, width, 0, height, TJ.PF_BGRX);
+        byte[] jpegBuf = tjc.compress(flags);
+        int jpegSize = tjc.getCompressedSize();
         tjc.close();
 
-        file = new File(argv[1]);
-        FileOutputStream fos = new FileOutputStream(file);
+        /* Write the JPEG image to disk. */
+        File outFile = new File(argv[1]);
+        FileOutputStream fos = new FileOutputStream(outFile);
         fos.write(jpegBuf, 0, jpegSize);
         fos.close();
       } else {
+        /* Output image format is not JPEG.  Save the uncompressed image
+           directly to disk. */
         System.out.print("\n");
-        file = new File(argv[1]);
-        ImageIO.write(img, outFormat, file);
+        File outFile = new File(argv[1]);
+        ImageIO.write(img, outFormat, outFile);
       }
 
-    } catch(Exception e) {
+    } catch (Exception e) {
       e.printStackTrace();
       System.exit(-1);
     }
   }
 
-  public void customFilter(ShortBuffer coeffBuffer, Rectangle bufferRegion,
-                           Rectangle planeRegion, int componentIndex,
-                           int transformIndex, TJTransform transform)
-                           throws TJException {
-    for (int i = 0; i < bufferRegion.width * bufferRegion.height; i++) {
-      coeffBuffer.put(i, (short)(-coeffBuffer.get(i)));
-    }
-  }
-
-  static TJScalingFactor[] sf = null;
+  static final TJScalingFactor[] SCALING_FACTORS =
+    TJ.getScalingFactors();
 };
diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java
index 47ff7bb..91ad5fd 100644
--- a/java/TJUnitTest.java
+++ b/java/TJUnitTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011-2017 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011-2018 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:
@@ -37,13 +37,16 @@
 import java.nio.*;
 import org.libjpegturbo.turbojpeg.*;
 
-public class TJUnitTest {
+@SuppressWarnings("checkstyle:JavadocType")
+final class TJUnitTest {
 
-  private static final String classname =
+  private TJUnitTest() {}
+
+  static final String CLASS_NAME =
     new TJUnitTest().getClass().getName();
 
-  private static void usage() {
-    System.out.println("\nUSAGE: java " + classname + " [options]\n");
+  static void usage() {
+    System.out.println("\nUSAGE: java " + CLASS_NAME + " [options]\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");
@@ -52,43 +55,39 @@
     System.exit(1);
   }
 
-  private static final String[] subNameLong = {
+  static final String[] SUBNAME_LONG = {
     "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0", "4:1:1"
   };
-  private static final String[] subName = {
+  static final String[] SUBNAME = {
     "444", "422", "420", "GRAY", "440", "411"
   };
 
-  private static final String[] pixFormatStr = {
+  static final String[] PIXFORMATSTR = {
     "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale",
     "RGBA", "BGRA", "ABGR", "ARGB", "CMYK"
   };
 
-  private static final int[] alphaOffset = {
-    -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1
-  };
-
-  private static final int[] _3byteFormats = {
+  static final int[] FORMATS_3BYTE = {
     TJ.PF_RGB, TJ.PF_BGR
   };
-  private static final int[] _3byteFormatsBI = {
+  static final int[] FORMATS_3BYTEBI = {
     BufferedImage.TYPE_3BYTE_BGR
   };
-  private static final int[] _4byteFormats = {
+  static final int[] FORMATS_4BYTE = {
     TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB, TJ.PF_CMYK
   };
-  private static final int[] _4byteFormatsBI = {
+  static final int[] FORMATS_4BYTEBI = {
     BufferedImage.TYPE_INT_BGR, BufferedImage.TYPE_INT_RGB,
     BufferedImage.TYPE_4BYTE_ABGR, BufferedImage.TYPE_4BYTE_ABGR_PRE,
     BufferedImage.TYPE_INT_ARGB, BufferedImage.TYPE_INT_ARGB_PRE
   };
-  private static final int[] onlyGray = {
+  static final int[] FORMATS_GRAY = {
     TJ.PF_GRAY
   };
-  private static final int[] onlyGrayBI = {
+  static final int[] FORMATS_GRAYBI = {
     BufferedImage.TYPE_BYTE_GRAY
   };
-  private static final int[] onlyRGB = {
+  static final int[] FORMATS_RGB = {
     TJ.PF_RGB
   };
 
@@ -98,55 +97,57 @@
 
   private static int exitStatus = 0;
 
-  private static int biTypePF(int biType) {
+  static int biTypePF(int biType) {
     ByteOrder byteOrder = ByteOrder.nativeOrder();
-    switch(biType) {
-      case BufferedImage.TYPE_3BYTE_BGR:
-        return TJ.PF_BGR;
-      case BufferedImage.TYPE_4BYTE_ABGR:
-      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
-        return TJ.PF_ABGR;
-      case BufferedImage.TYPE_BYTE_GRAY:
-        return TJ.PF_GRAY;
-      case BufferedImage.TYPE_INT_BGR:
-        return TJ.PF_RGBX;
-      case BufferedImage.TYPE_INT_RGB:
-        return TJ.PF_BGRX;
-      case BufferedImage.TYPE_INT_ARGB:
-      case BufferedImage.TYPE_INT_ARGB_PRE:
-        return TJ.PF_BGRA;
+    switch (biType) {
+    case BufferedImage.TYPE_3BYTE_BGR:
+      return TJ.PF_BGR;
+    case BufferedImage.TYPE_4BYTE_ABGR:
+    case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+      return TJ.PF_ABGR;
+    case BufferedImage.TYPE_BYTE_GRAY:
+      return TJ.PF_GRAY;
+    case BufferedImage.TYPE_INT_BGR:
+      return TJ.PF_RGBX;
+    case BufferedImage.TYPE_INT_RGB:
+      return TJ.PF_BGRX;
+    case BufferedImage.TYPE_INT_ARGB:
+    case BufferedImage.TYPE_INT_ARGB_PRE:
+      return TJ.PF_BGRA;
+    default:
+      return 0;
     }
-    return 0;
   }
 
-  private static String biTypeStr(int biType) {
-    switch(biType) {
-      case BufferedImage.TYPE_3BYTE_BGR:
-        return "3BYTE_BGR";
-      case BufferedImage.TYPE_4BYTE_ABGR:
-        return "4BYTE_ABGR";
-      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
-        return "4BYTE_ABGR_PRE";
-      case BufferedImage.TYPE_BYTE_GRAY:
-        return "BYTE_GRAY";
-      case BufferedImage.TYPE_INT_BGR:
-        return "INT_BGR";
-      case BufferedImage.TYPE_INT_RGB:
-        return "INT_RGB";
-      case BufferedImage.TYPE_INT_ARGB:
-        return "INT_ARGB";
-      case BufferedImage.TYPE_INT_ARGB_PRE:
-        return "INT_ARGB_PRE";
+  static String biTypeStr(int biType) {
+    switch (biType) {
+    case BufferedImage.TYPE_3BYTE_BGR:
+      return "3BYTE_BGR";
+    case BufferedImage.TYPE_4BYTE_ABGR:
+      return "4BYTE_ABGR";
+    case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+      return "4BYTE_ABGR_PRE";
+    case BufferedImage.TYPE_BYTE_GRAY:
+      return "BYTE_GRAY";
+    case BufferedImage.TYPE_INT_BGR:
+      return "INT_BGR";
+    case BufferedImage.TYPE_INT_RGB:
+      return "INT_RGB";
+    case BufferedImage.TYPE_INT_ARGB:
+      return "INT_ARGB";
+    case BufferedImage.TYPE_INT_ARGB_PRE:
+      return "INT_ARGB_PRE";
+    default:
+      return "Unknown";
     }
-    return "Unknown";
   }
 
-  private static void initBuf(byte[] buf, int w, int pitch, int h, int pf,
-                              int flags) throws Exception {
+  static void initBuf(byte[] buf, int w, int pitch, int h, int pf, int flags)
+                      throws Exception {
     int roffset = TJ.getRedOffset(pf);
     int goffset = TJ.getGreenOffset(pf);
     int boffset = TJ.getBlueOffset(pf);
-    int aoffset = alphaOffset[pf];
+    int aoffset = TJ.getAlphaOffset(pf);
     int ps = TJ.getPixelSize(pf);
     int index, row, col, halfway = 16;
 
@@ -210,12 +211,12 @@
     }
   }
 
-  private static void initIntBuf(int[] buf, int w, int pitch, int h, int pf,
-                                 int flags) throws Exception {
+  static void initIntBuf(int[] buf, int w, int pitch, int h, int pf, int flags)
+                         throws Exception {
     int rshift = TJ.getRedOffset(pf) * 8;
     int gshift = TJ.getGreenOffset(pf) * 8;
     int bshift = TJ.getBlueOffset(pf) * 8;
-    int ashift = alphaOffset[pf] * 8;
+    int ashift = TJ.getAlphaOffset(pf) * 8;
     int index, row, col, halfway = 16;
 
     Arrays.fill(buf, 0);
@@ -242,10 +243,10 @@
     }
   }
 
-  private static void initImg(BufferedImage img, int pf, int flags)
-                              throws Exception {
+  static void initImg(BufferedImage img, int pf, int flags) throws Exception {
     WritableRaster wr = img.getRaster();
     int imgType = img.getType();
+
     if (imgType == BufferedImage.TYPE_INT_RGB ||
         imgType == BufferedImage.TYPE_INT_BGR ||
         imgType == BufferedImage.TYPE_INT_ARGB ||
@@ -265,8 +266,8 @@
     }
   }
 
-  private static void checkVal(int row, int col, int v, String vname, int cv)
-                               throws Exception {
+  static void checkVal(int row, int col, int v, String vname, int cv)
+                       throws Exception {
     v = (v < 0) ? v + 256 : v;
     if (v < cv - 1 || v > cv + 1) {
       throw new Exception("Comp. " + vname + " at " + row + "," + col +
@@ -274,8 +275,8 @@
     }
   }
 
-  private static void checkVal0(int row, int col, int v, String vname)
-                                throws Exception {
+  static void checkVal0(int row, int col, int v, String vname)
+                        throws Exception {
     v = (v < 0) ? v + 256 : v;
     if (v > 1) {
       throw new Exception("Comp. " + vname + " at " + row + "," + col +
@@ -283,8 +284,8 @@
     }
   }
 
-  private static void checkVal255(int row, int col, int v, String vname)
-                                  throws Exception {
+  static void checkVal255(int row, int col, int v, String vname)
+                          throws Exception {
     v = (v < 0) ? v + 256 : v;
     if (v < 254) {
       throw new Exception("Comp. " + vname + " at " + row + "," + col +
@@ -292,13 +293,12 @@
     }
   }
 
-  private static int checkBuf(byte[] buf, int w, int pitch, int h, int pf,
-                              int subsamp, TJScalingFactor sf, int flags)
-                              throws Exception {
+  static int checkBuf(byte[] buf, int w, int pitch, int h, int pf, int subsamp,
+                      TJScalingFactor sf, int flags) throws Exception {
     int roffset = TJ.getRedOffset(pf);
     int goffset = TJ.getGreenOffset(pf);
     int boffset = TJ.getBlueOffset(pf);
-    int aoffset = alphaOffset[pf];
+    int aoffset = TJ.getAlphaOffset(pf);
     int ps = TJ.getPixelSize(pf);
     int index, row, col, retval = 1;
     int halfway = 16 * sf.getNum() / sf.getDenom();
@@ -306,6 +306,9 @@
 
     try {
 
+      if (pf == TJ.PF_GRAY)
+        roffset = goffset = boffset = 0;
+
       if (pf == TJ.PF_CMYK) {
         for (row = 0; row < h; row++) {
           for (col = 0; col < w; col++) {
@@ -382,7 +385,7 @@
           checkVal255(row, col, a, "A");
         }
       }
-    } catch(Exception e) {
+    } catch (Exception e) {
       System.out.println("\n" + e.getMessage());
       retval = 0;
     }
@@ -416,13 +419,13 @@
     return retval;
   }
 
-  private static int checkIntBuf(int[] buf, int w, int pitch, int h, int pf,
-                                 int subsamp, TJScalingFactor sf, int flags)
-                                 throws Exception {
+  static int checkIntBuf(int[] buf, int w, int pitch, int h, int pf,
+                         int subsamp, TJScalingFactor sf, int flags)
+                         throws Exception {
     int rshift = TJ.getRedOffset(pf) * 8;
     int gshift = TJ.getGreenOffset(pf) * 8;
     int bshift = TJ.getBlueOffset(pf) * 8;
-    int ashift = alphaOffset[pf] * 8;
+    int ashift = TJ.getAlphaOffset(pf) * 8;
     int index, row, col, retval = 1;
     int halfway = 16 * sf.getNum() / sf.getDenom();
     int blockSize = 8 * sf.getNum() / sf.getDenom();
@@ -472,7 +475,7 @@
           checkVal255(row, col, a, "A");
         }
       }
-    } catch(Exception e) {
+    } catch (Exception e) {
       System.out.println("\n" + e.getMessage());
       retval = 0;
     }
@@ -494,8 +497,8 @@
     return retval;
   }
 
-  private static int checkImg(BufferedImage img, int pf, int subsamp,
-                              TJScalingFactor sf, int flags) throws Exception {
+  static int checkImg(BufferedImage img, int pf, int subsamp,
+                      TJScalingFactor sf, int flags) throws Exception {
     WritableRaster wr = img.getRaster();
     int imgType = img.getType();
     if (imgType == BufferedImage.TYPE_INT_RGB ||
@@ -519,18 +522,17 @@
     }
   }
 
-  private static int PAD(int v, int p) {
+  static int pad(int v, int p) {
     return ((v + (p) - 1) & (~((p) - 1)));
   }
 
-  private static int checkBufYUV(byte[] buf, int size, int w, int h,
-                                 int subsamp, TJScalingFactor sf)
-                                 throws Exception {
+  static int checkBufYUV(byte[] buf, int size, int w, int h, int subsamp,
+                         TJScalingFactor sf) throws Exception {
     int row, col;
     int hsf = TJ.getMCUWidth(subsamp) / 8, vsf = TJ.getMCUHeight(subsamp) / 8;
-    int pw = PAD(w, hsf), ph = PAD(h, vsf);
+    int pw = pad(w, hsf), ph = pad(h, vsf);
     int cw = pw / hsf, ch = ph / vsf;
-    int ypitch = PAD(pw, pad), uvpitch = PAD(cw, pad);
+    int ypitch = pad(pw, pad), uvpitch = pad(cw, pad);
     int retval = 1;
     int correctsize = ypitch * ph +
                       (subsamp == TJ.SAMP_GRAY ? 0 : uvpitch * ch * 2);
@@ -579,7 +581,7 @@
           }
         }
       }
-    } catch(Exception e) {
+    } catch (Exception e) {
       System.out.println("\n" + e.getMessage());
       retval = 0;
     }
@@ -616,17 +618,17 @@
     return retval;
   }
 
-  private static void writeJPEG(byte[] jpegBuf, int jpegBufSize,
-                                String filename) throws Exception {
+  static void writeJPEG(byte[] jpegBuf, int jpegBufSize, String filename)
+                        throws Exception {
     File file = new File(filename);
     FileOutputStream fos = new FileOutputStream(file);
     fos.write(jpegBuf, 0, jpegBufSize);
     fos.close();
   }
 
-  private static int compTest(TJCompressor tjc, byte[] dstBuf, int w,
-                              int h, int pf, String baseName, int subsamp,
-                              int jpegQual, int flags) throws Exception {
+  static int compTest(TJCompressor tjc, byte[] dstBuf, int w, int h, int pf,
+                      String baseName, int subsamp, int jpegQual, int flags)
+                      throws Exception {
     String tempStr;
     byte[] srcBuf = null;
     BufferedImage img = null;
@@ -639,9 +641,9 @@
     if (bi) {
       pf = biTypePF(imgType);
       pfStr = biTypeStr(imgType);
-      pfStrLong = pfStr + " (" + pixFormatStr[pf] + ")";
+      pfStrLong = pfStr + " (" + PIXFORMATSTR[pf] + ")";
     } else {
-      pfStr = pixFormatStr[pf];
+      pfStr = PIXFORMATSTR[pf];
       pfStrLong = pfStr;
     }
     ps =  TJ.getPixelSize(pf);
@@ -650,7 +652,7 @@
       img = new BufferedImage(w, h, imgType);
       initImg(img, pf, flags);
       tempStr = baseName + "_enc_" + pfStr + "_" + buStr + "_" +
-                subName[subsamp] + "_Q" + jpegQual + ".png";
+                SUBNAME[subsamp] + "_Q" + jpegQual + ".png";
       File file = new File(tempStr);
       ImageIO.write(img, "png", file);
       tjc.setSourceImage(img, 0, 0, 0, 0);
@@ -665,38 +667,37 @@
     tjc.setJPEGQuality(jpegQual);
     if (doYUV) {
       System.out.format("%s %s -> YUV %s ... ", pfStrLong, buStrLong,
-                        subNameLong[subsamp]);
+                        SUBNAME_LONG[subsamp]);
       YUVImage yuvImage = tjc.encodeYUV(pad, flags);
       if (checkBufYUV(yuvImage.getBuf(), yuvImage.getSize(), w, h, subsamp,
-          new TJScalingFactor(1, 1)) == 1)
+                      new TJScalingFactor(1, 1)) == 1)
         System.out.print("Passed.\n");
       else {
         System.out.print("FAILED!\n");
         exitStatus = -1;
       }
 
-      System.out.format("YUV %s %s -> JPEG Q%d ... ", subNameLong[subsamp],
+      System.out.format("YUV %s %s -> JPEG Q%d ... ", SUBNAME_LONG[subsamp],
                         buStrLong, jpegQual);
       tjc.setSourceImage(yuvImage);
     } else {
       System.out.format("%s %s -> %s Q%d ... ", pfStrLong, buStrLong,
-                        subNameLong[subsamp], jpegQual);
+                        SUBNAME_LONG[subsamp], jpegQual);
     }
     tjc.compress(dstBuf, flags);
     size = tjc.getCompressedSize();
 
     tempStr = baseName + "_enc_" + pfStr + "_" + buStr + "_" +
-              subName[subsamp] + "_Q" + jpegQual + ".jpg";
+              SUBNAME[subsamp] + "_Q" + jpegQual + ".jpg";
     writeJPEG(dstBuf, size, tempStr);
     System.out.println("Done.\n  Result in " + tempStr);
 
     return size;
   }
 
-  private static void decompTest(TJDecompressor tjd, byte[] jpegBuf,
-                                 int jpegSize, int w, int h, int pf,
-                                 String baseName, int subsamp, int flags,
-                                 TJScalingFactor sf) throws Exception {
+  static void decompTest(TJDecompressor tjd, byte[] jpegBuf, int jpegSize,
+                         int w, int h, int pf, String baseName, int subsamp,
+                         int flags, TJScalingFactor sf) throws Exception {
     String pfStr, pfStrLong, tempStr;
     String buStrLong = (flags & TJ.FLAG_BOTTOMUP) != 0 ?
                        "Bottom-Up" : "Top-Down ";
@@ -709,9 +710,9 @@
     if (bi) {
       pf = biTypePF(imgType);
       pfStr = biTypeStr(imgType);
-      pfStrLong = pfStr + " (" + pixFormatStr[pf] + ")";
+      pfStrLong = pfStr + " (" + PIXFORMATSTR[pf] + ")";
     } else {
-      pfStr = pixFormatStr[pf];
+      pfStr = PIXFORMATSTR[pf];
       pfStrLong = pfStr;
     }
 
@@ -728,8 +729,8 @@
       throw new Exception("Scaled size mismatch");
 
     if (doYUV) {
-      System.out.format("JPEG -> YUV %s ", subNameLong[subsamp]);
-      if(!sf.isOne())
+      System.out.format("JPEG -> YUV %s ", SUBNAME_LONG[subsamp]);
+      if (!sf.isOne())
         System.out.format("%d/%d ... ", sf.getNum(), sf.getDenom());
       else System.out.print("... ");
       YUVImage yuvImage = tjd.decompressToYUV(scaledWidth, pad, scaledHeight,
@@ -741,12 +742,12 @@
         System.out.print("FAILED!\n");  exitStatus = -1;
       }
 
-      System.out.format("YUV %s -> %s %s ... ", subNameLong[subsamp],
+      System.out.format("YUV %s -> %s %s ... ", SUBNAME_LONG[subsamp],
                         pfStrLong, buStrLong);
       tjd.setSourceImage(yuvImage);
     } else {
       System.out.format("JPEG -> %s %s ", pfStrLong, buStrLong);
-      if(!sf.isOne())
+      if (!sf.isOne())
         System.out.format("%d/%d ... ", sf.getNum(), sf.getDenom());
       else System.out.print("... ");
     }
@@ -758,7 +759,7 @@
     if (bi) {
       tempStr = baseName + "_dec_" + pfStr + "_" +
                 (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_" +
-                subName[subsamp] + "_" +
+                SUBNAME[subsamp] + "_" +
                 (double)sf.getNum() / (double)sf.getDenom() + "x" + ".png";
       File file = new File(tempStr);
       ImageIO.write(img, "png", file);
@@ -775,10 +776,9 @@
     }
   }
 
-  private static void decompTest(TJDecompressor tjd, byte[] jpegBuf,
-                                 int jpegSize, int w, int h, int pf,
-                                 String baseName, int subsamp,
-                                 int flags) throws Exception {
+  static void decompTest(TJDecompressor tjd, byte[] jpegBuf, int jpegSize,
+                         int w, int h, int pf, String baseName, int subsamp,
+                         int flags) throws Exception {
     int i;
     TJScalingFactor[] sf = TJ.getScalingFactors();
     for (i = 0; i < sf.length; i++) {
@@ -794,8 +794,8 @@
     }
   }
 
-  private static void doTest(int w, int h, int[] formats, int subsamp,
-                             String baseName) throws Exception {
+  static void doTest(int w, int h, int[] formats, int subsamp, String baseName)
+                     throws Exception {
     TJCompressor tjc = null;
     TJDecompressor tjd = null;
     int size;
@@ -828,7 +828,7 @@
         }
       }
       System.out.print("--------------------\n\n");
-    } catch(Exception e) {
+    } catch (Exception e) {
       if (tjc != null) tjc.close();
       if (tjd != null) tjd.close();
       throw e;
@@ -837,7 +837,7 @@
     if (tjd != null) tjd.close();
   }
 
-  private static void bufSizeTest() throws Exception {
+  static void bufSizeTest() throws Exception {
     int w, h, i, subsamp;
     byte[] srcBuf, dstBuf = null;
     YUVImage dstImage = null;
@@ -889,7 +889,7 @@
         }
       }
       System.out.println("Done.      ");
-    } catch(Exception e) {
+    } catch (Exception e) {
       if (tjc != null) tjc.close();
       throw e;
     }
@@ -911,46 +911,47 @@
           usage();
       }
       if (doYUV)
-        _4byteFormats[4] = -1;
-      doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_444,
+        FORMATS_4BYTE[4] = -1;
+      doTest(35, 39, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_444,
              testName);
-      doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_444,
+      doTest(39, 41, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_444,
              testName);
-      doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_422,
+      doTest(41, 35, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_422,
              testName);
-      doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_422,
+      doTest(35, 39, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_422,
              testName);
-      doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_420,
+      doTest(39, 41, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_420,
              testName);
-      doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_420,
+      doTest(41, 35, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_420,
              testName);
-      doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_440,
+      doTest(35, 39, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_440,
              testName);
-      doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_440,
+      doTest(39, 41, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_440,
              testName);
-      doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_411,
+      doTest(41, 35, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_411,
              testName);
-      doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_411,
+      doTest(35, 39, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_411,
              testName);
-      doTest(39, 41, bi ? onlyGrayBI : onlyGray, TJ.SAMP_GRAY, testName);
-      doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_GRAY,
+      doTest(39, 41, bi ? FORMATS_GRAYBI : FORMATS_GRAY, TJ.SAMP_GRAY,
              testName);
-      _4byteFormats[4] = -1;
-      doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY,
+      doTest(41, 35, bi ? FORMATS_3BYTEBI : FORMATS_3BYTE, TJ.SAMP_GRAY,
+             testName);
+      FORMATS_4BYTE[4] = -1;
+      doTest(35, 39, bi ? FORMATS_4BYTEBI : FORMATS_4BYTE, TJ.SAMP_GRAY,
              testName);
       if (!bi)
         bufSizeTest();
       if (doYUV && !bi) {
         System.out.print("\n--------------------\n\n");
-        doTest(48, 48, onlyRGB, TJ.SAMP_444, "javatest_yuv0");
-        doTest(48, 48, onlyRGB, TJ.SAMP_422, "javatest_yuv0");
-        doTest(48, 48, onlyRGB, TJ.SAMP_420, "javatest_yuv0");
-        doTest(48, 48, onlyRGB, TJ.SAMP_440, "javatest_yuv0");
-        doTest(48, 48, onlyRGB, TJ.SAMP_411, "javatest_yuv0");
-        doTest(48, 48, onlyRGB, TJ.SAMP_GRAY, "javatest_yuv0");
-        doTest(48, 48, onlyGray, TJ.SAMP_GRAY, "javatest_yuv0");
+        doTest(48, 48, FORMATS_RGB, TJ.SAMP_444, "javatest_yuv0");
+        doTest(48, 48, FORMATS_RGB, TJ.SAMP_422, "javatest_yuv0");
+        doTest(48, 48, FORMATS_RGB, TJ.SAMP_420, "javatest_yuv0");
+        doTest(48, 48, FORMATS_RGB, TJ.SAMP_440, "javatest_yuv0");
+        doTest(48, 48, FORMATS_RGB, TJ.SAMP_411, "javatest_yuv0");
+        doTest(48, 48, FORMATS_RGB, TJ.SAMP_GRAY, "javatest_yuv0");
+        doTest(48, 48, FORMATS_GRAY, TJ.SAMP_GRAY, "javatest_yuv0");
       }
-    } catch(Exception e) {
+    } catch (Exception e) {
       e.printStackTrace();
       exitStatus = -1;
     }
diff --git a/java/doc/constant-values.html b/java/doc/constant-values.html
index ec1b21d..fb33327 100644
--- a/java/doc/constant-values.html
+++ b/java/doc/constant-values.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="Constant Field Values";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Constant Field Values";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -115,6 +119,20 @@
 <td class="colLast"><code>4</code></td>
 </tr>
 <tr class="rowColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.ERR_FATAL">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#ERR_FATAL">ERR_FATAL</a></code></td>
+<td class="colLast"><code>1</code></td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.ERR_WARNING">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#ERR_WARNING">ERR_WARNING</a></code></td>
+<td class="colLast"><code>0</code></td>
+</tr>
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_ACCURATEDCT">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
@@ -171,6 +189,20 @@
 <td class="colLast"><code>128</code></td>
 </tr>
 <tr class="rowColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_PROGRESSIVE">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></code></td>
+<td class="colLast"><code>16384</code></td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.FLAG_STOPONWARNING">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></code></td>
+<td class="colLast"><code>8192</code></td>
+</tr>
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMCS">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
@@ -178,139 +210,146 @@
 <td class="colLast"><code>5</code></td>
 </tr>
 <tr class="altColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMERR">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></code></td>
+<td class="colLast"><code>2</code></td>
+</tr>
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMPF">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</a></code></td>
 <td class="colLast"><code>12</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.NUMSAMP">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</a></code></td>
 <td class="colLast"><code>6</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_ABGR">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_ABGR">PF_ABGR</a></code></td>
 <td class="colLast"><code>9</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_ARGB">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_ARGB">PF_ARGB</a></code></td>
 <td class="colLast"><code>10</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGR">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</a></code></td>
 <td class="colLast"><code>1</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGRA">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRA">PF_BGRA</a></code></td>
 <td class="colLast"><code>8</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_BGRX">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</a></code></td>
 <td class="colLast"><code>3</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_CMYK">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_CMYK">PF_CMYK</a></code></td>
 <td class="colLast"><code>11</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_GRAY">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</a></code></td>
 <td class="colLast"><code>6</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGB">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</a></code></td>
 <td class="colLast"><code>0</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGBA">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBA">PF_RGBA</a></code></td>
 <td class="colLast"><code>7</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_RGBX">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</a></code></td>
 <td class="colLast"><code>2</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_XBGR">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</a></code></td>
 <td class="colLast"><code>4</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.PF_XRGB">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</a></code></td>
 <td class="colLast"><code>5</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_411">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_411">SAMP_411</a></code></td>
 <td class="colLast"><code>5</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_420">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</a></code></td>
 <td class="colLast"><code>2</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_422">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</a></code></td>
 <td class="colLast"><code>1</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_440">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</a></code></td>
 <td class="colLast"><code>4</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_444">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</a></code></td>
 <td class="colLast"><code>0</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJ.SAMP_GRAY">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
@@ -393,33 +432,47 @@
 <td class="colLast"><code>2</code></td>
 </tr>
 <tr class="rowColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_COPYNONE">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_COPYNONE">OPT_COPYNONE</a></code></td>
+<td class="colLast"><code>64</code></td>
+</tr>
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_CROP">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_CROP">OPT_CROP</a></code></td>
 <td class="colLast"><code>4</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_GRAY">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_GRAY">OPT_GRAY</a></code></td>
 <td class="colLast"><code>8</code></td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_NOOUTPUT">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_NOOUTPUT">OPT_NOOUTPUT</a></code></td>
 <td class="colLast"><code>16</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_PERFECT">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
 <td><code><a href="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT">OPT_PERFECT</a></code></td>
 <td class="colLast"><code>1</code></td>
 </tr>
+<tr class="altColor">
+<td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_PROGRESSIVE">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;int</code></td>
+<td><code><a href="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PROGRESSIVE">OPT_PROGRESSIVE</a></code></td>
+<td class="colLast"><code>32</code></td>
+</tr>
 <tr class="rowColor">
 <td class="colFirst"><a name="org.libjpegturbo.turbojpeg.TJTransform.OPT_TRIM">
 <!--   -->
diff --git a/java/doc/deprecated-list.html b/java/doc/deprecated-list.html
index e47ffb1..31d4e64 100644
--- a/java/doc/deprecated-list.html
+++ b/java/doc/deprecated-list.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="Deprecated List";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Deprecated List";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/help-doc.html b/java/doc/help-doc.html
index ce749a9..6645d95 100644
--- a/java/doc/help-doc.html
+++ b/java/doc/help-doc.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="API Help";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="API Help";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/index-all.html b/java/doc/index-all.html
index a02d9c4..366c7ea 100644
--- a/java/doc/index-all.html
+++ b/java/doc/index-all.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="Index";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Index";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -278,6 +282,15 @@
 <div class="block">Returns true or false, depending on whether this instance and
  <code>other</code> have the same numerator and denominator.</div>
 </dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#ERR_FATAL">ERR_FATAL</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
+<dd>
+<div class="block">The error was fatal and non-recoverable.</div>
+</dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#ERR_WARNING">ERR_WARNING</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
+<dd>
+<div class="block">The error was non-fatal and recoverable, but the image may still be
+ corrupt.</div>
+</dd>
 </dl>
 <a name="_F_">
 <!--   -->
@@ -324,12 +337,27 @@
 <dd>
 <div class="block"><span class="strong">Deprecated.</span></div>
 </dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
+<dd>
+<div class="block">Use progressive entropy coding in JPEG images generated by compression and
+ transform operations.</div>
+</dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
+<dd>
+<div class="block">Immediately discontinue the current compression/decompression/transform
+ operation if the underlying codec throws a warning (non-fatal error).</div>
+</dd>
 </dl>
 <a name="_G_">
 <!--   -->
 </a>
 <h2 class="title">G</h2>
 <dl>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#getAlphaOffset(int)">getAlphaOffset(int)</a></span> - Static method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
+<dd>
+<div class="block">For the given pixel format, returns the number of bytes that the alpha
+ component is offset from the start of the pixel.</div>
+</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#getBlueOffset(int)">getBlueOffset(int)</a></span> - Static method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
 <dd>
 <div class="block">For the given pixel format, returns the number of bytes that the blue
@@ -354,6 +382,11 @@
 <dd>
 <div class="block">Returns denominator</div>
 </dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJException.html#getErrorCode()">getErrorCode()</a></span> - Method in exception org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></dt>
+<dd>
+<div class="block">Returns a code (one of <a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><code>TJ.ERR_*</code></a>) indicating the severity of the
+ last error.</div>
+</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#getGreenOffset(int)">getGreenOffset(int)</a></span> - Static method in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
 <dd>
 <div class="block">For the given pixel format, returns the number of bytes that the green
@@ -516,6 +549,10 @@
 <dd>
 <div class="block">The number of JPEG colorspaces</div>
 </dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
+<dd>
+<div class="block">The number of error codes</div>
+</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJTransform.html#NUMOP">NUMOP</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</a></dt>
 <dd>
 <div class="block">The number of lossless transform operations</div>
@@ -571,6 +608,11 @@
 <dd>
 <div class="block">Flip (mirror) image vertically.</div>
 </dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_COPYNONE">OPT_COPYNONE</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</a></dt>
+<dd>
+<div class="block">This option will prevent <a href="./org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][],%20org.libjpegturbo.turbojpeg.TJTransform[],%20int)"><code>TJTransformer.transform()</code></a> from copying any extra markers (including EXIF
+ and ICC profile data) from the source image to the output image.</div>
+</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_CROP">OPT_CROP</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</a></dt>
 <dd>
 <div class="block">This option will enable lossless cropping.</div>
@@ -590,6 +632,11 @@
 <div class="block">This option will cause <a href="./org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][],%20org.libjpegturbo.turbojpeg.TJTransform[],%20int)"><code>TJTransformer.transform()</code></a> to throw an exception if the transform is not
  perfect.</div>
 </dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PROGRESSIVE">OPT_PROGRESSIVE</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</a></dt>
+<dd>
+<div class="block">This option will enable progressive entropy coding in the output image
+ generated by this particular transform.</div>
+</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_TRIM">OPT_TRIM</a></span> - Static variable in class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</a></dt>
 <dd>
 <div class="block">This option will discard any partial MCU blocks that cannot be
@@ -763,8 +810,6 @@
 <dd>
 <div class="block">TurboJPEG utility class (cannot be instantiated)</div>
 </dd>
-<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJ.html#TJ()">TJ()</a></span> - Constructor for class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</a></dt>
-<dd>&nbsp;</dd>
 <dt><a href="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><span class="strong">TJCompressor</span></a> - Class in <a href="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</a></dt>
 <dd>
 <div class="block">TurboJPEG compressor</div>
@@ -829,6 +874,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.String)">TJException(String)</a></span> - Constructor for exception org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.String,%20int)">TJException(String, int)</a></span> - Constructor for exception org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.Throwable)">TJException(Throwable)</a></span> - Constructor for exception org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></dt>
 <dd>&nbsp;</dd>
 <dt><a href="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><span class="strong">TJScalingFactor</span></a> - Class in <a href="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</a></dt>
@@ -836,7 +883,9 @@
 <div class="block">Fractional scaling factor</div>
 </dd>
 <dt><span class="strong"><a href="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#TJScalingFactor(int,%20int)">TJScalingFactor(int, int)</a></span> - Constructor for class org.libjpegturbo.turbojpeg.<a href="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</a></dt>
-<dd>&nbsp;</dd>
+<dd>
+<div class="block">Create a TurboJPEG scaling factor instance.</div>
+</dd>
 <dt><a href="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><span class="strong">TJTransform</span></a> - Class in <a href="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</a></dt>
 <dd>
 <div class="block">Lossless transform parameters</div>
diff --git a/java/doc/index.html b/java/doc/index.html
index b983957..4e21075 100644
--- a/java/doc/index.html
+++ b/java/doc/index.html
@@ -4,11 +4,12 @@
 <head>
 <title>Generated Documentation (Untitled)</title>
 <script type="text/javascript">
-    targetPage = "" + window.location.search;
-    if (targetPage != "" && targetPage != "undefined")
-        targetPage = targetPage.substring(1);
-    if (targetPage.indexOf(":") != -1 || (targetPage != "" && !validURL(targetPage)))
-        targetPage = "undefined";
+    tmpTargetPage = "" + window.location.search;
+    if (tmpTargetPage != "" && tmpTargetPage != "undefined")
+        tmpTargetPage = tmpTargetPage.substring(1);
+    if (tmpTargetPage.indexOf(":") != -1 || (tmpTargetPage != "" && !validURL(tmpTargetPage)))
+        tmpTargetPage = "undefined";
+    targetPage = tmpTargetPage;
     function validURL(url) {
         try {
             url = decodeURIComponent(url);
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html
index ffef657..79f9fcf 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJ.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJ";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJ";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -59,13 +63,13 @@
 <li>Summary:&nbsp;</li>
 <li>Nested&nbsp;|&nbsp;</li>
 <li><a href="#field_summary">Field</a>&nbsp;|&nbsp;</li>
-<li><a href="#constructor_summary">Constr</a>&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
 <li><a href="#method_summary">Method</a></li>
 </ul>
 <ul class="subNavList">
 <li>Detail:&nbsp;</li>
 <li><a href="#field_detail">Field</a>&nbsp;|&nbsp;</li>
-<li><a href="#constructor_detail">Constr</a>&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
 <li><a href="#method_detail">Method</a></li>
 </ul>
 </div>
@@ -145,6 +149,19 @@
 </tr>
 <tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#ERR_FATAL">ERR_FATAL</a></strong></code>
+<div class="block">The error was fatal and non-recoverable.</div>
+</td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#ERR_WARNING">ERR_WARNING</a></strong></code>
+<div class="block">The error was non-fatal and recoverable, but the image may still be
+ corrupt.</div>
+</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_ACCURATEDCT">FLAG_ACCURATEDCT</a></strong></code>
 <div class="block">Use the most accurate DCT/IDCT algorithm available in the underlying
  codec.</div>
@@ -197,125 +214,145 @@
 </tr>
 <tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_PROGRESSIVE">FLAG_PROGRESSIVE</a></strong></code>
+<div class="block">Use progressive entropy coding in JPEG images generated by compression and
+ transform operations.</div>
+</td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING">FLAG_STOPONWARNING</a></strong></code>
+<div class="block">Immediately discontinue the current compression/decompression/transform
+ operation if the underlying codec throws a warning (non-fatal error).</div>
+</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMCS">NUMCS</a></strong></code>
 <div class="block">The number of JPEG colorspaces</div>
 </td>
 </tr>
 <tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMERR">NUMERR</a></strong></code>
+<div class="block">The number of error codes</div>
+</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</a></strong></code>
 <div class="block">The number of pixel formats</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</a></strong></code>
 <div class="block">The number of chrominance subsampling options</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_ABGR">PF_ABGR</a></strong></code>
 <div class="block">ABGR pixel format.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_ARGB">PF_ARGB</a></strong></code>
 <div class="block">ARGB pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</a></strong></code>
 <div class="block">BGR pixel format.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRA">PF_BGRA</a></strong></code>
 <div class="block">BGRA pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</a></strong></code>
 <div class="block">BGRX pixel format.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_CMYK">PF_CMYK</a></strong></code>
 <div class="block">CMYK pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</a></strong></code>
 <div class="block">Grayscale pixel format.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</a></strong></code>
 <div class="block">RGB pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBA">PF_RGBA</a></strong></code>
 <div class="block">RGBA pixel format.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</a></strong></code>
 <div class="block">RGBX pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</a></strong></code>
 <div class="block">XBGR pixel format.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</a></strong></code>
 <div class="block">XRGB pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_411">SAMP_411</a></strong></code>
 <div class="block">4:1:1 chrominance subsampling.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</a></strong></code>
 <div class="block">4:2:0 chrominance subsampling.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</a></strong></code>
 <div class="block">4:2:2 chrominance subsampling.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</a></strong></code>
 <div class="block">4:4:0 chrominance subsampling.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</a></strong></code>
 <div class="block">4:4:4 chrominance subsampling (no chrominance subsampling).</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_GRAY">SAMP_GRAY</a></strong></code>
 <div class="block">Grayscale.</div>
@@ -324,23 +361,6 @@
 </table>
 </li>
 </ul>
-<!-- ======== CONSTRUCTOR SUMMARY ======== -->
-<ul class="blockList">
-<li class="blockList"><a name="constructor_summary">
-<!--   -->
-</a>
-<h3>Constructor Summary</h3>
-<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Constructor Summary table, listing constructors, and an explanation">
-<caption><span>Constructors</span><span class="tabEnd">&nbsp;</span></caption>
-<tr>
-<th class="colOne" scope="col">Constructor and Description</th>
-</tr>
-<tr class="altColor">
-<td class="colOne"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#TJ()">TJ</a></strong>()</code>&nbsp;</td>
-</tr>
-</table>
-</li>
-</ul>
 <!-- ========== METHOD SUMMARY =========== -->
 <ul class="blockList">
 <li class="blockList"><a name="method_summary">
@@ -384,53 +404,60 @@
 </tr>
 <tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getAlphaOffset(int)">getAlphaOffset</a></strong>(int&nbsp;pixelFormat)</code>
+<div class="block">For the given pixel format, returns the number of bytes that the alpha
+ component is offset from the start of the pixel.</div>
+</td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getBlueOffset(int)">getBlueOffset</a></strong>(int&nbsp;pixelFormat)</code>
 <div class="block">For the given pixel format, returns the number of bytes that the blue
  component is offset from the start of the pixel.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getGreenOffset(int)">getGreenOffset</a></strong>(int&nbsp;pixelFormat)</code>
 <div class="block">For the given pixel format, returns the number of bytes that the green
  component is offset from the start of the pixel.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUHeight(int)">getMCUHeight</a></strong>(int&nbsp;subsamp)</code>
 <div class="block">Returns the MCU block height for the given level of chrominance
  subsampling.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUWidth(int)">getMCUWidth</a></strong>(int&nbsp;subsamp)</code>
 <div class="block">Returns the MCU block width for the given level of chrominance
  subsampling.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getPixelSize(int)">getPixelSize</a></strong>(int&nbsp;pixelFormat)</code>
 <div class="block">Returns the pixel size (in bytes) for the given pixel format.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getRedOffset(int)">getRedOffset</a></strong>(int&nbsp;pixelFormat)</code>
 <div class="block">For the given pixel format, returns the number of bytes that the red
  component is offset from the start of the pixel.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static <a href="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</a>[]</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#getScalingFactors()">getScalingFactors</a></strong>()</code>
 <div class="block">Returns a list of fractional scaling factors that the JPEG decompressor in
  this implementation of TurboJPEG supports.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#planeHeight(int,%20int,%20int)">planeHeight</a></strong>(int&nbsp;componentID,
            int&nbsp;height,
@@ -438,7 +465,7 @@
 <div class="block">Returns the plane height of a YUV image plane with the given parameters.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#planeSizeYUV(int,%20int,%20int,%20int,%20int)">planeSizeYUV</a></strong>(int&nbsp;componentID,
             int&nbsp;width,
@@ -449,7 +476,7 @@
  plane with the given parameters.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJ.html#planeWidth(int,%20int,%20int)">planeWidth</a></strong>(int&nbsp;componentID,
           int&nbsp;width,
@@ -938,7 +965,7 @@
 <a name="FLAG_ACCURATEDCT">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>FLAG_ACCURATEDCT</h4>
 <pre>public static final&nbsp;int FLAG_ACCURATEDCT</pre>
@@ -952,21 +979,76 @@
 <dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_ACCURATEDCT">Constant Field Values</a></dd></dl>
 </li>
 </ul>
-</li>
-</ul>
-<!-- ========= CONSTRUCTOR DETAIL ======== -->
-<ul class="blockList">
-<li class="blockList"><a name="constructor_detail">
+<a name="FLAG_STOPONWARNING">
 <!--   -->
 </a>
-<h3>Constructor Detail</h3>
-<a name="TJ()">
+<ul class="blockList">
+<li class="blockList">
+<h4>FLAG_STOPONWARNING</h4>
+<pre>public static final&nbsp;int FLAG_STOPONWARNING</pre>
+<div class="block">Immediately discontinue the current compression/decompression/transform
+ 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.
+ <p>
+ NOTE: due to the design of the TurboJPEG Java API, only certain methods
+ (specifically, <a href="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><code>TJDecompressor.decompress*()</code></a> methods
+ with a void return type) will complete and leave the output image in a
+ fully recoverable state after a non-fatal error occurs.</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_STOPONWARNING">Constant Field Values</a></dd></dl>
+</li>
+</ul>
+<a name="FLAG_PROGRESSIVE">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>FLAG_PROGRESSIVE</h4>
+<pre>public static final&nbsp;int FLAG_PROGRESSIVE</pre>
+<div class="block">Use progressive entropy coding in JPEG images generated by compression and
+ transform operations.  Progressive entropy coding will generally improve
+ compression relative to baseline entropy coding (the default), but it will
+ reduce compression and decompression performance considerably.</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_PROGRESSIVE">Constant Field Values</a></dd></dl>
+</li>
+</ul>
+<a name="NUMERR">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>NUMERR</h4>
+<pre>public static final&nbsp;int NUMERR</pre>
+<div class="block">The number of error codes</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.NUMERR">Constant Field Values</a></dd></dl>
+</li>
+</ul>
+<a name="ERR_WARNING">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>ERR_WARNING</h4>
+<pre>public static final&nbsp;int ERR_WARNING</pre>
+<div class="block">The error was non-fatal and recoverable, but the image may still be
+ corrupt.
+ <p>
+ NOTE: due to the design of the TurboJPEG Java API, only certain methods
+ (specifically, <a href="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><code>TJDecompressor.decompress*()</code></a> methods
+ with a void return type) will complete and leave the output image in a
+ fully recoverable state after a non-fatal error occurs.</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.ERR_WARNING">Constant Field Values</a></dd></dl>
+</li>
+</ul>
+<a name="ERR_FATAL">
 <!--   -->
 </a>
 <ul class="blockListLast">
 <li class="blockList">
-<h4>TJ</h4>
-<pre>public&nbsp;TJ()</pre>
+<h4>ERR_FATAL</h4>
+<pre>public static final&nbsp;int ERR_FATAL</pre>
+<div class="block">The error was fatal and non-recoverable.</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.ERR_FATAL">Constant Field Values</a></dd></dl>
 </li>
 </ul>
 </li>
@@ -1032,7 +1114,8 @@
  then the red component will be
  <code>pixel[TJ.getRedOffset(TJ.PF_BGRX)]</code>.</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>pixelFormat</code> - the pixel format (one of <code>PF_*</code>)</dd>
-<dt><span class="strong">Returns:</span></dt><dd>the red offset for the given pixel format.</dd></dl>
+<dt><span class="strong">Returns:</span></dt><dd>the red offset for the given pixel format, or -1 if the pixel
+ format does not have a red component.</dd></dl>
 </li>
 </ul>
 <a name="getGreenOffset(int)">
@@ -1048,7 +1131,8 @@
  then the green component will be
  <code>pixel[TJ.getGreenOffset(TJ.PF_BGRX)]</code>.</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>pixelFormat</code> - the pixel format (one of <code>PF_*</code>)</dd>
-<dt><span class="strong">Returns:</span></dt><dd>the green offset for the given pixel format.</dd></dl>
+<dt><span class="strong">Returns:</span></dt><dd>the green offset for the given pixel format, or -1 if the pixel
+ format does not have a green component.</dd></dl>
 </li>
 </ul>
 <a name="getBlueOffset(int)">
@@ -1064,7 +1148,25 @@
  then the blue component will be
  <code>pixel[TJ.getBlueOffset(TJ.PF_BGRX)]</code>.</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>pixelFormat</code> - the pixel format (one of <code>PF_*</code>)</dd>
-<dt><span class="strong">Returns:</span></dt><dd>the blue offset for the given pixel format.</dd></dl>
+<dt><span class="strong">Returns:</span></dt><dd>the blue offset for the given pixel format, or -1 if the pixel
+ format does not have a blue component.</dd></dl>
+</li>
+</ul>
+<a name="getAlphaOffset(int)">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>getAlphaOffset</h4>
+<pre>public static&nbsp;int&nbsp;getAlphaOffset(int&nbsp;pixelFormat)</pre>
+<div class="block">For the given pixel format, returns the number of bytes that the alpha
+ component is offset from the start of the pixel.  For instance, if a pixel
+ of format <code>TJ.PF_BGRA</code> is stored in <code>char pixel[]</code>,
+ then the alpha component will be
+ <code>pixel[TJ.getAlphaOffset(TJ.PF_BGRA)]</code>.</div>
+<dl><dt><span class="strong">Parameters:</span></dt><dd><code>pixelFormat</code> - the pixel format (one of <code>PF_*</code>)</dd>
+<dt><span class="strong">Returns:</span></dt><dd>the alpha offset for the given pixel format, or -1 if the pixel
+ format does not have a alpha component.</dd></dl>
 </li>
 </ul>
 <a name="bufSize(int, int, int)">
@@ -1236,13 +1338,13 @@
 <li>Summary:&nbsp;</li>
 <li>Nested&nbsp;|&nbsp;</li>
 <li><a href="#field_summary">Field</a>&nbsp;|&nbsp;</li>
-<li><a href="#constructor_summary">Constr</a>&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
 <li><a href="#method_summary">Method</a></li>
 </ul>
 <ul class="subNavList">
 <li>Detail:&nbsp;</li>
 <li><a href="#field_detail">Field</a>&nbsp;|&nbsp;</li>
-<li><a href="#constructor_detail">Constr</a>&nbsp;|&nbsp;</li>
+<li>Constr&nbsp;|&nbsp;</li>
 <li><a href="#method_detail">Method</a></li>
 </ul>
 </div>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
index 29f12b7..a53f879 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJCompressor";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJCompressor";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -575,8 +579,8 @@
  <p>
  NOTE: This method has no effect when compressing a JPEG image from a YUV
  planar source.  In that case, the level of chrominance subsampling in
- the JPEG image is determined by the source.  Further, this method has no
- effect when encoding to a pre-allocated <a href="../../../org/libjpegturbo/turbojpeg/YUVImage.html" title="class in org.libjpegturbo.turbojpeg"><code>YUVImage</code></a> instance.  In
+ the JPEG image is determined by the source.  Furthermore, this method has
+ no effect when encoding to a pre-allocated <a href="../../../org/libjpegturbo/turbojpeg/YUVImage.html" title="class in org.libjpegturbo.turbojpeg"><code>YUVImage</code></a> instance.  In
  that case, the level of chrominance subsampling is determined by the
  destination.</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>newSubsamp</code> - the level of chrominance subsampling to use in
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html b/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html
index 6bd6fd2..412dcd4 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJCustomFilter.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJCustomFilter";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJCustomFilter";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html
index a914de9..b281e32 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJDecompressor";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJDecompressor";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -785,7 +789,11 @@
                 throws <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></pre>
 <div class="block">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.</div>
+ to the given destination buffer.
+ <p>
+ NOTE: The output image is fully recoverable if this method throws a
+ non-fatal <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg"><code>TJException</code></a> (unless
+ <a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING"><code>TJ.FLAG_STOPONWARNING</code></a> is specified.)</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>dstBuf</code> - buffer that will receive the decompressed/decoded image.
  If the source image is a JPEG image, then this buffer should normally be
  <code>pitch * scaledHeight</code> bytes in size, where
@@ -895,7 +903,11 @@
  <code>YUVImage</code> 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.</div>
+ used to decompress JPEG source images with the CMYK or YCCK colorspace.
+ <p>
+ NOTE: The YUV planar output image is fully recoverable if this method
+ throws a non-fatal <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg"><code>TJException</code></a> (unless
+ <a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING"><code>TJ.FLAG_STOPONWARNING</code></a> is specified.)</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>dstImage</code> - <a href="../../../org/libjpegturbo/turbojpeg/YUVImage.html" title="class in org.libjpegturbo.turbojpeg"><code>YUVImage</code></a> instance that will receive the YUV planar
  image.  The level of subsampling specified in this <code>YUVImage</code>
  instance must match that of the JPEG image, and the width and height
@@ -1035,7 +1047,11 @@
                 throws <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></pre>
 <div class="block">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.</div>
+ to the given destination buffer.
+ <p>
+ NOTE: The output image is fully recoverable if this method throws a
+ non-fatal <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg"><code>TJException</code></a> (unless
+ <a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING"><code>TJ.FLAG_STOPONWARNING</code></a> is specified.)</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>dstBuf</code> - buffer that will receive the decompressed/decoded image.
  If the source image is a JPEG image, then this buffer should normally be
  <code>stride * scaledHeight</code> pixels in size, where
@@ -1092,7 +1108,11 @@
                 throws <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg">TJException</a></pre>
 <div class="block">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 <code>BufferedImage</code> instance.</div>
+ the given <code>BufferedImage</code> instance.
+ <p>
+ NOTE: The output image is fully recoverable if this method throws a
+ non-fatal <a href="../../../org/libjpegturbo/turbojpeg/TJException.html" title="class in org.libjpegturbo.turbojpeg"><code>TJException</code></a> (unless
+ <a href="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_STOPONWARNING"><code>TJ.FLAG_STOPONWARNING</code></a> is specified.)</div>
 <dl><dt><span class="strong">Parameters:</span></dt><dd><code>dstImage</code> - a <code>BufferedImage</code> instance that will receive
  the decompressed/decoded image.  If the source image is a JPEG image, then
  the width and height of the <code>BufferedImage</code> instance must match
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJException.html b/java/doc/org/libjpegturbo/turbojpeg/TJException.html
index 6088066..66d73e7 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJException.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJException.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJException";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJException";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -60,13 +64,13 @@
 <li>Nested&nbsp;|&nbsp;</li>
 <li>Field&nbsp;|&nbsp;</li>
 <li><a href="#constructor_summary">Constr</a>&nbsp;|&nbsp;</li>
-<li><a href="#methods_inherited_from_class_java.lang.Throwable">Method</a></li>
+<li><a href="#method_summary">Method</a></li>
 </ul>
 <ul class="subNavList">
 <li>Detail:&nbsp;</li>
 <li>Field&nbsp;|&nbsp;</li>
 <li><a href="#constructor_detail">Constr</a>&nbsp;|&nbsp;</li>
-<li>Method</li>
+<li><a href="#method_detail">Method</a></li>
 </ul>
 </div>
 <a name="skip-navbar_top">
@@ -138,10 +142,14 @@
 <td class="colOne"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.String)">TJException</a></strong>(java.lang.String&nbsp;message)</code>&nbsp;</td>
 </tr>
 <tr class="altColor">
+<td class="colOne"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.String,%20int)">TJException</a></strong>(java.lang.String&nbsp;message,
+           int&nbsp;code)</code>&nbsp;</td>
+</tr>
+<tr class="rowColor">
 <td class="colOne"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.String,%20java.lang.Throwable)">TJException</a></strong>(java.lang.String&nbsp;message,
            java.lang.Throwable&nbsp;cause)</code>&nbsp;</td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colOne"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJException.html#TJException(java.lang.Throwable)">TJException</a></strong>(java.lang.Throwable&nbsp;cause)</code>&nbsp;</td>
 </tr>
 </table>
@@ -153,6 +161,20 @@
 <!--   -->
 </a>
 <h3>Method Summary</h3>
+<table class="overviewSummary" border="0" cellpadding="3" cellspacing="0" summary="Method Summary table, listing methods, and an explanation">
+<caption><span>Methods</span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Method and Description</th>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJException.html#getErrorCode()">getErrorCode</a></strong>()</code>
+<div class="block">Returns a code (one of <a href="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><code>TJ.ERR_*</code></a>) indicating the severity of the
+ last error.</div>
+</td>
+</tr>
+</table>
 <ul class="blockList">
 <li class="blockList"><a name="methods_inherited_from_class_java.lang.Throwable">
 <!--   -->
@@ -209,6 +231,16 @@
 <pre>public&nbsp;TJException(java.lang.String&nbsp;message)</pre>
 </li>
 </ul>
+<a name="TJException(java.lang.String, int)">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>TJException</h4>
+<pre>public&nbsp;TJException(java.lang.String&nbsp;message,
+           int&nbsp;code)</pre>
+</li>
+</ul>
 <a name="TJException(java.lang.Throwable)">
 <!--   -->
 </a>
@@ -220,6 +252,27 @@
 </ul>
 </li>
 </ul>
+<!-- ============ METHOD DETAIL ========== -->
+<ul class="blockList">
+<li class="blockList"><a name="method_detail">
+<!--   -->
+</a>
+<h3>Method Detail</h3>
+<a name="getErrorCode()">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>getErrorCode</h4>
+<pre>public&nbsp;int&nbsp;getErrorCode()</pre>
+<div class="block">Returns a code (one of <a href="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><code>TJ.ERR_*</code></a>) indicating the severity of the
+ last error.</div>
+<dl><dt><span class="strong">Returns:</span></dt><dd>a code (one of <a href="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><code>TJ.ERR_*</code></a>) indicating the severity of the
+ last error.</dd></dl>
+</li>
+</ul>
+</li>
+</ul>
 </li>
 </ul>
 </div>
@@ -270,13 +323,13 @@
 <li>Nested&nbsp;|&nbsp;</li>
 <li>Field&nbsp;|&nbsp;</li>
 <li><a href="#constructor_summary">Constr</a>&nbsp;|&nbsp;</li>
-<li><a href="#methods_inherited_from_class_java.lang.Throwable">Method</a></li>
+<li><a href="#method_summary">Method</a></li>
 </ul>
 <ul class="subNavList">
 <li>Detail:&nbsp;</li>
 <li>Field&nbsp;|&nbsp;</li>
 <li><a href="#constructor_detail">Constr</a>&nbsp;|&nbsp;</li>
-<li>Method</li>
+<li><a href="#method_detail">Method</a></li>
 </ul>
 </div>
 <a name="skip-navbar_bottom">
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html b/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html
index 35d6882..4006bac 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJScalingFactor";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJScalingFactor";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -114,7 +118,9 @@
 </tr>
 <tr class="altColor">
 <td class="colOne"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#TJScalingFactor(int,%20int)">TJScalingFactor</a></strong>(int&nbsp;num,
-               int&nbsp;denom)</code>&nbsp;</td>
+               int&nbsp;denom)</code>
+<div class="block">Create a TurboJPEG scaling factor instance.</div>
+</td>
 </tr>
 </table>
 </li>
@@ -193,6 +199,8 @@
 <h4>TJScalingFactor</h4>
 <pre>public&nbsp;TJScalingFactor(int&nbsp;num,
                int&nbsp;denom)</pre>
+<div class="block">Create a TurboJPEG scaling factor instance.</div>
+<dl><dt><span class="strong">Parameters:</span></dt><dd><code>num</code> - numerator</dd><dd><code>denom</code> - denominator</dd></dl>
 </li>
 </ul>
 </li>
@@ -235,7 +243,8 @@
 <div class="block">Returns the scaled value of <code>dimension</code>.  This function
  performs the integer equivalent of
  <code>ceil(dimension * scalingFactor)</code>.</div>
-<dl><dt><span class="strong">Returns:</span></dt><dd>the scaled value of <code>dimension</code>.</dd></dl>
+<dl><dt><span class="strong">Parameters:</span></dt><dd><code>dimension</code> - width or height to multiply by this scaling factor</dd>
+<dt><span class="strong">Returns:</span></dt><dd>the scaled value of <code>dimension</code>.</dd></dl>
 </li>
 </ul>
 <a name="equals(org.libjpegturbo.turbojpeg.TJScalingFactor)">
@@ -247,7 +256,8 @@
 <pre>public&nbsp;boolean&nbsp;equals(<a href="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</a>&nbsp;other)</pre>
 <div class="block">Returns true or false, depending on whether this instance and
  <code>other</code> have the same numerator and denominator.</div>
-<dl><dt><span class="strong">Returns:</span></dt><dd>true or false, depending on whether this instance and
+<dl><dt><span class="strong">Parameters:</span></dt><dd><code>other</code> - the scaling factor against which to compare this one</dd>
+<dt><span class="strong">Returns:</span></dt><dd>true or false, depending on whether this instance and
  <code>other</code> have the same numerator and denominator.</dd></dl>
 </li>
 </ul>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html
index cf65bd2..5f22691 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJTransform";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJTransform";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -217,31 +221,45 @@
 </tr>
 <tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_COPYNONE">OPT_COPYNONE</a></strong></code>
+<div class="block">This option will prevent <a href="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][],%20org.libjpegturbo.turbojpeg.TJTransform[],%20int)"><code>TJTransformer.transform()</code></a> from copying any extra markers (including EXIF
+ and ICC profile data) from the source image to the output image.</div>
+</td>
+</tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_CROP">OPT_CROP</a></strong></code>
 <div class="block">This option will enable lossless cropping.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_GRAY">OPT_GRAY</a></strong></code>
 <div class="block">This option will discard the color data in the input image and produce
  a grayscale output image.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_NOOUTPUT">OPT_NOOUTPUT</a></strong></code>
 <div class="block">This option will prevent <a href="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][],%20org.libjpegturbo.turbojpeg.TJTransform[],%20int)"><code>TJTransformer.transform()</code></a> from outputting a JPEG image for this
  particular transform.</div>
 </td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT">OPT_PERFECT</a></strong></code>
 <div class="block">This option will cause <a href="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][],%20org.libjpegturbo.turbojpeg.TJTransform[],%20int)"><code>TJTransformer.transform()</code></a> to throw an exception if the transform is not
  perfect.</div>
 </td>
 </tr>
+<tr class="altColor">
+<td class="colFirst"><code>static int</code></td>
+<td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PROGRESSIVE">OPT_PROGRESSIVE</a></strong></code>
+<div class="block">This option will enable progressive entropy coding in the output image
+ generated by this particular transform.</div>
+</td>
+</tr>
 <tr class="rowColor">
 <td class="colFirst"><code>static int</code></td>
 <td class="colLast"><code><strong><a href="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_TRIM">OPT_TRIM</a></strong></code>
@@ -548,6 +566,33 @@
 <dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_NOOUTPUT">Constant Field Values</a></dd></dl>
 </li>
 </ul>
+<a name="OPT_PROGRESSIVE">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>OPT_PROGRESSIVE</h4>
+<pre>public static final&nbsp;int OPT_PROGRESSIVE</pre>
+<div class="block">This option will enable progressive entropy coding in the output image
+ generated by this particular transform.  Progressive entropy coding will
+ generally improve compression relative to baseline entropy coding (the
+ default), but it will reduce compression and decompression performance
+ considerably.</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_PROGRESSIVE">Constant Field Values</a></dd></dl>
+</li>
+</ul>
+<a name="OPT_COPYNONE">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>OPT_COPYNONE</h4>
+<pre>public static final&nbsp;int OPT_COPYNONE</pre>
+<div class="block">This option will prevent <a href="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][],%20org.libjpegturbo.turbojpeg.TJTransform[],%20int)"><code>TJTransformer.transform()</code></a> from copying any extra markers (including EXIF
+ and ICC profile data) from the source image to the output image.</div>
+<dl><dt><span class="strong">See Also:</span></dt><dd><a href="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_COPYNONE">Constant Field Values</a></dd></dl>
+</li>
+</ul>
 <a name="op">
 <!--   -->
 </a>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html
index 36cbdb1..a30fe30 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="TJTransformer";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="TJTransformer";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html b/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html
index b2be0a0..d4485ed 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/YUVImage.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="YUVImage";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="YUVImage";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/package-summary.html b/java/doc/org/libjpegturbo/turbojpeg/package-summary.html
index f94656e..dedcce5 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/package-summary.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/package-summary.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="org.libjpegturbo.turbojpeg";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="org.libjpegturbo.turbojpeg";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/package-tree.html b/java/doc/org/libjpegturbo/turbojpeg/package-tree.html
index 02a5cde..5f0f8c3 100644
--- a/java/doc/org/libjpegturbo/turbojpeg/package-tree.html
+++ b/java/doc/org/libjpegturbo/turbojpeg/package-tree.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="org.libjpegturbo.turbojpeg Class Hierarchy";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="org.libjpegturbo.turbojpeg Class Hierarchy";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/overview-tree.html b/java/doc/overview-tree.html
index 2ae76c6..b659995 100644
--- a/java/doc/overview-tree.html
+++ b/java/doc/overview-tree.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="Class Hierarchy";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Class Hierarchy";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
diff --git a/java/doc/script.js b/java/doc/script.js
new file mode 100644
index 0000000..b346356
--- /dev/null
+++ b/java/doc/script.js
@@ -0,0 +1,30 @@
+function show(type)
+{
+    count = 0;
+    for (var key in methods) {
+        var row = document.getElementById(key);
+        if ((methods[key] &  type) != 0) {
+            row.style.display = '';
+            row.className = (count++ % 2) ? rowColor : altColor;
+        }
+        else
+            row.style.display = 'none';
+    }
+    updateTabs(type);
+}
+
+function updateTabs(type)
+{
+    for (var value in tabs) {
+        var sNode = document.getElementById(tabs[value][0]);
+        var spanNode = sNode.firstChild;
+        if (value == type) {
+            sNode.className = activeTableTab;
+            spanNode.innerHTML = tabs[value][1];
+        }
+        else {
+            sNode.className = tableTab;
+            spanNode.innerHTML = "<a href=\"javascript:show("+ value + ");\">" + tabs[value][1] + "</a>";
+        }
+    }
+}
diff --git a/java/doc/serialized-form.html b/java/doc/serialized-form.html
index 846cabc..45bbc86 100644
--- a/java/doc/serialized-form.html
+++ b/java/doc/serialized-form.html
@@ -7,8 +7,12 @@
 </head>
 <body>
 <script type="text/javascript"><!--
-    if (location.href.indexOf('is-external=true') == -1) {
-        parent.document.title="Serialized Form";
+    try {
+        if (location.href.indexOf('is-external=true') == -1) {
+            parent.document.title="Serialized Form";
+        }
+    }
+    catch(err) {
     }
 //-->
 </script>
@@ -74,6 +78,19 @@
 <dt>serialVersionUID:</dt>
 <dd>1L</dd>
 </dl>
+<ul class="blockList">
+<li class="blockList"><a name="serializedForm">
+<!--   -->
+</a>
+<h3>Serialized Fields</h3>
+<ul class="blockList">
+<li class="blockListLast">
+<h4>errorCode</h4>
+<pre>int errorCode</pre>
+</li>
+</ul>
+</li>
+</ul>
 </li>
 <li class="blockList"><a name="org.libjpegturbo.turbojpeg.TJTransform">
 <!--   -->
diff --git a/java/org/libjpegturbo/turbojpeg/TJ.java b/java/org/libjpegturbo/turbojpeg/TJ.java
index 02d14c0..fbb49df 100644
--- a/java/org/libjpegturbo/turbojpeg/TJ.java
+++ b/java/org/libjpegturbo/turbojpeg/TJ.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011-2013 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011-2013, 2017-2018 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
@@ -34,6 +34,7 @@
  */
 public final class TJ {
 
+  private TJ() {}
 
   /**
    * The number of chrominance subsampling options
@@ -90,10 +91,10 @@
    */
   public static int getMCUWidth(int subsamp) {
     checkSubsampling(subsamp);
-    return mcuWidth[subsamp];
+    return MCU_WIDTH[subsamp];
   }
 
-  private static final int[] mcuWidth = {
+  private static final int[] MCU_WIDTH = {
     8, 16, 16, 8, 8, 32
   };
 
@@ -110,10 +111,10 @@
    */
   public static int getMCUHeight(int subsamp) {
     checkSubsampling(subsamp);
-    return mcuHeight[subsamp];
+    return MCU_HEIGHT[subsamp];
   }
 
-  private static final int[] mcuHeight = {
+  private static final int[] MCU_HEIGHT = {
     8, 8, 16, 8, 16, 8
   };
 
@@ -218,10 +219,10 @@
    */
   public static int getPixelSize(int pixelFormat) {
     checkPixelFormat(pixelFormat);
-    return pixelSize[pixelFormat];
+    return PIXEL_SIZE[pixelFormat];
   }
 
-  private static final int[] pixelSize = {
+  private static final int[] PIXEL_SIZE = {
     3, 3, 4, 4, 4, 4, 1, 4, 4, 4, 4, 4
   };
 
@@ -235,15 +236,16 @@
    *
    * @param pixelFormat the pixel format (one of <code>PF_*</code>)
    *
-   * @return the red offset for the given pixel format.
+   * @return the red offset for the given pixel format, or -1 if the pixel
+   * format does not have a red component.
    */
   public static int getRedOffset(int pixelFormat) {
     checkPixelFormat(pixelFormat);
-    return redOffset[pixelFormat];
+    return RED_OFFSET[pixelFormat];
   }
 
-  private static final int[] redOffset = {
-    0, 2, 0, 2, 3, 1, 0, 0, 2, 3, 1, -1
+  private static final int[] RED_OFFSET = {
+    0, 2, 0, 2, 3, 1, -1, 0, 2, 3, 1, -1
   };
 
 
@@ -256,15 +258,16 @@
    *
    * @param pixelFormat the pixel format (one of <code>PF_*</code>)
    *
-   * @return the green offset for the given pixel format.
+   * @return the green offset for the given pixel format, or -1 if the pixel
+   * format does not have a green component.
    */
   public static int getGreenOffset(int pixelFormat) {
     checkPixelFormat(pixelFormat);
-    return greenOffset[pixelFormat];
+    return GREEN_OFFSET[pixelFormat];
   }
 
-  private static final int[] greenOffset = {
-    1, 1, 1, 1, 2, 2, 0, 1, 1, 2, 2, -1
+  private static final int[] GREEN_OFFSET = {
+    1, 1, 1, 1, 2, 2, -1, 1, 1, 2, 2, -1
   };
 
 
@@ -277,15 +280,38 @@
    *
    * @param pixelFormat the pixel format (one of <code>PF_*</code>)
    *
-   * @return the blue offset for the given pixel format.
+   * @return the blue offset for the given pixel format, or -1 if the pixel
+   * format does not have a blue component.
    */
   public static int getBlueOffset(int pixelFormat) {
     checkPixelFormat(pixelFormat);
-    return blueOffset[pixelFormat];
+    return BLUE_OFFSET[pixelFormat];
   }
 
-  private static final int[] blueOffset = {
-    2, 0, 2, 0, 1, 3, 0, 2, 0, 1, 3, -1
+  private static final int[] BLUE_OFFSET = {
+    2, 0, 2, 0, 1, 3, -1, 2, 0, 1, 3, -1
+  };
+
+
+  /**
+   * For the given pixel format, returns the number of bytes that the alpha
+   * component is offset from the start of the pixel.  For instance, if a pixel
+   * of format <code>TJ.PF_BGRA</code> is stored in <code>char pixel[]</code>,
+   * then the alpha component will be
+   * <code>pixel[TJ.getAlphaOffset(TJ.PF_BGRA)]</code>.
+   *
+   * @param pixelFormat the pixel format (one of <code>PF_*</code>)
+   *
+   * @return the alpha offset for the given pixel format, or -1 if the pixel
+   * format does not have a alpha component.
+   */
+  public static int getAlphaOffset(int pixelFormat) {
+    checkPixelFormat(pixelFormat);
+    return ALPHA_OFFSET[pixelFormat];
+  }
+
+  private static final int[] ALPHA_OFFSET = {
+    -1, -1, -1, -1, -1, -1, -1, 3, 3, 0, 0, -1
   };
 
 
@@ -316,6 +342,7 @@
    * can be compressed from and decompressed to any of the extended RGB pixel
    * formats or grayscale, or they can be decompressed to YUV planar images.
    */
+  @SuppressWarnings("checkstyle:ConstantName")
   public static final int CS_YCbCr = 1;
   /**
    * Grayscale colorspace.  The JPEG image retains only the luminance data (Y
@@ -348,16 +375,20 @@
    * The uncompressed source/destination image is stored in bottom-up (Windows,
    * OpenGL) order, not top-down (X11) order.
    */
-  public static final int FLAG_BOTTOMUP     = 2;
+  public static final int FLAG_BOTTOMUP      = 2;
 
+  @SuppressWarnings("checkstyle:JavadocVariable")
   @Deprecated
-  public static final int FLAG_FORCEMMX     = 8;
+  public static final int FLAG_FORCEMMX      = 8;
+  @SuppressWarnings("checkstyle:JavadocVariable")
   @Deprecated
-  public static final int FLAG_FORCESSE     = 16;
+  public static final int FLAG_FORCESSE      = 16;
+  @SuppressWarnings("checkstyle:JavadocVariable")
   @Deprecated
-  public static final int FLAG_FORCESSE2    = 32;
+  public static final int FLAG_FORCESSE2     = 32;
+  @SuppressWarnings("checkstyle:JavadocVariable")
   @Deprecated
-  public static final int FLAG_FORCESSE3    = 128;
+  public static final int FLAG_FORCESSE3     = 128;
 
   /**
    * When decompressing an image that was compressed using chrominance
@@ -366,7 +397,7 @@
    * creates a smooth transition between neighboring chrominance components in
    * order to reduce upsampling artifacts in the decompressed image.
    */
-  public static final int FLAG_FASTUPSAMPLE = 256;
+  public static final int FLAG_FASTUPSAMPLE  = 256;
   /**
    * Use the fastest DCT/IDCT algorithm available in the underlying codec.  The
    * default if this flag is not specified is implementation-specific.  For
@@ -375,7 +406,7 @@
    * only a very slight effect on accuracy, but it uses the accurate algorithm
    * when decompressing, because this has been shown to have a larger effect.
    */
-  public static final int FLAG_FASTDCT      =  2048;
+  public static final int FLAG_FASTDCT       = 2048;
   /**
    * Use the most accurate DCT/IDCT algorithm available in the underlying
    * codec.  The default if this flag is not specified is
@@ -385,7 +416,46 @@
    * but it uses the accurate algorithm when decompressing, because this has
    * been shown to have a larger effect.
    */
-  public static final int FLAG_ACCURATEDCT  =  4096;
+  public static final int FLAG_ACCURATEDCT   = 4096;
+  /**
+   * Immediately discontinue the current compression/decompression/transform
+   * 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.
+   * <p>
+   * 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;
+  /**
+   * Use progressive entropy coding in JPEG images generated by compression and
+   * transform operations.  Progressive entropy coding will generally improve
+   * compression relative to baseline entropy coding (the default), but it will
+   * reduce compression and decompression performance considerably.
+   */
+  public static final int FLAG_PROGRESSIVE   = 16384;
+
+
+  /**
+   * The number of error codes
+   */
+  public static final int NUMERR = 2;
+  /**
+   * The error was non-fatal and recoverable, but the image may still be
+   * corrupt.
+   * <p>
+   * 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;
+  /**
+   * The error was fatal and non-recoverable.
+   */
+  public static final int ERR_FATAL = 1;
 
 
   /**
@@ -427,6 +497,7 @@
   /**
    * @deprecated Use {@link #bufSizeYUV(int, int, int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public static native int bufSizeYUV(int width, int height, int subsamp);
 
diff --git a/java/org/libjpegturbo/turbojpeg/TJCompressor.java b/java/org/libjpegturbo/turbojpeg/TJCompressor.java
index 2ff8e4d..74e5db9 100644
--- a/java/org/libjpegturbo/turbojpeg/TJCompressor.java
+++ b/java/org/libjpegturbo/turbojpeg/TJCompressor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011-2015 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011-2015, 2018 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
@@ -77,6 +77,7 @@
    * @deprecated Use
    * {@link #TJCompressor(byte[], int, int, int, int, int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public TJCompressor(byte[] srcImage, int width, int pitch, int height,
                       int pixelFormat) throws TJException {
@@ -164,6 +165,7 @@
    * @deprecated Use
    * {@link #setSourceImage(byte[], int, int, int, int, int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void setSourceImage(byte[] srcImage, int width, int pitch,
                              int height, int pixelFormat) throws TJException {
@@ -199,7 +201,7 @@
       throw new IllegalArgumentException("Invalid argument in setSourceImage()");
     srcX = x;
     srcY = y;
-    srcWidth = (width == 0) ? srcImage.getWidth(): width;
+    srcWidth = (width == 0) ? srcImage.getWidth() : width;
     srcHeight = (height == 0) ? srcImage.getHeight() : height;
     if (x + width > srcImage.getWidth() || y + height > srcImage.getHeight())
       throw new IllegalArgumentException("Compression region exceeds the bounds of the source image");
@@ -208,30 +210,30 @@
     boolean intPixels = false;
     if (byteOrder == null)
       byteOrder = ByteOrder.nativeOrder();
-    switch(srcImage.getType()) {
-      case BufferedImage.TYPE_3BYTE_BGR:
-        pixelFormat = TJ.PF_BGR;  break;
-      case BufferedImage.TYPE_4BYTE_ABGR:
-      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
-        pixelFormat = TJ.PF_XBGR;  break;
-      case BufferedImage.TYPE_BYTE_GRAY:
-        pixelFormat = TJ.PF_GRAY;  break;
-      case BufferedImage.TYPE_INT_BGR:
-        if (byteOrder == ByteOrder.BIG_ENDIAN)
-          pixelFormat = TJ.PF_XBGR;
-        else
-          pixelFormat = TJ.PF_RGBX;
-        intPixels = true;  break;
-      case BufferedImage.TYPE_INT_RGB:
-      case BufferedImage.TYPE_INT_ARGB:
-      case BufferedImage.TYPE_INT_ARGB_PRE:
-        if (byteOrder == ByteOrder.BIG_ENDIAN)
-          pixelFormat = TJ.PF_XRGB;
-        else
-          pixelFormat = TJ.PF_BGRX;
-        intPixels = true;  break;
-      default:
-        throw new IllegalArgumentException("Unsupported BufferedImage format");
+    switch (srcImage.getType()) {
+    case BufferedImage.TYPE_3BYTE_BGR:
+      pixelFormat = TJ.PF_BGR;  break;
+    case BufferedImage.TYPE_4BYTE_ABGR:
+    case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+      pixelFormat = TJ.PF_XBGR;  break;
+    case BufferedImage.TYPE_BYTE_GRAY:
+      pixelFormat = TJ.PF_GRAY;  break;
+    case BufferedImage.TYPE_INT_BGR:
+      if (byteOrder == ByteOrder.BIG_ENDIAN)
+        pixelFormat = TJ.PF_XBGR;
+      else
+        pixelFormat = TJ.PF_RGBX;
+      intPixels = true;  break;
+    case BufferedImage.TYPE_INT_RGB:
+    case BufferedImage.TYPE_INT_ARGB:
+    case BufferedImage.TYPE_INT_ARGB_PRE:
+      if (byteOrder == ByteOrder.BIG_ENDIAN)
+        pixelFormat = TJ.PF_XRGB;
+      else
+        pixelFormat = TJ.PF_BGRX;
+      intPixels = true;  break;
+    default:
+      throw new IllegalArgumentException("Unsupported BufferedImage format");
     }
     srcPixelFormat = pixelFormat;
 
@@ -285,8 +287,8 @@
    * <p>
    * NOTE: This method has no effect when compressing a JPEG image from a YUV
    * planar source.  In that case, the level of chrominance subsampling in
-   * the JPEG image is determined by the source.  Further, this method has no
-   * effect when encoding to a pre-allocated {@link YUVImage} instance.  In
+   * the JPEG image is determined by the source.  Furthermore, this method has
+   * no effect when encoding to a pre-allocated {@link YUVImage} instance.  In
    * that case, the level of chrominance subsampling is determined by the
    * destination.
    *
@@ -386,6 +388,7 @@
    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    * {@link #compress(byte[], int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void compress(BufferedImage srcImage, byte[] dstBuf, int flags)
                        throws TJException {
@@ -398,6 +401,7 @@
    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    * {@link #compress(int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public byte[] compress(BufferedImage srcImage, int flags)
                          throws TJException {
@@ -445,14 +449,16 @@
   /**
    * @deprecated Use {@link #encodeYUV(YUVImage, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void encodeYUV(byte[] dstBuf, int flags) throws TJException {
-    if(dstBuf == null)
+    if (dstBuf == null)
       throw new IllegalArgumentException("Invalid argument in encodeYUV()");
     checkSourceImage();
     checkSubsampling();
-    YUVImage yuvImage = new YUVImage(dstBuf, srcWidth, 4, srcHeight, subsamp);
-    encodeYUV(yuvImage, flags);
+    YUVImage dstYUVImage = new YUVImage(dstBuf, srcWidth, 4, srcHeight,
+                                        subsamp);
+    encodeYUV(dstYUVImage, flags);
   }
 
   /**
@@ -475,11 +481,11 @@
   public YUVImage encodeYUV(int pad, int flags) throws TJException {
     checkSourceImage();
     checkSubsampling();
-    if(pad < 1 || ((pad & (pad - 1)) != 0))
+    if (pad < 1 || ((pad & (pad - 1)) != 0))
       throw new IllegalStateException("Invalid argument in encodeYUV()");
-    YUVImage yuvImage = new YUVImage(srcWidth, pad, srcHeight, subsamp);
-    encodeYUV(yuvImage, flags);
-    return yuvImage;
+    YUVImage dstYUVImage = new YUVImage(srcWidth, pad, srcHeight, subsamp);
+    encodeYUV(dstYUVImage, flags);
+    return dstYUVImage;
   }
 
   /**
@@ -506,21 +512,22 @@
   public YUVImage encodeYUV(int[] strides, int flags) throws TJException {
     checkSourceImage();
     checkSubsampling();
-    YUVImage yuvImage = new YUVImage(srcWidth, strides, srcHeight, subsamp);
-    encodeYUV(yuvImage, flags);
-    return yuvImage;
+    YUVImage dstYUVImage = new YUVImage(srcWidth, strides, srcHeight, subsamp);
+    encodeYUV(dstYUVImage, flags);
+    return dstYUVImage;
   }
 
   /**
    * @deprecated Use {@link #encodeYUV(int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public byte[] encodeYUV(int flags) throws TJException {
     checkSourceImage();
     checkSubsampling();
-    YUVImage yuvImage = new YUVImage(srcWidth, 4, srcHeight, subsamp);
-    encodeYUV(yuvImage, flags);
-    return yuvImage.getBuf();
+    YUVImage dstYUVImage = new YUVImage(srcWidth, 4, srcHeight, subsamp);
+    encodeYUV(dstYUVImage, flags);
+    return dstYUVImage.getBuf();
   }
 
   /**
@@ -528,6 +535,7 @@
    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    * {@link #encodeYUV(byte[], int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void encodeYUV(BufferedImage srcImage, byte[] dstBuf, int flags)
                         throws TJException {
@@ -540,6 +548,7 @@
    * {@link #setSourceImage(BufferedImage, int, int, int, int)} and
    * {@link #encodeYUV(int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public byte[] encodeYUV(BufferedImage srcImage, int flags)
                           throws TJException {
@@ -567,11 +576,12 @@
       destroy();
   }
 
+  @SuppressWarnings("checkstyle:DesignForExtension")
   @Override
   protected void finalize() throws Throwable {
     try {
       close();
-    } catch(TJException e) {
+    } catch (TJException e) {
     } finally {
       super.finalize();
     }
@@ -582,44 +592,53 @@
   private native void destroy() throws TJException;
 
   // JPEG size in bytes is returned
+  @SuppressWarnings("checkstyle:HiddenField")
   @Deprecated
   private native int compress(byte[] srcBuf, int width, int pitch,
-    int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp, int jpegQual,
+    int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, int jpegQual,
     int flags) throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   private native int compress(byte[] srcBuf, int x, int y, int width,
-    int pitch, int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp,
+    int pitch, int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp,
     int jpegQual, int flags) throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   @Deprecated
   private native int compress(int[] srcBuf, int width, int stride,
-    int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp, int jpegQual,
+    int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp, int jpegQual,
     int flags) throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   private native int compress(int[] srcBuf, int x, int y, int width,
-    int stride, int height, int pixelFormat, byte[] dstBuf, int jpegSubsamp,
+    int stride, int height, int pixelFormat, byte[] jpegBuf, int jpegSubsamp,
     int jpegQual, int flags) throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   private native int compressFromYUV(byte[][] srcPlanes, int[] srcOffsets,
-    int width, int[] srcStrides, int height, int subsamp, byte[] dstBuf,
+    int width, int[] srcStrides, int height, int subsamp, byte[] jpegBuf,
     int jpegQual, int flags)
     throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   @Deprecated
   private native void encodeYUV(byte[] srcBuf, int width, int pitch,
     int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags)
     throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   private native void encodeYUV(byte[] srcBuf, int x, int y, int width,
     int pitch, int height, int pixelFormat, byte[][] dstPlanes,
     int[] dstOffsets, int[] dstStrides, int subsamp, int flags)
     throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   @Deprecated
   private native void encodeYUV(int[] srcBuf, int width, int stride,
     int height, int pixelFormat, byte[] dstBuf, int subsamp, int flags)
     throws TJException;
 
+  @SuppressWarnings("checkstyle:HiddenField")
   private native void encodeYUV(int[] srcBuf, int x, int y, int width,
     int srcStride, int height, int pixelFormat, byte[][] dstPlanes,
     int[] dstOffsets, int[] dstStrides, int subsamp, int flags)
diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java
index bd0e694..cba9ff0 100644
--- a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java
+++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011-2015 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011-2015, 2018 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
@@ -82,6 +82,7 @@
    * @param yuvImage {@link YUVImage} instance containing a YUV planar
    * image to be decoded.  This image is not modified.
    */
+  @SuppressWarnings("checkstyle:HiddenField")
   public TJDecompressor(YUVImage yuvImage) throws TJException {
     init();
     setSourceImage(yuvImage);
@@ -109,6 +110,7 @@
   /**
    * @deprecated Use {@link #setSourceImage(byte[], int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void setJPEGImage(byte[] jpegImage, int imageSize)
                            throws TJException {
@@ -308,6 +310,10 @@
    * 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.
+   * <p>
+   * 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
@@ -396,6 +402,7 @@
    * @deprecated Use
    * {@link #decompress(byte[], int, int, int, int, int, int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void decompress(byte[] dstBuf, int desiredWidth, int pitch,
                          int desiredHeight, int pixelFormat, int flags)
@@ -451,6 +458,10 @@
    * 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.
+   * <p>
+   * 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 <code>YUVImage</code>
@@ -486,11 +497,12 @@
   /**
    * @deprecated Use {@link #decompressToYUV(YUVImage, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public void decompressToYUV(byte[] dstBuf, int flags) throws TJException {
-    YUVImage dstImage = new YUVImage(dstBuf, jpegWidth, 4, jpegHeight,
-                                     jpegSubsamp);
-    decompressToYUV(dstImage, flags);
+    YUVImage dstYUVImage = new YUVImage(dstBuf, jpegWidth, 4, jpegHeight,
+                                        jpegSubsamp);
+    decompressToYUV(dstYUVImage, flags);
   }
 
   /**
@@ -545,10 +557,10 @@
 
     int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
     int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
-    YUVImage yuvImage = new YUVImage(scaledWidth, null, scaledHeight,
-                                     jpegSubsamp);
-    decompressToYUV(yuvImage, flags);
-    return yuvImage;
+    YUVImage dstYUVImage = new YUVImage(scaledWidth, null, scaledHeight,
+                                        jpegSubsamp);
+    decompressToYUV(dstYUVImage, flags);
+    return dstYUVImage;
   }
 
   /**
@@ -598,26 +610,31 @@
 
     int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
     int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
-    YUVImage yuvImage = new YUVImage(scaledWidth, pad, scaledHeight,
-                                     jpegSubsamp);
-    decompressToYUV(yuvImage, flags);
-    return yuvImage;
+    YUVImage dstYUVImage = new YUVImage(scaledWidth, pad, scaledHeight,
+                                        jpegSubsamp);
+    decompressToYUV(dstYUVImage, flags);
+    return dstYUVImage;
   }
 
   /**
    * @deprecated Use {@link #decompressToYUV(int, int, int, int)} instead.
    */
+  @SuppressWarnings("checkstyle:JavadocMethod")
   @Deprecated
   public byte[] decompressToYUV(int flags) throws TJException {
-    YUVImage dstImage = new YUVImage(jpegWidth, 4, jpegHeight, jpegSubsamp);
-    decompressToYUV(dstImage, flags);
-    return dstImage.getBuf();
+    YUVImage dstYUVImage = new YUVImage(jpegWidth, 4, jpegHeight, jpegSubsamp);
+    decompressToYUV(dstYUVImage, flags);
+    return dstYUVImage.getBuf();
   }
 
   /**
    * 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.
+   * <p>
+   * 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 +716,10 @@
    * 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 <code>BufferedImage</code> instance.
+   * <p>
+   * 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 <code>BufferedImage</code> instance that will receive
    * the decompressed/decoded image.  If the source image is a JPEG image, then
@@ -734,35 +755,35 @@
     int pixelFormat;  boolean intPixels = false;
     if (byteOrder == null)
       byteOrder = ByteOrder.nativeOrder();
-    switch(dstImage.getType()) {
-      case BufferedImage.TYPE_3BYTE_BGR:
-        pixelFormat = TJ.PF_BGR;  break;
-      case BufferedImage.TYPE_4BYTE_ABGR:
-      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
-        pixelFormat = TJ.PF_XBGR;  break;
-      case BufferedImage.TYPE_BYTE_GRAY:
-        pixelFormat = TJ.PF_GRAY;  break;
-      case BufferedImage.TYPE_INT_BGR:
-        if (byteOrder == ByteOrder.BIG_ENDIAN)
-          pixelFormat = TJ.PF_XBGR;
-        else
-          pixelFormat = TJ.PF_RGBX;
-        intPixels = true;  break;
-      case BufferedImage.TYPE_INT_RGB:
-        if (byteOrder == ByteOrder.BIG_ENDIAN)
-          pixelFormat = TJ.PF_XRGB;
-        else
-          pixelFormat = TJ.PF_BGRX;
-        intPixels = true;  break;
-      case BufferedImage.TYPE_INT_ARGB:
-      case BufferedImage.TYPE_INT_ARGB_PRE:
-        if (byteOrder == ByteOrder.BIG_ENDIAN)
-          pixelFormat = TJ.PF_ARGB;
-        else
-          pixelFormat = TJ.PF_BGRA;
-        intPixels = true;  break;
-      default:
-        throw new IllegalArgumentException("Unsupported BufferedImage format");
+    switch (dstImage.getType()) {
+    case BufferedImage.TYPE_3BYTE_BGR:
+      pixelFormat = TJ.PF_BGR;  break;
+    case BufferedImage.TYPE_4BYTE_ABGR:
+    case BufferedImage.TYPE_4BYTE_ABGR_PRE:
+      pixelFormat = TJ.PF_XBGR;  break;
+    case BufferedImage.TYPE_BYTE_GRAY:
+      pixelFormat = TJ.PF_GRAY;  break;
+    case BufferedImage.TYPE_INT_BGR:
+      if (byteOrder == ByteOrder.BIG_ENDIAN)
+        pixelFormat = TJ.PF_XBGR;
+      else
+        pixelFormat = TJ.PF_RGBX;
+      intPixels = true;  break;
+    case BufferedImage.TYPE_INT_RGB:
+      if (byteOrder == ByteOrder.BIG_ENDIAN)
+        pixelFormat = TJ.PF_XRGB;
+      else
+        pixelFormat = TJ.PF_BGRX;
+      intPixels = true;  break;
+    case BufferedImage.TYPE_INT_ARGB:
+    case BufferedImage.TYPE_INT_ARGB_PRE:
+      if (byteOrder == ByteOrder.BIG_ENDIAN)
+        pixelFormat = TJ.PF_ARGB;
+      else
+        pixelFormat = TJ.PF_BGRA;
+      intPixels = true;  break;
+    default:
+      throw new IllegalArgumentException("Unsupported BufferedImage format");
     }
     WritableRaster wr = dstImage.getRaster();
     if (intPixels) {
@@ -842,11 +863,12 @@
       destroy();
   }
 
+  @SuppressWarnings("checkstyle:DesignForExtension")
   @Override
   protected void finalize() throws Throwable {
     try {
       close();
-    } catch(TJException e) {
+    } catch (TJException e) {
     } finally {
       super.finalize();
     }
diff --git a/java/org/libjpegturbo/turbojpeg/TJException.java b/java/org/libjpegturbo/turbojpeg/TJException.java
index 59c2041..d03a256 100644
--- a/java/org/libjpegturbo/turbojpeg/TJException.java
+++ b/java/org/libjpegturbo/turbojpeg/TJException.java
@@ -1,5 +1,6 @@
 /*
  * Copyright (C)2015 Viktor Szathmáry.  All Rights Reserved.
+ * Copyright (C)2017-2018 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:
@@ -30,24 +31,48 @@
 
 import java.io.IOException;
 
+@SuppressWarnings("checkstyle:JavadocType")
 public class TJException extends IOException {
 
   private static final long serialVersionUID = 1L;
 
+  @SuppressWarnings("checkstyle:JavadocMethod")
   public TJException() {
     super();
   }
 
+  @SuppressWarnings("checkstyle:JavadocMethod")
   public TJException(String message, Throwable cause) {
     super(message, cause);
   }
 
+  @SuppressWarnings("checkstyle:JavadocMethod")
   public TJException(String message) {
     super(message);
   }
 
+  @SuppressWarnings("checkstyle:JavadocMethod")
+  public TJException(String message, int code) {
+    super(message);
+    if (errorCode >= 0 && errorCode < TJ.NUMERR)
+      errorCode = code;
+  }
+
+  @SuppressWarnings("checkstyle:JavadocMethod")
   public TJException(Throwable cause) {
     super(cause);
   }
 
+  /**
+   * Returns a code (one of {@link TJ TJ.ERR_*}) indicating the severity of the
+   * last error.
+   *
+   * @return a code (one of {@link TJ TJ.ERR_*}) indicating the severity of the
+   * last error.
+   */
+  public int getErrorCode() {
+    return errorCode;
+  }
+
+  private int errorCode = TJ.ERR_FATAL;
 }
diff --git a/java/org/libjpegturbo/turbojpeg/TJLoader.java.tmpl b/java/org/libjpegturbo/turbojpeg/TJLoader-unix.java.in
similarity index 77%
rename from java/org/libjpegturbo/turbojpeg/TJLoader.java.tmpl
rename to java/org/libjpegturbo/turbojpeg/TJLoader-unix.java.in
index 5ef3118..65884e8 100644
--- a/java/org/libjpegturbo/turbojpeg/TJLoader.java.tmpl
+++ b/java/org/libjpegturbo/turbojpeg/TJLoader-unix.java.in
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011-2013 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011-2013, 2016 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:
@@ -36,19 +36,19 @@
       String os = System.getProperty("os.name").toLowerCase();
       if (os.indexOf("mac") >= 0) {
         try {
-          System.load("%{__libdir}/libturbojpeg.jnilib");
+          System.load("@CMAKE_INSTALL_FULL_LIBDIR@/libturbojpeg.jnilib");
         } catch (java.lang.UnsatisfiedLinkError e2) {
           System.load("/usr/lib/libturbojpeg.jnilib");
         }
       } else {
         try {
-          System.load("%{__libdir}/libturbojpeg.so");
+          System.load("@CMAKE_INSTALL_FULL_LIBDIR@/libturbojpeg.so");
         } catch (java.lang.UnsatisfiedLinkError e3) {
-          String libdir = "%{__libdir}";
-          if (libdir.equals("/opt/libjpeg-turbo/lib64")) {
-            System.load("/opt/libjpeg-turbo/lib32/libturbojpeg.so");
-          } else if (libdir.equals("/opt/libjpeg-turbo/lib32")) {
-            System.load("/opt/libjpeg-turbo/lib64/libturbojpeg.so");
+          String libdir = "@CMAKE_INSTALL_FULL_LIBDIR@";
+          if (libdir.equals("@CMAKE_INSTALL_DEFAULT_PREFIX@/lib64")) {
+            System.load("@CMAKE_INSTALL_DEFAULT_PREFIX@/lib32/libturbojpeg.so");
+          } else if (libdir.equals("@CMAKE_INSTALL_DEFAULT_PREFIX@/lib32")) {
+            System.load("@CMAKE_INSTALL_DEFAULT_PREFIX@/lib64/libturbojpeg.so");
           } else {
             throw e3;
           }
diff --git a/java/org/libjpegturbo/turbojpeg/TJLoader.java.in b/java/org/libjpegturbo/turbojpeg/TJLoader-win.java.in
similarity index 100%
rename from java/org/libjpegturbo/turbojpeg/TJLoader.java.in
rename to java/org/libjpegturbo/turbojpeg/TJLoader-win.java.in
diff --git a/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java b/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java
index ddb1d75..ccf9179 100644
--- a/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java
+++ b/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011, 2018 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
@@ -34,6 +34,13 @@
  */
 public class TJScalingFactor {
 
+  /**
+   * Create a TurboJPEG scaling factor instance.
+   *
+   * @param num numerator
+   * @param denom denominator
+   */
+  @SuppressWarnings("checkstyle:HiddenField")
   public TJScalingFactor(int num, int denom) {
     if (num < 1 || denom < 1)
       throw new IllegalArgumentException("Numerator and denominator must be >= 1");
@@ -64,6 +71,8 @@
    * performs the integer equivalent of
    * <code>ceil(dimension * scalingFactor)</code>.
    *
+   * @param dimension width or height to multiply by this scaling factor
+   *
    * @return the scaled value of <code>dimension</code>.
    */
   public int getScaled(int dimension) {
@@ -74,6 +83,8 @@
    * Returns true or false, depending on whether this instance and
    * <code>other</code> have the same numerator and denominator.
    *
+   * @param other the scaling factor against which to compare this one
+   *
    * @return true or false, depending on whether this instance and
    * <code>other</code> have the same numerator and denominator.
    */
diff --git a/java/org/libjpegturbo/turbojpeg/TJTransform.java b/java/org/libjpegturbo/turbojpeg/TJTransform.java
index 7381f36..41c4b45 100644
--- a/java/org/libjpegturbo/turbojpeg/TJTransform.java
+++ b/java/org/libjpegturbo/turbojpeg/TJTransform.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C)2011, 2013 D. R. Commander.  All Rights Reserved.
+ * Copyright (C)2011, 2013, 2018 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:
@@ -103,21 +103,21 @@
    * partial MCU blocks that cannot be transformed will be left in place, which
    * will create odd-looking strips on the right or bottom edge of the image.
    */
-  public static final int OPT_PERFECT  = 1;
+  public static final int OPT_PERFECT     = 1;
   /**
    * This option will discard any partial MCU blocks that cannot be
    * transformed.
    */
-  public static final int OPT_TRIM     = 2;
+  public static final int OPT_TRIM        = 2;
   /**
    * This option will enable lossless cropping.
    */
-  public static final int OPT_CROP     = 4;
+  public static final int OPT_CROP        = 4;
   /**
    * This option will discard the color data in the input image and produce
    * a grayscale output image.
    */
-  public static final int OPT_GRAY     = 8;
+  public static final int OPT_GRAY        = 8;
   /**
    * This option will prevent {@link TJTransformer#transform
    * TJTransformer.transform()} from outputting a JPEG image for this
@@ -125,7 +125,21 @@
    * filter to capture the transformed DCT coefficients without transcoding
    * them.
    */
-  public static final int OPT_NOOUTPUT = 16;
+  public static final int OPT_NOOUTPUT    = 16;
+  /**
+   * This option will enable progressive entropy coding in the output image
+   * generated by this particular transform.  Progressive entropy coding will
+   * generally improve compression relative to baseline entropy coding (the
+   * default), but it will reduce compression and decompression performance
+   * considerably.
+   */
+  public static final int OPT_PROGRESSIVE = 32;
+  /**
+   * This option will prevent {@link TJTransformer#transform
+   * TJTransformer.transform()} from copying any extra markers (including EXIF
+   * and ICC profile data) from the source image to the output image.
+   */
+  public static final int OPT_COPYNONE    = 64;
 
 
   /**
@@ -159,6 +173,7 @@
    * @param cf an instance of an object that implements the {@link
    * TJCustomFilter} interface, or null if no custom filter is needed
    */
+  @SuppressWarnings("checkstyle:HiddenField")
   public TJTransform(int x, int y, int w, int h, int op, int options,
                      TJCustomFilter cf) {
     super(x, y, w, h);
@@ -183,6 +198,7 @@
    * @param cf an instance of an object that implements the {@link
    * TJCustomFilter} interface, or null if no custom filter is needed
    */
+  @SuppressWarnings("checkstyle:HiddenField")
   public TJTransform(Rectangle r, int op, int options,
                      TJCustomFilter cf) {
     super(r);
@@ -194,15 +210,18 @@
   /**
    * Transform operation (one of <code>OP_*</code>)
    */
+  @SuppressWarnings("checkstyle:VisibilityModifier")
   public int op = 0;
 
   /**
    * Transform options (bitwise OR of one or more of <code>OPT_*</code>)
    */
+  @SuppressWarnings("checkstyle:VisibilityModifier")
   public int options = 0;
 
   /**
    * Custom filter instance
    */
+  @SuppressWarnings("checkstyle:VisibilityModifier")
   public TJCustomFilter cf = null;
 }
diff --git a/java/org/libjpegturbo/turbojpeg/TJTransformer.java b/java/org/libjpegturbo/turbojpeg/TJTransformer.java
index d76647f..d7a56f3 100644
--- a/java/org/libjpegturbo/turbojpeg/TJTransformer.java
+++ b/java/org/libjpegturbo/turbojpeg/TJTransformer.java
@@ -111,11 +111,11 @@
    * which specifies the transform parameters and/or cropping region for the
    * corresponding transformed output image
    *
-   * @return an array of {@link TJDecompressor} instances, each of
-   * which has a transformed JPEG image associated with it.
-   *
    * @param flags the bitwise OR of one or more of
    * {@link TJ#FLAG_BOTTOMUP TJ.FLAG_*}
+   *
+   * @return an array of {@link TJDecompressor} instances, each of
+   * which has a transformed JPEG image associated with it.
    */
   public TJDecompressor[] transform(TJTransform[] transforms, int flags)
                                     throws TJException {
diff --git a/java/org/libjpegturbo/turbojpeg/YUVImage.java b/java/org/libjpegturbo/turbojpeg/YUVImage.java
index d123e37..4da9843 100644
--- a/java/org/libjpegturbo/turbojpeg/YUVImage.java
+++ b/java/org/libjpegturbo/turbojpeg/YUVImage.java
@@ -208,12 +208,12 @@
    * @param subsamp the level of chrominance subsampling used in the YUV
    * image (one of {@link TJ#SAMP_444 TJ.SAMP_*})
    */
-  public void setBuf(byte[][] planes, int[] offsets, int width, int strides[],
+  public void setBuf(byte[][] planes, int[] offsets, int width, int[] strides,
                      int height, int subsamp) {
     setBuf(planes, offsets, width, strides, height, subsamp, false);
   }
 
-  private void setBuf(byte[][] planes, int[] offsets, int width, int strides[],
+  private void setBuf(byte[][] planes, int[] offsets, int width, int[] strides,
                      int height, int subsamp, boolean alloc) {
     if ((planes == null && !alloc) || width < 1 || height < 1 || subsamp < 0 ||
         subsamp >= TJ.NUMSAMP)
@@ -247,9 +247,11 @@
       if (planes[i] == null || offsets[i] < 0)
         throw new IllegalArgumentException("Invalid argument in YUVImage::setBuf()");
       if (strides[i] < 0 && offsets[i] - planeSize + pw < 0)
-        throw new IllegalArgumentException("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 IllegalArgumentException("Image plane " + i + " is not large enough");
+        throw new IllegalArgumentException("Image plane " + i +
+                                           " is not large enough");
     }
 
     yuvPlanes = planes;
@@ -294,9 +296,9 @@
     int[] offsets = new int[nc];
 
     planes[0] = yuvImage;
-    strides[0] = PAD(TJ.planeWidth(0, width, subsamp), pad);
+    strides[0] = pad(TJ.planeWidth(0, width, subsamp), pad);
     if (subsamp != TJ.SAMP_GRAY) {
-      strides[1] = strides[2] = PAD(TJ.planeWidth(1, width, subsamp), pad);
+      strides[1] = strides[2] = pad(TJ.planeWidth(1, width, subsamp), pad);
       planes[1] = planes[2] = yuvImage;
       offsets[1] = offsets[0] +
         strides[0] * TJ.planeHeight(0, height, subsamp);
@@ -428,7 +430,7 @@
     return TJ.bufSizeYUV(yuvWidth, yuvPad, yuvHeight, yuvSubsamp);
   }
 
-  private static final int PAD(int v, int p) {
+  private static int pad(int v, int p) {
     return (v + p - 1) & (~(p - 1));
   }