Attempt to make build work with Visual Studio 2010 (still doesn't work if SIMD or Java are enabled-- see bug tracker)


git-svn-id: svn+ssh://svn.code.sf.net/p/libjpeg-turbo/code/trunk@570 632fc199-4ca6-4c93-a231-07263d6284db
diff --git a/BUILDING.txt b/BUILDING.txt
index 50e2fb7..416d8c1 100644
--- a/BUILDING.txt
+++ b/BUILDING.txt
@@ -30,6 +30,14 @@
 
 -- GCC v4.1 or later recommended for best performance
 
+-- If building the TurboJPEG/OSS Java wrapper, JDK or OpenJDK 1.5 or later is
+   required.  Some systems, such as OS X 10.4, Solaris 10 and later, and Red
+   Hat Enterprise Linux 5 and later, have this pre-installed.  On OS X 10.5 and
+   later, it will be necessary to install the Java Developer Package, which can
+   be downloaded from http://connect.apple.com.  For systems that do not have a
+   JDK installed, you can obtain the Oracle Java Development Kit from
+   http://www.java.com.
+
 
 ==================
 Out-of-Tree Builds
@@ -117,6 +125,22 @@
 disable encoding or decoding (respectively.)
 
 
+TurboJPEG/OSS Java Wrapper
+--------------------------
+Add --with-java to the configure command line to incorporate an optional Java
+Native Interface wrapper into the TurboJPEG/OSS dynamic library and build the
+Java front-end classes to support it.  This allows the TurboJPEG/OSS dynamic
+library to be used directly from Java applications.  See java/README for more
+details.
+
+You can set the JAVAC, JAR, and JAVA configure variables to specify
+alternate commands for javac, jar, and java (respectively.)  You can also
+set the JAVACFLAGS configure variable to specify arguments that should be
+passed to the Java compiler when building the front-end classes, and JNI_CFLAGS
+to specify arguments that should be passed to the C compiler when building the
+JNI wrapper.  Run 'configure --help' for more details.
+
+
 ========================
 Installing libjpeg-turbo
 ========================
@@ -295,6 +319,9 @@
 -- NASM (http://www.nasm.us/) 0.98 or later (NASM 2.05 or later is required for
    a 64-bit build)
 
+-- If building the TurboJPEG/OSS Java wrapper, JDK 1.5 or later is required.
+   This can be downloaded from http://www.java.com.
+
 
 ==================
 Out-of-Tree Builds
@@ -434,6 +461,22 @@
 disable encoding or decoding (respectively.)
 
 
+TurboJPEG/OSS Java Wrapper
+--------------------------
+Add "-DWITH_JAVA=1" to the cmake command line to incorporate an optional Java
+Native Interface wrapper into the TurboJPEG/OSS dynamic library and build the
+Java front-end classes to support it.  This allows the TurboJPEG/OSS dynamic
+library to be used directly from Java applications.  See java/README for more
+details.
+
+If you are using CMake 2.8, you can set the Java_JAVAC_EXECUTABLE,
+Java_JAVA_EXECUTABLE, and Java_JAR_EXECUTABLE CMake variables to specify
+alternate commands or locations for javac, jar, and java (respectively.)  If
+you are using CMake 2.6, set JAVA_COMPILE, JAVA_RUNTIME, and JAVA_ARCHIVE
+instead.  You can also set the JAVACFLAGS CMake variable to specify arguments
+that should be passed to the Java compiler when building the front-end classes.
+
+
 ========================
 Installing libjpeg-turbo
 ========================
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f5631bf..c8850a6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@
 cmake_minimum_required(VERSION 2.6)
 
 project(libjpeg-turbo C)
-set(VERSION 1.1.1)
+set(VERSION 1.1.90)
 
 if(MINGW OR CYGWIN)
   execute_process(COMMAND "date" "+%Y%m%d" OUTPUT_VARIABLE BUILD)
@@ -18,6 +18,8 @@
   message(FATAL_ERROR "Platform not supported by this build system.  Use autotools instead.")
 endif()
 
+# This does nothing except when using MinGW.  CMAKE_BUILD_TYPE has no meaning
+# in Visual Studio, and it always defaults to Debug when using NMake.
 if(NOT CMAKE_BUILD_TYPE)
   set(CMAKE_BUILD_TYPE Release)
 endif()
@@ -25,7 +27,7 @@
 message(STATUS "CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
 
 # This only works if building from the command line.  There is currently no way
-# to set a variable's value based on the build type when using the MSVC IDE.
+# to set a variable's value based on the build type when using Visual Studio.
 if(CMAKE_BUILD_TYPE STREQUAL "Debug")
   set(BUILD "${BUILD}d")
 endif()
@@ -58,6 +60,16 @@
   message(STATUS "Arithmetic decoding support disabled")
 endif()
 
+if(NOT DEFINED WITH_JAVA)
+  set(WITH_JAVA 0)
+endif()
+
+if(WITH_JAVA)
+  message(STATUS "TurboJPEG/OSS Java wrapper enabled")
+else()
+  message(STATUS "TurboJPEG/OSS Java wrapper disabled")
+endif()
+
 set(JPEG_LIB_VERSION 62)
 set(DLL_VERSION ${JPEG_LIB_VERSION})
 set(FULLVERSION ${DLL_VERSION}.0.0)
@@ -105,6 +117,14 @@
 
 include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR})
 
+if(WITH_JAVA)
+  find_package(Java)
+  find_package(JNI)
+  if(DEFINED JAVACFLAGS)
+    message(STATUS "Java compiler flags = ${JAVACFLAGS}")
+  endif()
+endif()
+
 
 #
 # Targets
@@ -145,6 +165,10 @@
   message(STATUS "Not using SIMD acceleration")
 endif()
 
+if(WITH_JAVA)
+  add_subdirectory(java)
+endif()
+
 add_subdirectory(sharedlib)
 
 add_library(jpeg-static STATIC ${JPEG_SOURCES} ${SIMD_OBJS})
@@ -155,13 +179,22 @@
   add_dependencies(jpeg-static simd)
 endif()
 
-add_library(turbojpeg SHARED turbojpegl.c)
+set(TURBOJPEG_SOURCES turbojpegl.c transupp.c)
+if(WITH_JAVA)
+  set(TURBOJPEG_SOURCES ${TURBOJPEG_SOURCES} turbojpeg-jni.c)
+  include_directories(${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
+endif()
+
+add_library(turbojpeg SHARED ${TURBOJPEG_SOURCES})
 set_target_properties(turbojpeg PROPERTIES DEFINE_SYMBOL DLLDEFINE)
+if(MINGW)
+  set_target_properties(turbojpeg PROPERTIES LINK_FLAGS -Wl,--kill-at)
+endif()
 target_link_libraries(turbojpeg jpeg-static)
 set_target_properties(turbojpeg PROPERTIES LINK_INTERFACE_LIBRARIES "")
 
 add_library(turbojpeg-static STATIC ${JPEG_SOURCES} ${SIMD_OBJS}
-  turbojpegl.c)
+  turbojpegl.c transupp.c)
 if(NOT MSVC)
   set_target_properties(turbojpeg-static PROPERTIES OUTPUT_NAME turbojpeg)
 endif()
@@ -205,7 +238,19 @@
 # Tests
 #
 
+if(MSVC_IDE)
+  set(OBJDIR "\${CTEST_CONFIGURATION_TYPE}/")
+else()
+  set(OBJDIR "")
+endif()
+
 enable_testing()
+if(WITH_JAVA)
+add_test(TJUnitTest ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest)
+add_test(TJUnitTest-yuv ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -yuv)
+add_test(TJUnitTest-bi ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -bi)
+add_test(TJUnitTest-bi-yuv ${JAVA_RUNTIME} -cp java/${OBJDIR}turbojpeg.jar -Djava.library.path=${CMAKE_CURRENT_BINARY_DIR}/${OBJDIR} TJUnitTest -bi -yuv)
+endif()
 add_test(jpegut jpegut)
 add_test(jpegut-yuv jpegut -yuv)
 add_test(cjpeg-int sharedlib/cjpeg -dct int -outfile testoutint.jpg ${CMAKE_SOURCE_DIR}/testorig.ppm)
@@ -220,6 +265,8 @@
 else()
 add_test(cjpeg-float-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimgflt-nosimd.jpg testoutflt.jpg)
 endif()
+add_test(cjpeg-int-gray sharedlib/cjpeg -dct int -grayscale -outfile testoutgray.jpg ${CMAKE_SOURCE_DIR}/testorig.ppm)
+add_test(cjpeg-int-gray-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimggray.jpg testoutgray.jpg)
 add_test(djpeg-int sharedlib/djpeg -dct int -fast -ppm -outfile testoutint.ppm ${CMAKE_SOURCE_DIR}/testorig.jpg)
 add_test(djpeg-int-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimgint.ppm testoutint.ppm)
 add_test(djpeg-fast sharedlib/djpeg -dct fast -ppm -outfile testoutfst.ppm ${CMAKE_SOURCE_DIR}/testorig.jpg)
@@ -265,6 +312,8 @@
 else()
 add_test(cjpeg-static-float-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimgflt-nosimd.jpg testoutflt.jpg)
 endif()
+add_test(cjpeg-static-int-gray cjpeg-static -dct int -grayscale -outfile testoutgray.jpg ${CMAKE_SOURCE_DIR}/testorig.ppm)
+add_test(cjpeg-static-int-gray-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimggray.jpg testoutgray.jpg)
 add_test(djpeg-static-int djpeg-static -dct int -fast -ppm -outfile testoutint.ppm ${CMAKE_SOURCE_DIR}/testorig.jpg)
 add_test(djpeg-static-int-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimgint.ppm testoutint.ppm)
 add_test(djpeg-static-fast djpeg-static -dct fast -ppm -outfile testoutfst.ppm ${CMAKE_SOURCE_DIR}/testorig.jpg)
@@ -296,6 +345,9 @@
 add_test(jpegtran-static-crop jpegtran-static -crop 120x90+20+50 -transpose -perfect -outfile testoutcrop.jpg ${CMAKE_SOURCE_DIR}/testorig.jpg)
 add_test(jpegtran-static-crop-cmp ${CMAKE_COMMAND} -E compare_files ${CMAKE_SOURCE_DIR}/testimgcrop.jpg testoutcrop.jpg)
 
+add_custom_target(testclean COMMAND ${CMAKE_COMMAND} -P
+  ${CMAKE_SOURCE_DIR}/cmakescripts/testclean.cmake)
+
 
 #
 # Installer
@@ -319,6 +371,10 @@
   set(INST_DEFS ${INST_DEFS} -DWIN64)
 endif()
 
+if(WITH_JAVA)
+  set(INST_DEFS ${INST_DEFS} -DJAVA)
+endif()
+
 if(MSVC_IDE)
   set(INST_DEFS ${INST_DEFS} "-DBUILDDIR=${CMAKE_CFG_INTDIR}\\")
 else()
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 22d66d9..044a99f 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,39 @@
+1.1.90 (1.2 beta1)
+==================
+
+[1] Added a JNI wrapper for TurboJPEG/OSS.  See java/README for more details.
+
+[2] TurboJPEG/OSS can now scale down images during decompression.
+
+[3] Added SIMD routines for RGB-to-grayscale color conversion, which
+significantly improves the performance of grayscale JPEG compression from an
+RGB source image.
+
+[4] Improved performance for non-x86 machines.
+
+[5] Added a function to the TurboJPEG API which performs lossless transforms.
+This function uses the same back end as jpegtran, but it performs transcoding
+entirely in memory and allows multiple transforms and/or crop operations to be
+batched together, so the source coefficients only need to be read once.  This
+is useful when generating image tiles from a single source JPEG.
+
+[6] Modified jpgtest to benchmark the new scaled decompression and lossless
+transform features in TurboJPEG/OSS.
+
+[7] Added support for 4:4:0 (transposed 4:2:2) subsampling in TurboJPEG, which
+was necessary in order for it to read 4:2:2 JPEG files that had been losslessly
+transposed or rotated 90 degrees.
+
+[8] Fixed a regression bug in the NSIS script that caused the Windows installer
+build to fail when using the Visual Studio IDE.
+
+[9] Fixed a bug in jpeg_read_coefficients() whereby it would not initialize
+cinfo->image_width and cinfo->image_height if libjpeg v7 or v8 emulation was
+enabled.  This specifically caused the jpegoptim program to fail if it was
+linked against a version of libjpeg-turbo that was built with libjpeg v7 or v8
+emulation.
+
+
 1.1.1
 =====
 
@@ -16,15 +52,6 @@
 libjpeg-turbo with older versions of MinGW64, you will now have to add
 -fno-leading-underscore to the CFLAGS.
 
-[4] Fixed a regression bug in the NSIS script that caused the Windows installer
-build to fail when using the Visual Studio IDE.
-
-[5] Fixed a bug in jpeg_read_coefficients() whereby it would not initialize
-cinfo->image_width and cinfo->image_height if libjpeg v7 or v8 emulation was
-enabled.  This specifically caused the jpegoptim program to fail if it was
-linked against a version of libjpeg-turbo that was built with libjpeg v7 or v8
-emulation.
-
 
 1.1.0
 =====
@@ -46,7 +73,7 @@
 [3] Ported jpgtest.cxx to pure C to avoid the need for a C++ compiler.
 
 [4] Fixed visual artifacts in grayscale JPEG compression caused by a typo in
-the RGB-to-luminance lookup tables.
+the RGB-to-chrominance lookup tables.
 
 [5] The Windows distribution packages now include the libjpeg run-time programs
 (cjpeg, etc.)
diff --git a/Makefile.am b/Makefile.am
index 005f040..281159e 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -35,18 +35,34 @@
 endif
 
 libturbojpeg_la_SOURCES = $(libjpeg_la_SOURCES) turbojpegl.c turbojpeg.h \
-	turbojpeg-mapfile
+	transupp.c transupp.h
+
+SUBDIRS = java
+
+if WITH_JAVA
+
+libturbojpeg_la_SOURCES += turbojpeg-jni.c
+libturbojpeg_la_CFLAGS = ${JNI_CFLAGS}
+TJMAPFILE = turbojpeg-mapfile.jni
+
+else
+
+TJMAPFILE = turbojpeg-mapfile
+
+endif
+
+libturbojpeg_la_SOURCES += $(TJMAPFILE)
 
 if VERSION_SCRIPT
 
-libturbojpeg_la_LDFLAGS += $(VERSION_SCRIPT_FLAG)$(srcdir)/turbojpeg-mapfile
+libturbojpeg_la_LDFLAGS += $(VERSION_SCRIPT_FLAG)$(srcdir)/$(TJMAPFILE)
 libjpeg_la_LDFLAGS += $(VERSION_SCRIPT_FLAG)libjpeg.map
 
 endif
 
 if WITH_SIMD
 
-SUBDIRS = simd
+SUBDIRS += simd
 libjpeg_la_LIBADD = simd/libsimd.la
 libturbojpeg_la_LIBADD = simd/libsimd.la
 
@@ -108,7 +124,7 @@
 TESTFILES= testorig.jpg testorig.ppm testimg.bmp testimgflt.jpg \
 	testimgfst.jpg testimgint.jpg testimgp.jpg testimgflt.ppm testimgfst.ppm \
 	testimgint.ppm testimgflt-nosimd.jpg testimgcrop.jpg testimgari.jpg \
-	testimgari.ppm testimgfst100.jpg
+	testimgari.ppm testimgfst100.jpg testimggray.jpg
 
 EXTRA_DIST = win release $(DOCS) $(TESTFILES) CMakeLists.txt \
 	sharedlib/CMakeLists.txt cmakescripts libjpeg.map.in
@@ -118,6 +134,12 @@
 
 
 test: testclean all
+if WITH_JAVA
+	$(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest
+	$(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -bi
+	$(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv
+	$(JAVA) -cp java/turbojpeg.jar -Djava.library.path=.libs TJUnitTest -yuv -bi
+endif
 	./jpegut
 	./jpegut -yuv
 	./cjpeg -dct int -outfile testoutint.jpg $(srcdir)/testorig.ppm
@@ -132,6 +154,8 @@
 else
 	cmp $(srcdir)/testimgflt-nosimd.jpg testoutflt.jpg
 endif
+	./cjpeg -dct int -grayscale -outfile testoutgray.jpg $(srcdir)/testorig.ppm
+	cmp $(srcdir)/testimggray.jpg testoutgray.jpg
 	./djpeg -dct int -fast -ppm -outfile testoutint.ppm $(srcdir)/testorig.jpg
 	cmp $(srcdir)/testimgint.ppm testoutint.ppm
 	./djpeg -dct fast -ppm -outfile testoutfst.ppm $(srcdir)/testorig.jpg
@@ -166,22 +190,31 @@
 
 testclean:
 	rm -f testout*
-	rm -f *_GRAYQ[0-9]*.bmp
-	rm -f *_GRAYQ[0-9]*.ppm
-	rm -f *_GRAYQ[0-9]*.jpg
+	rm -f *_GRAY_*.bmp
+	rm -f *_GRAY_*.png
+	rm -f *_GRAY_*.ppm
+	rm -f *_GRAY_*.jpg
 	rm -f *_GRAY.yuv
-	rm -f *_420Q[0-9]*.bmp
-	rm -f *_420Q[0-9]*.ppm
-	rm -f *_420Q[0-9]*.jpg
+	rm -f *_420_*.bmp
+	rm -f *_420_*.png
+	rm -f *_420_*.ppm
+	rm -f *_420_*.jpg
 	rm -f *_420.yuv
-	rm -f *_422Q[0-9]*.bmp
-	rm -f *_422Q[0-9]*.ppm
-	rm -f *_422Q[0-9]*.jpg
+	rm -f *_422_*.bmp
+	rm -f *_422_*.png
+	rm -f *_422_*.ppm
+	rm -f *_422_*.jpg
 	rm -f *_422.yuv
-	rm -f *_444Q[0-9]*.bmp
-	rm -f *_444Q[0-9]*.ppm
-	rm -f *_444Q[0-9]*.jpg
+	rm -f *_444_*.bmp
+	rm -f *_444_*.png
+	rm -f *_444_*.ppm
+	rm -f *_444_*.jpg
 	rm -f *_444.yuv
+	rm -f *_440_*.bmp
+	rm -f *_440_*.png
+	rm -f *_440_*.ppm
+	rm -f *_440_*.jpg
+	rm -f *_440.yuv
 
 if X86_64
 
diff --git a/cmakescripts/testclean.cmake b/cmakescripts/testclean.cmake
new file mode 100644
index 0000000..e357787
--- /dev/null
+++ b/cmakescripts/testclean.cmake
@@ -0,0 +1,34 @@
+file(GLOB FILES
+  testout*
+  *_GRAY_*.bmp
+  *_GRAY_*.png
+  *_GRAY_*.ppm
+  *_GRAY_*.jpg
+  *_GRAY.yuv
+  *_420_*.bmp
+  *_420_*.png
+  *_420_*.ppm
+  *_420_*.jpg
+  *_420.yuv
+  *_422_*.bmp
+  *_422_*.png
+  *_422_*.ppm
+  *_422_*.jpg
+  *_422.yuv
+  *_444_*.bmp
+  *_444_*.png
+  *_444_*.ppm
+  *_444_*.jpg
+  *_444.yuv
+  *_440_*.bmp
+  *_440_*.png
+  *_440_*.ppm
+  *_440_*.jpg
+  *_440.yuv)
+
+if(NOT FILES STREQUAL "")
+  message(STATUS "Removing test files")
+  file(REMOVE ${FILES})
+else()
+  message(STATUS "No files to remove")
+endif()
diff --git a/configure.ac b/configure.ac
index ac548a3..5454181 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.56])
-AC_INIT([libjpeg-turbo], [1.1.1])
+AC_INIT([libjpeg-turbo], [1.1.90])
 BUILD=`date +%Y%m%d`
 
 AM_INIT_AUTOMAKE([-Wall foreign dist-bzip2])
@@ -196,6 +196,69 @@
 
 AM_CONDITIONAL([WITH_ARITH], [test "x$with_arith_dec" != "xno" -o "x$with_arith_enc" != "xno"])
 
+AC_ARG_VAR(JAVAC, [Java compiler command (default: javac)])
+if test "x$JAVAC" = "x"; then
+  JAVAC=javac
+fi
+AC_SUBST(JAVAC)
+AC_ARG_VAR(JAVACFLAGS, [Java compiler flags])
+AC_SUBST(JAVACFLAGS)
+AC_ARG_VAR(JAR, [Java archive command (default: jar)])
+if test "x$JAR" = "x"; then
+  JAR=jar
+fi
+AC_SUBST(JAR)
+AC_ARG_VAR(JAVA, [Java runtime command (default: java)])
+if test "x$JAVA" = "x"; then
+  JAVA=java
+fi
+AC_SUBST(JAVA)
+AC_ARG_VAR(JNI_CFLAGS, [C compiler flags needed to include jni.h (default: -I/System/Library/Frameworks/JavaVM.framework/Headers on OS X, '-I/usr/java/include -I/usr/java/include/solaris' on Solaris, and '-I/usr/java/default/include -I/usr/java/default/include/linux' on Linux)])
+
+AC_MSG_CHECKING([whether to build TurboJPEG/OSS Java wrapper])
+AC_ARG_WITH([java],
+    AC_HELP_STRING([--with-java],[Build Java wrapper for the TurboJPEG/OSS library]))
+
+RPM_CONFIG_ARGS=
+WITH_JAVA=0
+if test "x$with_java" = "xyes"; then
+    AC_MSG_RESULT(yes)
+
+    case $host_os in
+      darwin*)
+        DEFAULT_JNI_CFLAGS=-I/System/Library/Frameworks/JavaVM.framework/Headers
+        ;;
+      solaris*)
+        DEFAULT_JNI_CFLAGS='-I/usr/java/include -I/usr/java/include/solaris'
+        ;;
+      linux*)
+        DEFAULT_JNI_CFLAGS='-I/usr/java/default/include -I/usr/java/default/include/linux'
+        ;;
+    esac
+    if test "x$JNI_CFLAGS" = "x"; then
+        JNI_CFLAGS=$DEFAULT_JNI_CFLAGS
+    fi
+
+    SAVE_CPPFLAGS=${CPPFLAGS}
+    CPPFLAGS="${CPPFLAGS} ${JNI_CFLAGS}"
+    AC_CHECK_HEADERS([jni.h], [DUMMY=1],
+        [AC_MSG_ERROR([Could not find JNI header file])])
+    CPPFLAGS=${SAVE_CPPFLAGS}
+    AC_SUBST(JNI_CFLAGS)
+
+    RPM_CONFIG_ARGS=--with-java
+    JAVA_RPM_CONTENTS_1='%dir /opt/%{name}/classes'
+    JAVA_RPM_CONTENTS_2=/opt/%{name}/classes/turbojpeg.jar
+    WITH_JAVA=1
+else
+    AC_MSG_RESULT(no)
+fi
+AM_CONDITIONAL([WITH_JAVA], [test "x$with_java" = "xyes"])
+AC_SUBST(WITH_JAVA)
+AC_SUBST(JAVA_RPM_CONTENTS_1)
+AC_SUBST(JAVA_RPM_CONTENTS_2)
+AC_SUBST(RPM_CONFIG_ARGS)
+
 # SIMD is optional
 AC_ARG_WITH([simd],
     AC_HELP_STRING([--without-simd],[Omit accelerated SIMD routines.]))
@@ -264,4 +327,5 @@
 AC_CONFIG_FILES([pkgscripts/pkginfo:release/pkginfo.in])
 AC_CONFIG_FILES([libjpeg.map])
 AC_CONFIG_FILES([Makefile simd/Makefile])
+AC_CONFIG_FILES([java/Makefile])
 AC_OUTPUT
diff --git a/djpeg.c b/djpeg.c
index 466973f..0dd4f24 100644
--- a/djpeg.c
+++ b/djpeg.c
@@ -2,7 +2,7 @@
  * djpeg.c
  *
  * Copyright (C) 1991-1997, Thomas G. Lane.
- * Copyright (C) 2010, D. R. Commander.
+ * Copyright (C) 2010-2011, D. R. Commander.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -103,6 +103,7 @@
   fprintf(stderr, "  -colors N      Reduce image to no more than N colors\n");
   fprintf(stderr, "  -fast          Fast, low-quality processing\n");
   fprintf(stderr, "  -grayscale     Force grayscale output\n");
+  fprintf(stderr, "  -rgb           Force RGB output\n");
 #ifdef IDCT_SCALING_SUPPORTED
   fprintf(stderr, "  -scale M/N     Scale output image by fraction M/N, eg, 1/8\n");
 #endif
@@ -268,6 +269,10 @@
       /* Force monochrome output. */
       cinfo->out_color_space = JCS_GRAYSCALE;
 
+    } else if (keymatch(arg, "rgb", 2)) {
+      /* Force RGB output. */
+      cinfo->out_color_space = JCS_RGB;
+
     } else if (keymatch(arg, "map", 3)) {
       /* Quantize to a color map taken from an input file. */
       if (++argn >= argc)	/* advance to next argument */
diff --git a/java/CMakeLists.txt b/java/CMakeLists.txt
new file mode 100644
index 0000000..08795f7
--- /dev/null
+++ b/java/CMakeLists.txt
@@ -0,0 +1,53 @@
+set(JAR_FILE turbojpeg.jar)
+set(MANIFEST_FILE ${CMAKE_CURRENT_SOURCE_DIR}/MANIFEST.MF)
+
+set(JAVA_CLASSNAMES org/libjpegturbo/turbojpeg/TJ
+  org/libjpegturbo/turbojpeg/TJCompressor
+  org/libjpegturbo/turbojpeg/TJDecompressor
+  org/libjpegturbo/turbojpeg/TJScalingFactor
+  org/libjpegturbo/turbojpeg/TJTransform
+  org/libjpegturbo/turbojpeg/TJTransformer
+  TJUnitTest
+  TJExample)
+
+if(MSVC_IDE)
+  set(OBJDIR "${CMAKE_CURRENT_BINARY_DIR}/$(OutDir)")
+else()
+  set(OBJDIR ${CMAKE_CURRENT_BINARY_DIR})
+endif()
+
+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()
+
+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})
+
+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(java ALL DEPENDS ${JAR_FILE})
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${JAR_FILE} DESTINATION classes)
diff --git a/java/MANIFEST.MF b/java/MANIFEST.MF
new file mode 100644
index 0000000..723bc51
--- /dev/null
+++ b/java/MANIFEST.MF
@@ -0,0 +1,2 @@
+Manifest-Version: 1.0
+Main-Class: TJExample
diff --git a/java/Makefile.am b/java/Makefile.am
new file mode 100644
index 0000000..b749183
--- /dev/null
+++ b/java/Makefile.am
@@ -0,0 +1,62 @@
+JAVAROOT = .
+
+JAVASOURCES = org/libjpegturbo/turbojpeg/TJ.java \
+	org/libjpegturbo/turbojpeg/TJCompressor.java \
+	org/libjpegturbo/turbojpeg/TJDecompressor.java \
+	org/libjpegturbo/turbojpeg/TJLoader.java \
+	org/libjpegturbo/turbojpeg/TJScalingFactor.java \
+	org/libjpegturbo/turbojpeg/TJTransform.java \
+	org/libjpegturbo/turbojpeg/TJTransformer.java \
+	TJExample.java \
+	TJUnitTest.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
+
+dist_noinst_JAVA = ${JAVASOURCES}
+
+JAVA_CLASSES = org/libjpegturbo/turbojpeg/TJ.class \
+	org/libjpegturbo/turbojpeg/TJCompressor.class \
+	org/libjpegturbo/turbojpeg/TJDecompressor.class \
+	org/libjpegturbo/turbojpeg/TJLoader.class \
+	org/libjpegturbo/turbojpeg/TJScalingFactor.class \
+	org/libjpegturbo/turbojpeg/TJTransform.class \
+	org/libjpegturbo/turbojpeg/TJTransformer.class \
+	TJExample.class \
+	TJUnitTest.class
+
+all: all-am turbojpeg.jar
+
+turbojpeg.jar: $(JAVA_CLASSES) ${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)/$(prefix)/classes
+	$(INSTALL) -m 644 turbojpeg.jar $(DESTDIR)/$(prefix)/classes/
+
+uninstall-local:
+	rm -f $(DESTDIR)/$(prefix)/classes/turbojpeg.jar
+	if [ -d $(DESTDIR)/$(prefix)/classes ]; then rmdir $(DESTDIR)/$(prefix)/classes; fi
+
+headers: all
+	cd ${srcdir}; \
+	javah org.libjpegturbo.turbojpeg.TJ; \
+	javah org.libjpegturbo.turbojpeg.TJCompressor; \
+	javah org.libjpegturbo.turbojpeg.TJDecompressor; \
+	javah org.libjpegturbo.turbojpeg.TJTransformer
+
+docs: all
+	cd ${srcdir}; \
+	mkdir -p doc; cd doc; javadoc -classpath .. org.libjpegturbo.turbojpeg
+
+endif
+
+EXTRA_DIST = MANIFEST.MF ${JAVASOURCES} ${JNIHEADERS} doc CMakeLists.txt \
+	org/libjpegturbo/turbojpeg/TJLoader.java.in
diff --git a/java/README b/java/README
new file mode 100644
index 0000000..f586682
--- /dev/null
+++ b/java/README
@@ -0,0 +1,55 @@
+TurboJPEG/OSS Java Wrapper
+==========================
+
+TurboJPEG/OSS can optionally be built with a Java Native Interface wrapper,
+which allows the TurboJPEG/OSS dynamic library to be loaded and used directly
+from Java applications.  The Java front end for this is defined in several
+classes located under org/libjpegturbo/turbojpeg.  The source code for these
+Java classes is licensed under a BSD-style license, so the files can be
+incorporated directly into both open source and proprietary projects without
+restriction.  A Java archive (JAR) file containing these classes is also
+shipped with the "official" distribution packages of libjpeg-turbo.
+
+TJExample.java, which should also be located in the same directory as this
+README file, demonstrates how to use the TurboJPEG/OSS Java front end to
+compress and decompress JPEG images in memory.
+
+
+Performance Pitfalls
+--------------------
+
+The TurboJPEG Java front end defines several convenience methods which can
+allocate image buffers or instantiate classes to hold the result of compress,
+decompress, or transform operations.  However, if you use these methods, then
+be mindful of the amount of new data you are creating on the heap.  It may be
+necessary to manually invoke the garbage collector to prevent heap exhaustion
+or to prevent performance degradation.  Background garbage collection can kill
+performance, particularly in a multi-threaded environment (Java pauses all
+threads when the GC runs.)
+
+The Java front end always gives you the option of pre-allocating your own
+source and destination buffers, which allows you to re-use these buffers for
+compressing/decompressing multiple images.  If the image sequence you are
+compressing or decompressing consists of images of the same size, then
+pre-allocating the buffers is recommended.
+
+
+Note for OS X users
+-------------------
+
+/usr/lib, the directory under which libturbojpeg.dylib is installed on Mac
+systems, is not part of the normal Java library path.  Thus, when running a
+Java application that uses TurboJPEG/OSS on Mac systems, you will need to pass
+an argument of -Djava.library.path=/usr/lib to java.
+
+
+Note for Solaris users
+----------------------
+
+/opt/libjpeg-turbo/lib, the directory under which libturbojpeg.so is installed
+on Solaris systems, is not part of the normal Java library path.  Thus, when
+running a Java application that uses TurboJPEG/OSS on Solaris systems, you will
+need to pass an argument of -Djava.library.path=/opt/libjpeg-turbo/lib to java.
+If using a 64-bit data model, then instead pass an argument of
+-Djava.library.path=/opt/libjpeg-turbo/lib/amd64 to use the 64-bit version of
+libturbojpeg.so.
diff --git a/java/TJExample.java b/java/TJExample.java
new file mode 100644
index 0000000..a326c71
--- /dev/null
+++ b/java/TJExample.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This program demonstrates how to compress and decompress JPEG files using
+ * the TurboJPEG JNI wrapper
+ */
+
+import java.io.*;
+import java.awt.image.*;
+import javax.imageio.*;
+import javax.swing.*;
+import org.libjpegturbo.turbojpeg.*;
+
+public class TJExample {
+
+  public static final String classname = new TJExample().getClass().getName();
+
+  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");
+    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.print(" or ");
+      else if(sf.length > 2) {
+        if(i != sf.length - 1) System.out.print(", ");
+        if(i == sf.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("     case.)\n");
+    System.exit(1);
+  }
+
+  private final static String sampName[] = {
+    "4:4:4", "4:2:2", "4:2:0", "Grayscale", "4:4:0"
+  };
+
+  public static void main(String argv[]) {
+
+    BufferedImage img = null;  byte[] bmpBuf = null;
+    TJTransform xform = new TJTransform();
+
+    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;
+      boolean display = false;
+
+      if(argv.length > 1) {
+        for(int i = 1; i < argv.length; i++) {
+          if(argv[i].length() < 2) continue;
+          if(argv[i].length() > 2
+            && argv[i].substring(0, 3).equalsIgnoreCase("-sc")) {
+            int match = 0;
+            if(i < argv.length - 1) {
+              String[] scaleArg = argv[++i].split("/");
+              if(scaleArg.length == 2) {
+                TJScalingFactor tempsf =
+                  new TJScalingFactor(Integer.parseInt(scaleArg[0]),
+                    Integer.parseInt(scaleArg[1]));
+                for(int j = 0; j < sf.length; j++) {
+                  if(tempsf.equals(sf[j])) {
+                    scaleFactor = sf[j];
+                    match = 1;  break;
+                  }
+                }
+              }
+            }
+            if(match != 1) usage();
+          }
+          if(argv[i].equalsIgnoreCase("-h") || argv[i].equalsIgnoreCase("-?"))
+            usage();
+          if(argv[i].length() > 2
+            && argv[i].substring(0, 3).equalsIgnoreCase("-sa")) {
+            if(i < argv.length - 1) {
+              i++;
+              if(argv[i].substring(0, 1).equalsIgnoreCase("g"))
+                outSubsamp = TJ.SAMP_GRAY;
+              else if(argv[i].equals("444")) outSubsamp = TJ.SAMP_444;
+              else if(argv[i].equals("422")) outSubsamp = TJ.SAMP_422;
+              else if(argv[i].equals("420")) outSubsamp = TJ.SAMP_420;
+              else usage();
+            }
+            else usage();
+          }
+          if(argv[i].substring(0, 2).equalsIgnoreCase("-q")) {
+            if(i < argv.length - 1) {
+              int qual = Integer.parseInt(argv[++i]);
+              if(qual >= 1 && qual <= 100) outQual = qual;
+              else usage();
+            }
+            else usage();
+          }
+          if(argv[i].substring(0, 2).equalsIgnoreCase("-g"))
+            xform.options |= TJTransform.OPT_GRAY;
+          if(argv[i].equalsIgnoreCase("-hflip"))
+            xform.op = TJTransform.OP_HFLIP;
+          if(argv[i].equalsIgnoreCase("-vflip"))
+            xform.op = TJTransform.OP_VFLIP;
+          if(argv[i].equalsIgnoreCase("-transpose"))
+            xform.op = TJTransform.OP_TRANSPOSE;
+          if(argv[i].equalsIgnoreCase("-transverse"))
+            xform.op = TJTransform.OP_TRANSVERSE;
+          if(argv[i].equalsIgnoreCase("-rot90"))
+            xform.op = TJTransform.OP_ROT90;
+          if(argv[i].equalsIgnoreCase("-rot180"))
+            xform.op = TJTransform.OP_ROT180;
+          if(argv[i].equalsIgnoreCase("-rot270"))
+            xform.op = TJTransform.OP_ROT270;
+          if(argv[i].length() > 2
+            && argv[i].substring(0, 2).equalsIgnoreCase("-c")) {
+            if(i >= argv.length - 1) usage();
+            String[] cropArg = argv[++i].split(",");
+            if(cropArg.length != 3) usage();
+            String[] dimArg = cropArg[2].split("[xX]");
+            if(dimArg.length != 2) usage();
+            int tempx = Integer.parseInt(cropArg[0]);
+            int tempy = Integer.parseInt(cropArg[1]);
+            int tempw = Integer.parseInt(dimArg[0]);
+            int temph = Integer.parseInt(dimArg[1]);
+            if(tempx < 0 || tempy < 0 || tempw < 0 || temph < 0) usage();
+            xform.x = tempx;  xform.y = tempy;
+            xform.width = tempw;  xform.height = temph;
+            xform.options |= TJTransform.OPT_CROP;
+          }
+          if(argv[i].substring(0, 2).equalsIgnoreCase("-d"))
+            display = true;
+        }
+      }
+      String[] inFileTokens = argv[0].split("\\.");
+      if(inFileTokens.length > 1)
+        inFormat = inFileTokens[inFileTokens.length - 1];
+      String[] outFileTokens;
+      if(display) outFormat = "bmp";
+      else {
+        outFileTokens = argv[1].split("\\.");
+        if(outFileTokens.length > 1)
+          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) {
+          System.out.println("Input file contains no data");
+          System.exit(1);
+        }
+        byte[] inputBuf = new byte[inputSize];
+        fis.read(inputBuf);
+        fis.close();
+
+        TJDecompressor tjd;
+        if(xform.op != TJTransform.OP_NONE || xform.options != 0) {
+          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];
+        }
+        else tjd = new TJDecompressor(inputBuf);
+
+        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;
+
+        if(outFormat.equalsIgnoreCase("jpg")
+          && (xform.op != TJTransform.OP_NONE || xform.options != 0)
+          && scaleFactor.isOne()) {
+          file = new File(argv[1]);
+          FileOutputStream fos = new FileOutputStream(file);
+          fos.write(tjd.getJPEGBuf(), 0, tjd.getJPEGSize());
+          fos.close();
+          System.exit(0);
+        }
+
+        width = scaleFactor.getScaled(width);
+        height = scaleFactor.getScaled(height);
+
+        if(!outFormat.equalsIgnoreCase("jpg"))
+          img = tjd.decompress(width, height, BufferedImage.TYPE_INT_RGB, 0);
+        else bmpBuf = tjd.decompress(width, 0, height, TJ.PF_BGRX, 0);
+        tjd.close();
+      }
+      else {
+        img = ImageIO.read(file);
+        width = img.getWidth();
+        height = img.getHeight();
+        if(outSubsamp < 0) {
+          if(img.getType() == BufferedImage.TYPE_BYTE_GRAY)
+            outSubsamp = TJ.SAMP_GRAY;
+          else outSubsamp = TJ.SAMP_444;
+        }
+      }
+      System.gc();
+      if(!display)
+        System.out.print("Dest. Image (" + outFormat + "):  " + width + " x "
+          + height + " pixels");
+
+      if(display) {
+        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]
+          + " subsampling, quality = " + outQual);
+        TJCompressor tjc = new TJCompressor();
+        int jpegSize;
+        byte[] jpegBuf;
+
+        tjc.setSubsamp(outSubsamp);
+        tjc.setJPEGQuality(outQual);
+        if(img != null)
+          jpegBuf = tjc.compress(img, 0);
+        else {
+          tjc.setSourceImage(bmpBuf, width, 0, height, TJ.PF_BGRX);
+          jpegBuf = tjc.compress(0);
+        }
+        jpegSize = tjc.getCompressedSize();
+        tjc.close();
+
+        file = new File(argv[1]);
+        FileOutputStream fos = new FileOutputStream(file);
+        fos.write(jpegBuf, 0, jpegSize);
+        fos.close();
+      }
+      else {
+        System.out.print("\n");
+        file = new File(argv[1]);
+        ImageIO.write(img, outFormat, file);
+      }
+
+    }
+    catch(Exception e) {
+      e.printStackTrace();
+      System.exit(-1);
+    }
+  }
+
+  static TJScalingFactor sf [] = null;
+};
diff --git a/java/TJUnitTest.java b/java/TJUnitTest.java
new file mode 100644
index 0000000..1bbdad2
--- /dev/null
+++ b/java/TJUnitTest.java
@@ -0,0 +1,847 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This program tests the various code paths in the TurboJPEG JNI Wrapper
+ */
+
+import java.io.*;
+import java.util.*;
+import java.awt.image.*;
+import javax.imageio.*;
+import org.libjpegturbo.turbojpeg.*;
+
+public class TJUnitTest {
+
+  private static final String classname =
+    new TJUnitTest().getClass().getName();
+
+  private static void usage() {
+    System.out.println("\nUSAGE: java " + classname + " [options]\n");
+    System.out.println("Options:\n");
+    System.out.println("-yuv = test YUV encoding/decoding support\n");
+    System.out.println("-bi = test BufferedImage support\n");
+    System.exit(1);
+  }
+
+  private final static String subNameLong[] = {
+    "4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"
+  };
+  private final static String subName[] = {
+    "444", "422", "420", "GRAY", "440"
+  };
+
+  private final static String pixFormatStr[] = {
+    "RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB", "Grayscale"
+  };
+  private final static int biType[] = {
+    0, BufferedImage.TYPE_3BYTE_BGR, BufferedImage.TYPE_INT_BGR,
+    BufferedImage.TYPE_INT_RGB, 0, 0, BufferedImage.TYPE_BYTE_GRAY
+  };
+
+  private final static int _3byteFormats[] = {
+    TJ.PF_RGB, TJ.PF_BGR
+  };
+  private final static int _3byteFormatsBI[] = {
+    TJ.PF_BGR
+  };
+  private final static int _4byteFormats[] = {
+    TJ.PF_RGBX, TJ.PF_BGRX, TJ.PF_XBGR, TJ.PF_XRGB
+  };
+  private final static int _4byteFormatsBI[] = {
+    TJ.PF_RGBX, TJ.PF_BGRX
+  };
+  private final static int onlyGray[] = {
+    TJ.PF_GRAY
+  };
+  private final static int onlyRGB[] = {
+    TJ.PF_RGB
+  };
+
+  private final static int YUVENCODE = 1;
+  private final static int YUVDECODE = 2;
+  private static int yuv = 0;
+  private static boolean bi = false;
+
+  private static int exitStatus = 0;
+
+  private static double getTime() {
+    return (double)System.nanoTime() / 1.0e9;
+  }
+
+  private final static byte pixels[][] = {
+    {0, (byte)255, 0},
+    {(byte)255, 0, (byte)255},
+    {(byte)255, (byte)255, 0},
+    {0, 0, (byte)255},
+    {0, (byte)255, (byte)255},
+    {(byte)255, 0, 0},
+    {(byte)255, (byte)255, (byte)255},
+    {0, 0, 0},
+    {(byte)255, 0, 0}
+  };
+
+  private 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 ps = TJ.getPixelSize(pf);
+    int i, _i, j;
+
+    Arrays.fill(buf, (byte)0);
+    if(pf == TJ.PF_GRAY) {
+      for(_i = 0; _i < 16; _i++) {
+        if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+        else i = _i;
+        for(j = 0; j < w; j++) {
+          if(((_i / 8) + (j / 8)) % 2 == 0) buf[pitch * i + j] = (byte)255;
+          else buf[pitch * i + j] = 76;
+        }
+      }
+      for(_i = 16; _i < h; _i++) {
+        if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+        else i = _i;
+        for(j = 0; j < w; j++) {
+          if(((_i / 8) + (j / 8)) % 2 == 0) buf[pitch * i + j] = 0;
+          else buf[pitch * i + j] = (byte)226;
+        }
+      }
+      return;
+    }
+    for(_i = 0; _i < 16; _i++) {
+      if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+      else i = _i;
+      for(j = 0; j < w; j++) {
+        buf[pitch * i + j * ps + roffset] = (byte)255;
+        if(((_i / 8) + (j / 8)) % 2 == 0) {
+          buf[pitch * i + j * ps + goffset] = (byte)255;
+          buf[pitch * i + j * ps + boffset] = (byte)255;
+        }
+      }
+    }
+    for(_i = 16; _i < h; _i++) {
+      if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+      else i = _i;
+      for(j = 0; j < w; j++) {
+        if(((_i / 8) + (j / 8)) % 2 != 0) {
+          buf[pitch * i + j * ps + roffset] = (byte)255;
+          buf[pitch * i + j * ps + goffset] = (byte)255;
+        }
+      }
+    }
+  }
+
+  private 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 i, _i, j;
+
+    Arrays.fill(buf, 0);
+    for(_i = 0; _i < 16; _i++) {
+      if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+      else i = _i;
+      for(j = 0; j < w; j++) {
+        buf[pitch * i + j] = (255 << rshift);
+        if(((_i / 8) + (j / 8)) % 2 == 0) {
+          buf[pitch * i + j] |= (255 << gshift);
+          buf[pitch * i + j] |= (255 << bshift);
+        }
+      }
+    }
+    for(_i = 16; _i < h; _i++) {
+      if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+      else i = _i;
+      for(j = 0; j < w; j++) {
+        if(((_i / 8) + (j / 8)) % 2 != 0) {
+          buf[pitch * i + j] = (255 << rshift);
+          buf[pitch * i + j] |= (255 << gshift);
+        }
+      }
+    }
+  }
+
+  private 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) {
+      SinglePixelPackedSampleModel sm =
+        (SinglePixelPackedSampleModel)img.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+      int[] buf = db.getData();
+      initIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
+    }
+    else {
+      ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+      byte[] buf = db.getData();
+      initBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, flags);
+    }
+  }
+
+  private static void checkVal(int i, int j, int v, String vname, int cv)
+    throws Exception {
+    v = (v < 0) ? v + 256 : v;
+    if(v < cv - 1 || v > cv + 1) {
+      throw new Exception("\nComp. " + vname + " at " + i + "," + j
+        + " should be " + cv + ", not " + v + "\n");
+    }
+  }
+
+  private static void checkVal0(int i, int j, int v, String vname)
+    throws Exception {
+    v = (v < 0) ? v + 256 : v;
+    if(v > 1) {
+      throw new Exception("\nComp. " + vname + " at " + i + "," + j
+        + " should be 0, not " + v + "\n");
+    }
+  }
+
+  private static void checkVal255(int i, int j, int v, String vname)
+    throws Exception {
+    v = (v < 0) ? v + 256 : v;
+    if(v < 254) {
+      throw new Exception("\nComp. " + vname + " at " + i + "," + j
+        + " should be 255, not " + v + "\n");
+    }
+  }
+
+  private 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 ps = TJ.getPixelSize(pf);
+    int i, _i, j, retval = 1;
+    int halfway = 16 * sf.getNum() / sf.getDenom();
+    int blockSize = 8 * sf.getNum() / sf.getDenom();
+
+    try {
+      for(_i = 0; _i < halfway; _i++) {
+        if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+        else i = _i;
+        for(j = 0; j < w; j++) {
+          byte r = buf[pitch * i + j * ps + roffset];
+          byte g = buf[pitch * i + j * ps + goffset];
+          byte b = buf[pitch * i + j * ps + boffset];
+          if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+            checkVal255(_i, j, r, "R");
+            checkVal255(_i, j, g, "G");
+            checkVal255(_i, j, b, "B");
+          }
+          else {
+            if(subsamp == TJ.SAMP_GRAY) {
+              checkVal(_i, j, r, "R", 76);
+              checkVal(_i, j, g, "G", 76);
+              checkVal(_i, j, b, "B", 76);
+            }
+            else {
+              checkVal255(_i, j, r, "R");
+              checkVal0(_i, j, g, "G");
+              checkVal0(_i, j, b, "B");
+            }
+          }
+        }
+      }
+      for(_i = halfway; _i < h; _i++) {
+        if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+        else i = _i;
+        for(j = 0; j < w; j++) {
+          byte r = buf[pitch * i + j * ps + roffset];
+          byte g = buf[pitch * i + j * ps + goffset];
+          byte b = buf[pitch * i + j * ps + boffset];
+          if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+            checkVal0(_i, j, r, "R");
+            checkVal0(_i, j, g, "G");
+          }
+          else {
+            if(subsamp == TJ.SAMP_GRAY) {
+              checkVal(_i, j, r, "R", 226);
+              checkVal(_i, j, g, "G", 226);
+              checkVal(_i, j, b, "B", 226);
+            }
+            else {
+              checkVal255(_i, j, r, "R");
+              checkVal255(_i, j, g, "G");
+              checkVal0(_i, j, b, "B");							
+            }
+          }
+        }
+      }
+    }
+    catch(Exception e) {
+      System.out.println(e);
+      retval = 0;
+    }
+
+    if(retval == 0) {
+      System.out.print("\n");
+      for(i = 0; i < h; i++) {
+        for(j = 0; j < w; j++) {
+          int r = buf[pitch * i + j * ps + roffset];
+          int g = buf[pitch * i + j * ps + goffset];
+          int b = buf[pitch * i + j * ps + boffset];
+          if(r < 0) r += 256;  if(g < 0) g += 256;  if(b < 0) b += 256;
+          System.out.format("%3d/%3d/%3d ", r, g, b);
+        }
+        System.out.print("\n");
+      }
+    }
+    return retval;
+  }
+
+  private 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 i, _i, j, retval = 1;
+    int halfway = 16 * sf.getNum() / sf.getDenom();
+    int blockSize = 8 * sf.getNum() / sf.getDenom();
+
+    try {
+      for(_i = 0; _i < halfway; _i++) {
+        if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+        else i = _i;
+        for(j = 0; j < w; j++) {
+          int r = (buf[pitch * i + j] >> rshift) & 0xFF;
+          int g = (buf[pitch * i + j] >> gshift) & 0xFF;
+          int b = (buf[pitch * i + j] >> bshift) & 0xFF;
+          if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+            checkVal255(_i, j, r, "R");
+            checkVal255(_i, j, g, "G");
+            checkVal255(_i, j, b, "B");
+          }
+          else {
+            if(subsamp == TJ.SAMP_GRAY) {
+              checkVal(_i, j, r, "R", 76);
+              checkVal(_i, j, g, "G", 76);
+              checkVal(_i, j, b, "B", 76);
+            }
+            else {
+              checkVal255(_i, j, r, "R");
+              checkVal0(_i, j, g, "G");
+              checkVal0(_i, j, b, "B");
+            }
+          }
+        }
+      }
+      for(_i = halfway; _i < h; _i++) {
+        if((flags & TJ.FLAG_BOTTOMUP) != 0) i = h - _i - 1;
+        else i = _i;
+        for(j = 0; j < w; j++) {
+          int r = (buf[pitch * i + j] >> rshift) & 0xFF;
+          int g = (buf[pitch * i + j] >> gshift) & 0xFF;
+          int b = (buf[pitch * i + j] >> bshift) & 0xFF;
+          if(((_i / blockSize) + (j / blockSize)) % 2 == 0) {
+            checkVal0(_i, j, r, "R");
+            checkVal0(_i, j, g, "G");
+          }
+          else {
+            if(subsamp == TJ.SAMP_GRAY) {
+              checkVal(_i, j, r, "R", 226);
+              checkVal(_i, j, g, "G", 226);
+              checkVal(_i, j, b, "B", 226);
+            }
+            else {
+              checkVal255(_i, j, r, "R");
+              checkVal255(_i, j, g, "G");
+              checkVal0(_i, j, b, "B");
+            }
+          }
+        }
+      }
+    }
+    catch(Exception e) {
+      System.out.println(e);
+      retval = 0;
+    }
+
+    if(retval == 0) {
+      System.out.print("\n");
+      for(i = 0; i < h; i++) {
+        for(j = 0; j < w; j++) {
+          int r = (buf[pitch * i + j] >> rshift) & 0xFF;
+          int g = (buf[pitch * i + j] >> gshift) & 0xFF;
+          int b = (buf[pitch * i + j] >> bshift) & 0xFF;
+          if(r < 0) r += 256;  if(g < 0) g += 256;  if(b < 0) b += 256;
+          System.out.format("%3d/%3d/%3d ", r, g, b);
+        }
+        System.out.print("\n");
+      }
+    }
+    return retval;
+  }
+
+  private 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
+      || imgtype == BufferedImage.TYPE_INT_BGR) {
+      SinglePixelPackedSampleModel sm =
+        (SinglePixelPackedSampleModel)img.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+      int[] buf = db.getData();
+      return checkIntBuf(buf, img.getWidth(), pitch, img.getHeight(), pf,
+        subsamp, sf, flags);
+    }
+    else {
+      ComponentSampleModel sm = (ComponentSampleModel)img.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+      byte[] buf = db.getData();
+      return checkBuf(buf, img.getWidth(), pitch, img.getHeight(), pf, subsamp,
+        sf, flags);
+    }
+  }
+
+  private 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) throws Exception {
+    int i, j;
+    int hsf = TJ.getMCUWidth(subsamp)/8, vsf = TJ.getMCUHeight(subsamp)/8;
+    int pw = PAD(w, hsf), ph = PAD(h, vsf);
+    int cw = pw / hsf, ch = ph / vsf;
+    int ypitch = PAD(pw, 4), uvpitch = PAD(cw, 4);
+    int retval = 1;
+    int correctsize = ypitch * ph
+      + (subsamp == TJ.SAMP_GRAY ? 0 : uvpitch * ch * 2);
+
+    try {
+      if(size != correctsize)
+        throw new Exception("\nIncorrect size " + size + ".  Should be "
+          + correctsize);
+
+      for(i = 0; i < 16; i++) {
+        for(j = 0; j < pw; j++) {
+          byte y = buf[ypitch * i + j];
+          if(((i / 8) + (j / 8)) % 2 == 0) checkVal255(i, j, y, "Y");
+          else checkVal(i, j, y, "Y", 76);
+        }
+      }
+      for(i = 16; i < ph; i++) {
+        for(j = 0; j < pw; j++) {
+          byte y = buf[ypitch * i + j];
+          if(((i / 8) + (j / 8)) % 2 == 0) checkVal0(i, j, y, "Y");
+          else checkVal(i, j, y, "Y", 226);
+        }
+      }
+      if(subsamp != TJ.SAMP_GRAY) {
+        for(i = 0; i < 16 / vsf; i++) {
+          for(j = 0; j < cw; j++) {
+            byte u = buf[ypitch * ph + (uvpitch * i + j)],
+              v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)];
+            if(((i * vsf / 8) + (j * hsf / 8)) % 2 == 0) {
+              checkVal(i, j, u, "U", 128);  checkVal(i, j, v, "V", 128);
+            }
+            else {
+              checkVal(i, j, u, "U", 85);  checkVal255(i, j, v, "V");
+            }
+          }
+        }
+        for(i = 16 / vsf; i < ch; i++) {
+          for(j = 0; j < cw; j++) {
+            byte u = buf[ypitch * ph + (uvpitch * i + j)],
+              v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)];
+            if(((i * vsf / 8) + (j * hsf / 8)) % 2 == 0) {
+              checkVal(i, j, u, "U", 128);  checkVal(i, j, v, "V", 128);
+            }
+            else {
+              checkVal0(i, j, u, "U");  checkVal(i, j, v, "V", 149);
+            }
+          }
+        }
+      }
+    }
+    catch(Exception e) {
+      System.out.println(e);
+      retval = 0;
+    }
+
+    if(retval == 0) {
+      for(i = 0; i < ph; i++) {
+        for(j = 0; j < pw; j++) {
+          int y = buf[ypitch * i + j];
+          if(y < 0) y += 256;
+          System.out.format("%3d ", y);
+        }
+        System.out.print("\n");
+      }
+      System.out.print("\n");
+      for(i = 0; i < ch; i++) {
+        for(j = 0; j < cw; j++) {
+          int u = buf[ypitch * ph + (uvpitch * i + j)];
+          if(u < 0) u += 256;
+          System.out.format("%3d ", u);
+        }
+        System.out.print("\n");
+      }
+      System.out.print("\n");
+      for(i = 0; i < ch; i++) {
+        for(j = 0; j < cw; j++) {
+          int v = buf[ypitch * ph + uvpitch * ch + (uvpitch * i + j)];
+          if(v < 0) v += 256;
+          System.out.format("%3d ", v);
+        }
+        System.out.print("\n");
+      }
+      System.out.print("\n");
+    }
+
+    return retval;
+  }
+
+  private 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 genTestJPEG(TJCompressor tjc, byte[] jpegBuf, int w,
+    int h, int pf, String baseFilename, int subsamp, int qual,
+    int flags) throws Exception {
+    String tempstr;
+    byte[] bmpBuf = null;
+    BufferedImage img = null;
+    String pfStr;
+    double t;
+    int size = 0, ps = TJ.getPixelSize(pf);
+
+    pfStr = pixFormatStr[pf];
+
+    System.out.print(pfStr + " ");
+    if((flags & TJ.FLAG_BOTTOMUP) != 0) System.out.print("Bottom-Up");
+    else System.out.print("Top-Down ");
+    System.out.print(" -> " + subNameLong[subsamp] + " ");
+    if(yuv == YUVENCODE) System.out.print("YUV ... ");
+    else System.out.print("Q" + qual + " ... ");
+
+    if(bi) {
+      img = new BufferedImage(w, h, biType[pf]);
+      initImg(img, pf, flags);
+      tempstr = baseFilename + "_enc_" + pfStr + "_"
+        + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+        + subName[subsamp] + "_Q" + qual + ".png";
+      File file = new File(tempstr);
+      ImageIO.write(img, "png", file);
+    }
+    else {
+      bmpBuf = new byte[w * h * ps + 1];
+      initBuf(bmpBuf, w, w * ps, h, pf, flags);
+    }
+    Arrays.fill(jpegBuf, (byte)0);
+
+    t = getTime();
+    tjc.setSubsamp(subsamp);
+    tjc.setJPEGQuality(qual);
+    if(bi) {
+      if(yuv == YUVENCODE) tjc.encodeYUV(img, jpegBuf, flags);
+      else tjc.compress(img, jpegBuf, flags);
+    }
+    else {
+      tjc.setSourceImage(bmpBuf, w, 0, h, pf);
+      if(yuv == YUVENCODE) tjc.encodeYUV(jpegBuf, flags);
+      else tjc.compress(jpegBuf, flags);
+    }
+    size = tjc.getCompressedSize();
+    t = getTime() - t;
+
+    if(yuv == YUVENCODE)
+      tempstr = baseFilename + "_enc_" + pfStr + "_"
+        + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+        + subName[subsamp] + ".yuv";
+    else
+      tempstr = baseFilename + "_enc_" + pfStr + "_"
+        + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+        + subName[subsamp] + "_Q" + qual + ".jpg";
+    writeJPEG(jpegBuf, size, tempstr);
+
+    if(yuv == YUVENCODE) {
+      if(checkBufYUV(jpegBuf, size, w, h, subsamp) == 1)
+        System.out.print("Passed.");
+      else {
+        System.out.print("FAILED!");  exitStatus = -1;
+      }
+    }
+    else System.out.print("Done.");
+    System.out.format("  %.6f ms\n", t * 1000.);
+    System.out.println("  Result in " + tempstr);
+
+    return size;
+  }
+
+  private static void genTestBMP(TJDecompressor tjd, byte[] jpegBuf,
+    int jpegsize, int w, int h, int pf, String baseFilename, int subsamp,
+    int flags, TJScalingFactor sf) throws Exception {
+    String pfStr, tempstr;
+    double t;
+    int scaledWidth = sf.getScaled(w);
+    int scaledHeight = sf.getScaled(h);
+    int temp1, temp2;
+    BufferedImage img = null;
+    byte[] bmpBuf = null;
+
+    if(yuv == YUVENCODE) return;
+
+    pfStr = pixFormatStr[pf];
+    System.out.print("JPEG -> ");
+    if(yuv == YUVDECODE)
+      System.out.print("YUV " + subName[subsamp] + " ... ");
+    else {
+      System.out.print(pfStr + " ");
+      if((flags & TJ.FLAG_BOTTOMUP) != 0) System.out.print("Bottom-Up ");
+      else System.out.print("Top-Down  ");
+      if(!sf.isOne())
+        System.out.print(sf.getNum() + "/" + sf.getDenom() + " ... ");
+      else System.out.print("... ");
+    }
+
+    t = getTime();
+    tjd.setJPEGImage(jpegBuf, jpegsize);
+    if(tjd.getWidth() != w || tjd.getHeight() != h
+      || tjd.getSubsamp() != subsamp)
+      throw new Exception("Incorrect JPEG header");
+
+    temp1 = scaledWidth;
+    temp2 = scaledHeight;
+    temp1 = tjd.getScaledWidth(temp1, temp2);
+    temp2 = tjd.getScaledHeight(temp1, temp2);
+    if(temp1 != scaledWidth || temp2 != scaledHeight)
+      throw new Exception("Scaled size mismatch");
+
+    if(yuv == YUVDECODE) bmpBuf = tjd.decompressToYUV(flags);
+    else {
+      if(bi)
+        img = tjd.decompress(scaledWidth, scaledHeight, biType[pf], flags);
+      else bmpBuf = tjd.decompress(scaledWidth, 0, scaledHeight, pf, flags);
+    }
+    t = getTime() - t;
+
+    if(bi) {
+      tempstr = baseFilename + "_dec_" + pfStr + "_"
+        + (((flags & TJ.FLAG_BOTTOMUP) != 0) ? "BU" : "TD") + "_"
+        + subName[subsamp] + "_" + (double)sf.getNum() / (double)sf.getDenom()
+        + "x" + ".png";
+      File file = new File(tempstr);
+      ImageIO.write(img, "png", file);
+    }
+
+    if(yuv == YUVDECODE) {
+      if(checkBufYUV(bmpBuf, bmpBuf.length, w, h, subsamp) == 1)
+        System.out.print("Passed.");
+      else {
+        System.out.print("FAILED!");  exitStatus = -1;
+      }
+    }
+    else {
+      if((bi && checkImg(img, pf, subsamp, sf, flags) == 1)
+        || (!bi && checkBuf(bmpBuf, scaledWidth, scaledWidth
+          * TJ.getPixelSize(pf), scaledHeight, pf, subsamp, sf, flags) == 1))
+        System.out.print("Passed.");
+      else {
+        System.out.print("FAILED!");  exitStatus = -1;
+      }
+    }
+    System.out.format("  %.6f ms\n", t * 1000.);
+  }
+
+  private static void genTestBMP(TJDecompressor tjd, byte[] jpegBuf,
+    int jpegsize, int w, int h, int pf, String baseFilename, int subsamp,
+    int flags) throws Exception {
+    int i;
+    if((subsamp == TJ.SAMP_444 || subsamp == TJ.SAMP_GRAY) && yuv == 0) {
+      TJScalingFactor sf[] = TJ.getScalingFactors();
+      for(i = 0; i < sf.length; i++)
+        genTestBMP(tjd, jpegBuf, jpegsize, w, h, pf, baseFilename, subsamp,
+          flags, sf[i]);
+    }
+    else
+      genTestBMP(tjd, jpegBuf, jpegsize, w, h, pf, baseFilename, subsamp,
+        flags, new TJScalingFactor(1, 1));
+    System.out.print("\n");
+  }
+
+  private static void doTest(int w, int h, int[] formats, int subsamp,
+    String baseFilename) throws Exception {
+    TJCompressor tjc = null;
+    TJDecompressor tjd = null;
+    int size;
+    byte[] jpegBuf;
+
+    if(yuv == YUVENCODE) jpegBuf = new byte[TJ.bufSizeYUV(w, h, subsamp)];
+    else jpegBuf = new byte[TJ.bufSize(w, h)];
+
+    try {
+      tjc = new TJCompressor();
+      tjd = new TJDecompressor();  
+
+      for(int pf : formats) {
+        for(int i = 0; i < 2; i++) {
+          int flags = 0;
+          if(i == 1) {
+            if(yuv == YUVDECODE) {
+              tjc.close();  tjd.close();  return;
+            }
+            else flags |= TJ.FLAG_BOTTOMUP;
+          }
+          size = genTestJPEG(tjc, jpegBuf, w, h, pf, baseFilename, subsamp,
+            100, flags);
+          genTestBMP(tjd, jpegBuf, size, w, h, pf, baseFilename, subsamp,
+            flags);
+        }
+      }
+    }
+    catch(Exception e) {
+      if(tjc != null) tjc.close();
+      if(tjd != null) tjd.close();
+      throw e;
+    }
+    if(tjc != null) tjc.close();
+    if(tjd != null) tjd.close();
+  }
+
+  private final static int MAXLENGTH = 2048;
+
+  private static void doTest1() throws Exception {
+    int i, j, i2;
+    byte[] bmpBuf, jpegBuf;
+    TJCompressor tjc = null;
+
+    try {
+      tjc = new TJCompressor();
+      System.out.println("Buffer size regression test");
+      for(j = 1; j < 48; j++) {
+        for(i = 1; i < (j == 1 ? MAXLENGTH : 48); i++) {
+          if(i % 100 == 0)
+            System.out.format("%04d x %04d\b\b\b\b\b\b\b\b\b\b\b", i, j);
+          bmpBuf = new byte[i * j * 4];
+          jpegBuf = new byte[TJ.bufSize(i, j)];
+          Arrays.fill(bmpBuf, (byte)0);
+          for(i2 = 0; i2 < i * j; i2++) {
+            bmpBuf[i2 * 4] = pixels[i2 % 9][2];
+            bmpBuf[i2 * 4 + 1] = pixels[i2 % 9][1];
+            bmpBuf[i2 * 4 + 2] = pixels[i2 % 9][0];
+          }
+          tjc.setSourceImage(bmpBuf, i, 0, j, TJ.PF_BGRX);
+          tjc.setSubsamp(TJ.SAMP_444);
+          tjc.setJPEGQuality(100);
+          tjc.compress(jpegBuf, 0);
+
+          bmpBuf = new byte[j * i * 4];
+          jpegBuf = new byte[TJ.bufSize(j, i)];
+          for(i2 = 0; i2 < j * i; i2++) {
+            if(i2 % 2 == 0) bmpBuf[i2 * 4] =
+                bmpBuf[i2 * 4 + 1] = bmpBuf[i2 * 4 + 2] = (byte)0xFF;
+            else bmpBuf[i2 * 4] = bmpBuf[i2 * 4 + 1] = bmpBuf[i2 * 4 + 2] = 0;
+          }
+          tjc.setSourceImage(bmpBuf, j, 0, i, TJ.PF_BGRX);
+          tjc.compress(jpegBuf, 0);
+        }
+      }
+      System.out.println("Done.      ");
+    }
+    catch(Exception e) {
+      if(tjc != null) tjc.close();
+      throw e;
+    }
+    if(tjc != null) tjc.close();
+  }
+
+  public static void main(String argv[]) {
+    try {
+      String testName = "javatest";
+      boolean doyuv = false;
+      for(int i = 0; i < argv.length; i++) {
+        if(argv[i].equalsIgnoreCase("-yuv")) doyuv = true;
+        if(argv[i].substring(0, 1).equalsIgnoreCase("-h")
+          || argv[i].equalsIgnoreCase("-?"))
+          usage();
+        if(argv[i].equalsIgnoreCase("-bi")) {
+          bi = true;
+          testName = "javabitest";
+        }
+      }
+      if(doyuv) yuv = YUVENCODE;
+      doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_444, testName);
+      doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_444, testName);
+      if(doyuv) {
+        doTest(41, 35, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_422,
+          testName);
+        doTest(35, 39, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_422,
+          testName);
+        doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_420,
+          testName);
+        doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_420,
+          testName);
+        doTest(35, 39, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_440,
+          testName);
+        doTest(39, 41, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_440,
+          testName);
+      }
+      doTest(35, 39, onlyGray, TJ.SAMP_GRAY, testName);
+      doTest(39, 41, bi ? _3byteFormatsBI : _3byteFormats, TJ.SAMP_GRAY,
+        testName);
+      doTest(41, 35, bi ? _4byteFormatsBI : _4byteFormats, TJ.SAMP_GRAY,
+        testName);
+      if(!doyuv && !bi) doTest1();
+      if(doyuv && !bi) {
+        yuv = YUVDECODE;
+        doTest(48, 48, onlyRGB, TJ.SAMP_444, "javatest_yuv0");
+        doTest(35, 39, onlyRGB, TJ.SAMP_444, "javatest_yuv1");
+        doTest(48, 48, onlyRGB, TJ.SAMP_422, "javatest_yuv0");
+        doTest(39, 41, onlyRGB, TJ.SAMP_422, "javatest_yuv1");
+        doTest(48, 48, onlyRGB, TJ.SAMP_420, "javatest_yuv0");
+        doTest(41, 35, onlyRGB, TJ.SAMP_420, "javatest_yuv1");
+        doTest(48, 48, onlyRGB, TJ.SAMP_440, "javatest_yuv0");
+        doTest(35, 39, onlyRGB, TJ.SAMP_440, "javatest_yuv1");
+        doTest(48, 48, onlyRGB, TJ.SAMP_GRAY, "javatest_yuv0");
+        doTest(35, 39, onlyRGB, TJ.SAMP_GRAY, "javatest_yuv1");
+        doTest(48, 48, onlyGray, TJ.SAMP_GRAY, "javatest_yuv0");
+        doTest(39, 41, onlyGray, TJ.SAMP_GRAY, "javatest_yuv1");
+      }
+    }
+    catch(Exception e) {
+      e.printStackTrace();
+      exitStatus = -1;
+    }
+    System.exit(exitStatus);
+  }
+}
diff --git a/java/doc/allclasses-frame.html b/java/doc/allclasses-frame.html
new file mode 100644
index 0000000..038f9ad
--- /dev/null
+++ b/java/doc/allclasses-frame.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+All Classes
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+
+</HEAD>
+
+<BODY BGCOLOR="white">
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B>All Classes</B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%" SUMMARY="">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJ</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJCompressor</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJDecompressor</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJScalingFactor</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJTransform</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJTransformer</A>
+<BR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
diff --git a/java/doc/allclasses-noframe.html b/java/doc/allclasses-noframe.html
new file mode 100644
index 0000000..964f111
--- /dev/null
+++ b/java/doc/allclasses-noframe.html
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+All Classes
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+
+</HEAD>
+
+<BODY BGCOLOR="white">
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B>All Classes</B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%" SUMMARY="">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<BR>
+<A HREF="org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<BR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
diff --git a/java/doc/constant-values.html b/java/doc/constant-values.html
new file mode 100644
index 0000000..17936ea
--- /dev/null
+++ b/java/doc/constant-values.html
@@ -0,0 +1,374 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+Constant Field Values
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="Constant Field Values";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?constant-values.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="constant-values.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<CENTER>
+<H1>
+Constant Field Values</H1>
+</CENTER>
+<HR SIZE="4" NOSHADE>
+<B>Contents</B><UL>
+<LI><A HREF="#org.libjpegturbo">org.libjpegturbo.*</A>
+</UL>
+
+<A NAME="org.libjpegturbo"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left"><FONT SIZE="+2">
+org.libjpegturbo.*</FONT></TH>
+</TR>
+</TABLE>
+
+<P>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left" COLSPAN="3">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.FLAG_BOTTOMUP"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#FLAG_BOTTOMUP">FLAG_BOTTOMUP</A></CODE></TD>
+<TD ALIGN="right"><CODE>2</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.FLAG_FASTUPSAMPLE"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#FLAG_FASTUPSAMPLE">FLAG_FASTUPSAMPLE</A></CODE></TD>
+<TD ALIGN="right"><CODE>256</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.FLAG_FORCEMMX"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCEMMX">FLAG_FORCEMMX</A></CODE></TD>
+<TD ALIGN="right"><CODE>8</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.FLAG_FORCESSE"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE">FLAG_FORCESSE</A></CODE></TD>
+<TD ALIGN="right"><CODE>16</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.FLAG_FORCESSE2"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE2">FLAG_FORCESSE2</A></CODE></TD>
+<TD ALIGN="right"><CODE>32</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.FLAG_FORCESSE3"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE3">FLAG_FORCESSE3</A></CODE></TD>
+<TD ALIGN="right"><CODE>128</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.NUMPF"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</A></CODE></TD>
+<TD ALIGN="right"><CODE>7</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.NUMSAMP"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</A></CODE></TD>
+<TD ALIGN="right"><CODE>5</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_BGR"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</A></CODE></TD>
+<TD ALIGN="right"><CODE>1</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_BGRX"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</A></CODE></TD>
+<TD ALIGN="right"><CODE>3</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_GRAY"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</A></CODE></TD>
+<TD ALIGN="right"><CODE>6</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_RGB"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</A></CODE></TD>
+<TD ALIGN="right"><CODE>0</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_RGBX"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</A></CODE></TD>
+<TD ALIGN="right"><CODE>2</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_XBGR"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</A></CODE></TD>
+<TD ALIGN="right"><CODE>4</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.PF_XRGB"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</A></CODE></TD>
+<TD ALIGN="right"><CODE>5</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.SAMP_420"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</A></CODE></TD>
+<TD ALIGN="right"><CODE>2</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.SAMP_422"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</A></CODE></TD>
+<TD ALIGN="right"><CODE>1</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.SAMP_440"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</A></CODE></TD>
+<TD ALIGN="right"><CODE>4</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.SAMP_444"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</A></CODE></TD>
+<TD ALIGN="right"><CODE>0</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJ.SAMP_GRAY"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJ.html#SAMP_GRAY">SAMP_GRAY</A></CODE></TD>
+<TD ALIGN="right"><CODE>3</CODE></TD>
+</TR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left" COLSPAN="3">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.NUMOP"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#NUMOP">NUMOP</A></CODE></TD>
+<TD ALIGN="right"><CODE>8</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_HFLIP"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_HFLIP">OP_HFLIP</A></CODE></TD>
+<TD ALIGN="right"><CODE>1</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_NONE"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_NONE">OP_NONE</A></CODE></TD>
+<TD ALIGN="right"><CODE>0</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_ROT180"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT180">OP_ROT180</A></CODE></TD>
+<TD ALIGN="right"><CODE>6</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_ROT270"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT270">OP_ROT270</A></CODE></TD>
+<TD ALIGN="right"><CODE>7</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_ROT90"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT90">OP_ROT90</A></CODE></TD>
+<TD ALIGN="right"><CODE>5</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_TRANSPOSE"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_TRANSPOSE">OP_TRANSPOSE</A></CODE></TD>
+<TD ALIGN="right"><CODE>3</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_TRANSVERSE"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_TRANSVERSE">OP_TRANSVERSE</A></CODE></TD>
+<TD ALIGN="right"><CODE>4</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OP_VFLIP"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OP_VFLIP">OP_VFLIP</A></CODE></TD>
+<TD ALIGN="right"><CODE>2</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OPT_CROP"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_CROP">OPT_CROP</A></CODE></TD>
+<TD ALIGN="right"><CODE>4</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OPT_GRAY"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_GRAY">OPT_GRAY</A></CODE></TD>
+<TD ALIGN="right"><CODE>8</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OPT_PERFECT"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT">OPT_PERFECT</A></CODE></TD>
+<TD ALIGN="right"><CODE>1</CODE></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform.OPT_TRIM"><!-- --></A><TD ALIGN="right"><FONT SIZE="-1">
+<CODE>public&nbsp;static&nbsp;final&nbsp;int</CODE></FONT></TD>
+<TD ALIGN="left"><CODE><A HREF="org/libjpegturbo/turbojpeg/TJTransform.html#OPT_TRIM">OPT_TRIM</A></CODE></TD>
+<TD ALIGN="right"><CODE>2</CODE></TD>
+</TR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?constant-values.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="constant-values.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/deprecated-list.html b/java/doc/deprecated-list.html
new file mode 100644
index 0000000..ac6d82c
--- /dev/null
+++ b/java/doc/deprecated-list.html
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+Deprecated List
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="Deprecated List";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?deprecated-list.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="deprecated-list.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<CENTER>
+<H2>
+<B>Deprecated API</B></H2>
+</CENTER>
+<HR SIZE="4" NOSHADE>
+<B>Contents</B><UL>
+</UL>
+
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?deprecated-list.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="deprecated-list.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/help-doc.html b/java/doc/help-doc.html
new file mode 100644
index 0000000..27fbb7f
--- /dev/null
+++ b/java/doc/help-doc.html
@@ -0,0 +1,209 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+API Help
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="API Help";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?help-doc.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="help-doc.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<CENTER>
+<H1>
+How This API Document Is Organized</H1>
+</CENTER>
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.<H3>
+Package</H3>
+<BLOCKQUOTE>
+
+<P>
+Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:<UL>
+<LI>Interfaces (italic)<LI>Classes<LI>Enums<LI>Exceptions<LI>Errors<LI>Annotation Types</UL>
+</BLOCKQUOTE>
+<H3>
+Class/Interface</H3>
+<BLOCKQUOTE>
+
+<P>
+Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:<UL>
+<LI>Class inheritance diagram<LI>Direct Subclasses<LI>All Known Subinterfaces<LI>All Known Implementing Classes<LI>Class/interface declaration<LI>Class/interface description
+<P>
+<LI>Nested Class Summary<LI>Field Summary<LI>Constructor Summary<LI>Method Summary
+<P>
+<LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL>
+Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</BLOCKQUOTE>
+</BLOCKQUOTE>
+<H3>
+Annotation Type</H3>
+<BLOCKQUOTE>
+
+<P>
+Each annotation type has its own separate page with the following sections:<UL>
+<LI>Annotation Type declaration<LI>Annotation Type description<LI>Required Element Summary<LI>Optional Element Summary<LI>Element Detail</UL>
+</BLOCKQUOTE>
+</BLOCKQUOTE>
+<H3>
+Enum</H3>
+<BLOCKQUOTE>
+
+<P>
+Each enum has its own separate page with the following sections:<UL>
+<LI>Enum declaration<LI>Enum description<LI>Enum Constant Summary<LI>Enum Constant Detail</UL>
+</BLOCKQUOTE>
+<H3>
+Tree (Class Hierarchy)</H3>
+<BLOCKQUOTE>
+There is a <A HREF="overview-tree.html">Class Hierarchy</A> page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with <code>java.lang.Object</code>. The interfaces do not inherit from <code>java.lang.Object</code>.<UL>
+<LI>When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.<LI>When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.</UL>
+</BLOCKQUOTE>
+<H3>
+Deprecated API</H3>
+<BLOCKQUOTE>
+The <A HREF="deprecated-list.html">Deprecated API</A> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</BLOCKQUOTE>
+<H3>
+Index</H3>
+<BLOCKQUOTE>
+The <A HREF="index-all.html">Index</A> contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.</BLOCKQUOTE>
+<H3>
+Prev/Next</H3>
+These links take you to the next or previous class, interface, package, or related page.<H3>
+Frames/No Frames</H3>
+These links show and hide the HTML frames.  All pages are available with or without frames.
+<P>
+<H3>
+Serialized Form</H3>
+Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
+<P>
+<H3>
+Constant Field Values</H3>
+The <a href="constant-values.html">Constant Field Values</a> page lists the static final fields and their values.
+<P>
+<FONT SIZE="-1">
+<EM>
+This help file applies to API documentation generated using the standard doclet.</EM>
+</FONT>
+<BR>
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?help-doc.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="help-doc.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/index-all.html b/java/doc/index-all.html
new file mode 100644
index 0000000..af5f275
--- /dev/null
+++ b/java/doc/index-all.html
@@ -0,0 +1,566 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+Index
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="./stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="Index";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="./index.html?index-all.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="index-all.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="./allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="./allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<A HREF="#_B_">B</A> <A HREF="#_C_">C</A> <A HREF="#_D_">D</A> <A HREF="#_E_">E</A> <A HREF="#_F_">F</A> <A HREF="#_G_">G</A> <A HREF="#_H_">H</A> <A HREF="#_I_">I</A> <A HREF="#_J_">J</A> <A HREF="#_N_">N</A> <A HREF="#_O_">O</A> <A HREF="#_P_">P</A> <A HREF="#_S_">S</A> <A HREF="#_T_">T</A> <HR>
+<A NAME="_B_"><!-- --></A><H2>
+<B>B</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#bufSize(int, int)"><B>bufSize(int, int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Returns the maximum size of the buffer (in bytes) required to hold a JPEG
+ image with the given width and height.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#bufSizeYUV(int, int, int)"><B>bufSizeYUV(int, int, int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Returns the size of the buffer (in bytes) required to hold a YUV planar
+ image with the given width, height, and level of chrominance subsampling.
+</DL>
+<HR>
+<A NAME="_C_"><!-- --></A><H2>
+<B>C</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#close()"><B>close()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Free the native structures associated with this compressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#close()"><B>close()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Free the native structures associated with this decompressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#compress(byte[], int)"><B>compress(byte[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Compress the uncompressed source image associated with this compressor
+ instance and output a JPEG image to the given destination buffer.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#compress(int)"><B>compress(int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Compress the uncompressed source image associated with this compressor
+ instance and return a buffer containing a JPEG image.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#compress(java.awt.image.BufferedImage, byte[], int)"><B>compress(BufferedImage, byte[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Compress the uncompressed source image stored in <code>srcImage</code>
+ and output a JPEG image to the given destination buffer.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#compress(java.awt.image.BufferedImage, int)"><B>compress(BufferedImage, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Compress the uncompressed source image stored in <code>srcImage</code>
+ and return a buffer containing a JPEG image.
+</DL>
+<HR>
+<A NAME="_D_"><!-- --></A><H2>
+<B>D</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)"><B>decompress(byte[], int, int, int, int, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and output a decompressed image to the given destination buffer.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(int, int, int, int, int)"><B>decompress(int, int, int, int, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and return a buffer containing the decompressed image.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(java.awt.image.BufferedImage, int)"><B>decompress(BufferedImage, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and output a decompressed image to the given
+ <code>BufferedImage</code> instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(int, int, int, int)"><B>decompress(int, int, int, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and return a <code>BufferedImage</code> instance containing the
+ decompressed image.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(byte[], int)"><B>decompressToYUV(byte[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and output a YUV planar image to the given destination buffer.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(int)"><B>decompressToYUV(int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and return a buffer containing a YUV planar image.
+</DL>
+<HR>
+<A NAME="_E_"><!-- --></A><H2>
+<B>E</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(byte[], int)"><B>encodeYUV(byte[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Encode the uncompressed source image associated with this compressor
+ instance and output a YUV planar image to the given destination buffer.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(int)"><B>encodeYUV(int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Encode the uncompressed source image associated with this compressor
+ instance and return a buffer containing a YUV planar image.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(java.awt.image.BufferedImage, byte[], int)"><B>encodeYUV(BufferedImage, byte[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Encode the uncompressed source image stored in <code>srcImage</code>
+ and output a YUV planar image to the given destination buffer.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(java.awt.image.BufferedImage, int)"><B>encodeYUV(BufferedImage, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Encode the uncompressed source image stored in <code>srcImage</code>
+ and return a buffer containing a YUV planar image.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#equals(org.libjpegturbo.turbojpeg.TJScalingFactor)"><B>equals(TJScalingFactor)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<DD>Returns true or false, depending on whether this instance and
+ <code>other</code> have the same numerator and denominator.
+</DL>
+<HR>
+<A NAME="_F_"><!-- --></A><H2>
+<B>F</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#finalize()"><B>finalize()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#finalize()"><B>finalize()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_BOTTOMUP"><B>FLAG_BOTTOMUP</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>The uncompressed source/destination image is stored in bottom-up (Windows,
+ OpenGL) order, not top-down (X11) order.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_FASTUPSAMPLE"><B>FLAG_FASTUPSAMPLE</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Use fast, inaccurate chrominance upsampling routines in the JPEG
+ decompressor (libjpeg and libjpeg-turbo versions only.)
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCEMMX"><B>FLAG_FORCEMMX</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use MMX code
+ (IPP and 32-bit libjpeg-turbo versions only.)
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE"><B>FLAG_FORCESSE</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use SSE code
+ (32-bit IPP and 32-bit libjpeg-turbo versions only.)
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE2"><B>FLAG_FORCESSE2</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use SSE2 code
+ (32-bit IPP and 32-bit libjpeg-turbo versions only.)
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE3"><B>FLAG_FORCESSE3</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use SSE3 code
+(64-bit IPP version only.)
+</DL>
+<HR>
+<A NAME="_G_"><!-- --></A><H2>
+<B>G</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getBlueOffset(int)"><B>getBlueOffset(int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>For the given pixel format, returns the number of bytes that the blue
+ component is offset from the start of the pixel.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#getCompressedSize()"><B>getCompressedSize()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Returns the size of the image (in bytes) generated by the most recent
+ compress/encode operation.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#getDenom()"><B>getDenom()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<DD>Returns denominator
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getGreenOffset(int)"><B>getGreenOffset(int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>For the given pixel format, returns the number of bytes that the green
+ component is offset from the start of the pixel.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getHeight()"><B>getHeight()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the height of the JPEG image associated with this decompressor
+ instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getJPEGBuf()"><B>getJPEGBuf()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the JPEG image buffer associated with this decompressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getJPEGSize()"><B>getJPEGSize()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the size of the JPEG image (in bytes) associated with this
+ decompressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getMCUHeight(int)"><B>getMCUHeight(int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Returns the MCU block height for the given level of chrominance
+ subsampling.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getMCUWidth(int)"><B>getMCUWidth(int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Returns the MCU block width for the given level of chrominance
+ subsampling.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#getNum()"><B>getNum()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<DD>Returns numerator
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getPixelSize(int)"><B>getPixelSize(int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Returns the pixel size (in bytes) of the given pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getRedOffset(int)"><B>getRedOffset(int)</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>For the given pixel format, returns the number of bytes that the red
+ component is offset from the start of the pixel.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#getScaled(int)"><B>getScaled(int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<DD>Returns the scaled value of <code>dimension</code>.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledHeight(int, int)"><B>getScaledHeight(int, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the height of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledWidth(int, int)"><B>getScaledWidth(int, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the width of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#getScalingFactors()"><B>getScalingFactors()</B></A> - 
+Static method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Returns a list of fractional scaling factors that the JPEG decompressor in
+ this implementation of TurboJPEG supports.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getSubsamp()"><B>getSubsamp()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the level of chrominance subsampling used in the JPEG image
+ associated with this decompressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#getTransformedSizes()"><B>getTransformedSizes()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<DD>Returns an array containing the sizes of the transformed JPEG images from
+ the most recent call to <A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>transform()</CODE></A>.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#getWidth()"><B>getWidth()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Returns the width of the JPEG image associated with this decompressor
+ instance.
+</DL>
+<HR>
+<A NAME="_H_"><!-- --></A><H2>
+<B>H</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#handle"><B>handle</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_I_"><!-- --></A><H2>
+<B>I</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#isOne()"><B>isOne()</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<DD>Returns true or false, depending on whether this instance is equal to
+ 1/1.
+</DL>
+<HR>
+<A NAME="_J_"><!-- --></A><H2>
+<B>J</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegBuf"><B>jpegBuf</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegBufSize"><B>jpegBufSize</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegHeight"><B>jpegHeight</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegSubsamp"><B>jpegSubsamp</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegWidth"><B>jpegWidth</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_N_"><!-- --></A><H2>
+<B>N</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#NUMOP"><B>NUMOP</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>The number of lossless transform operations
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#NUMPF"><B>NUMPF</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>The number of pixel formats
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP"><B>NUMSAMP</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>The number of chrominance subsampling options
+</DL>
+<HR>
+<A NAME="_O_"><!-- --></A><H2>
+<B>O</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#op"><B>op</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Transform operation (one of <code>OP_*</code>)
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_HFLIP"><B>OP_HFLIP</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Flip (mirror) image horizontally.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_NONE"><B>OP_NONE</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Do not transform the position of the image pixels.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT180"><B>OP_ROT180</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Rotate image 180 degrees.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT270"><B>OP_ROT270</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Rotate image counter-clockwise by 90 degrees.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT90"><B>OP_ROT90</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Rotate image clockwise by 90 degrees.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_TRANSPOSE"><B>OP_TRANSPOSE</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Transpose image (flip/mirror along upper left to lower right axis).
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_TRANSVERSE"><B>OP_TRANSVERSE</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Transverse transpose image (flip/mirror along upper right to lower left
+ axis).
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OP_VFLIP"><B>OP_VFLIP</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Flip (mirror) image vertically.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_CROP"><B>OPT_CROP</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>This option will enable lossless cropping.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_GRAY"><B>OPT_GRAY</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>This option will discard the color data in the input image and produce
+ a grayscale output image.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><B>OPT_PERFECT</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>This option will cause <A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>TJTransformer.transform()</CODE></A> to throw an exception if the transform is not
+ perfect.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#OPT_TRIM"><B>OPT_TRIM</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>This option will discard any partial MCU blocks that cannot be
+ transformed.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#options"><B>options</B></A> - 
+Variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Transform options (bitwise OR of one or more of <code>OPT_*</code>)
+<DT><A HREF="./org/libjpegturbo/turbojpeg/package-summary.html"><B>org.libjpegturbo.turbojpeg</B></A> - package org.libjpegturbo.turbojpeg<DD>&nbsp;</DL>
+<HR>
+<A NAME="_P_"><!-- --></A><H2>
+<B>P</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_BGR"><B>PF_BGR</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>BGR pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX"><B>PF_BGRX</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>BGRX pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY"><B>PF_GRAY</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Grayscale pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_RGB"><B>PF_RGB</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>RGB pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX"><B>PF_RGBX</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>RGBX pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR"><B>PF_XBGR</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>XBGR pixel format.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB"><B>PF_XRGB</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>XRGB pixel format.
+</DL>
+<HR>
+<A NAME="_S_"><!-- --></A><H2>
+<B>S</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#SAMP_420"><B>SAMP_420</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>4:2:0 chrominance subsampling.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#SAMP_422"><B>SAMP_422</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>4:2:2 chrominance subsampling.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#SAMP_440"><B>SAMP_440</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>4:4:0 chrominance subsampling.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#SAMP_444"><B>SAMP_444</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>4:4:4 chrominance subsampling (no chrominance subsampling).
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#SAMP_GRAY"><B>SAMP_GRAY</B></A> - 
+Static variable in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>Grayscale.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#setJPEGImage(byte[], int)"><B>setJPEGImage(byte[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Associate the JPEG image of length <code>imageSize</code> bytes stored in
+ <code>jpegImage</code> with this decompressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#setJPEGQuality(int)"><B>setJPEGQuality(int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Set the JPEG image quality level for subsequent compress operations.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)"><B>setSourceImage(byte[], int, int, int, int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Associate an uncompressed source image with this compressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#setSubsamp(int)"><B>setSubsamp(int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Set the level of chrominance subsampling for subsequent compress/encode
+ operations.
+</DL>
+<HR>
+<A NAME="_T_"><!-- --></A><H2>
+<B>T</B></H2>
+<DL>
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><B>TJ</B></A> - Class in <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</A><DD>TurboJPEG utility class (cannot be instantiated)<DT><A HREF="./org/libjpegturbo/turbojpeg/TJ.html#TJ()"><B>TJ()</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJCompressor</B></A> - Class in <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</A><DD>TurboJPEG compressor<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#TJCompressor()"><B>TJCompressor()</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Create a TurboJPEG compressor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html#TJCompressor(byte[], int, int, int, int)"><B>TJCompressor(byte[], int, int, int, int)</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A>
+<DD>Create a TurboJPEG compressor instance and associate the uncompressed
+ source image stored in <code>srcImage</code> with the newly-created
+ instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJDecompressor</B></A> - Class in <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</A><DD>TurboJPEG decompressor<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#TJDecompressor()"><B>TJDecompressor()</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Create a TurboJPEG decompresssor instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#TJDecompressor(byte[])"><B>TJDecompressor(byte[])</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Create a TurboJPEG decompressor instance and associate the JPEG image
+ stored in <code>jpegImage</code> with the newly-created instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html#TJDecompressor(byte[], int)"><B>TJDecompressor(byte[], int)</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>
+<DD>Create a TurboJPEG decompressor instance and associate the JPEG image
+ of length <code>imageSize</code> bytes stored in <code>jpegImage</code>
+ with the newly-created instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJScalingFactor</B></A> - Class in <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</A><DD>Fractional scaling factor<DT><A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html#TJScalingFactor(int, int)"><B>TJScalingFactor(int, int)</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>
+<DD>&nbsp;
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>TJTransform</B></A> - Class in <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</A><DD>Lossless transform parameters<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform()"><B>TJTransform()</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Create a new lossless transform instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform(int, int, int, int, int, int)"><B>TJTransform(int, int, int, int, int, int)</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Create a new lossless transform instance with the given parameters.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform(java.awt.Rectangle, int, int)"><B>TJTransform(Rectangle, int, int)</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>
+<DD>Create a new lossless transform instance with the given parameters.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg"><B>TJTransformer</B></A> - Class in <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html">org.libjpegturbo.turbojpeg</A><DD>TurboJPEG lossless transformer<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#TJTransformer()"><B>TJTransformer()</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<DD>Create a TurboJPEG lossless transformer instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#TJTransformer(byte[])"><B>TJTransformer(byte[])</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<DD>Create a TurboJPEG lossless transformer instance and associate the JPEG
+ image stored in <code>jpegImage</code> with the newly-created instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#TJTransformer(byte[], int)"><B>TJTransformer(byte[], int)</B></A> - 
+Constructor for class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<DD>Create a TurboJPEG lossless transformer instance and associate the JPEG
+ image of length <code>imageSize</code> bytes stored in
+ <code>jpegImage</code> with the newly-created instance.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><B>transform(byte[][], TJTransform[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<DD>Losslessly transform the JPEG image associated with this transformer
+ instance into one or more JPEG images stored in the given destination
+ buffers.
+<DT><A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html#transform(org.libjpegturbo.turbojpeg.TJTransform[], int)"><B>transform(TJTransform[], int)</B></A> - 
+Method in class org.libjpegturbo.turbojpeg.<A HREF="./org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A>
+<DD>Losslessly transform the JPEG image associated with this transformer
+ instance and return an array of <A HREF="./org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJDecompressor</CODE></A> instances, each of
+ which has a transformed JPEG image associated with it.
+</DL>
+<HR>
+<A HREF="#_B_">B</A> <A HREF="#_C_">C</A> <A HREF="#_D_">D</A> <A HREF="#_E_">E</A> <A HREF="#_F_">F</A> <A HREF="#_G_">G</A> <A HREF="#_H_">H</A> <A HREF="#_I_">I</A> <A HREF="#_J_">J</A> <A HREF="#_N_">N</A> <A HREF="#_O_">O</A> <A HREF="#_P_">P</A> <A HREF="#_S_">S</A> <A HREF="#_T_">T</A> 
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="./help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="./index.html?index-all.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="index-all.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="./allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="./allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/index.html b/java/doc/index.html
new file mode 100644
index 0000000..abf4dd4
--- /dev/null
+++ b/java/doc/index.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Apr 01 20:49:05 CDT 2011-->
+<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 = "undefined";
+    function loadFrames() {
+        if (targetPage != "" && targetPage != "undefined")
+             top.classFrame.location = top.targetPage;
+    }
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+</HEAD>
+<FRAMESET cols="20%,80%" title="" onLoad="top.loadFrames()">
+<FRAME src="allclasses-frame.html" name="packageFrame" title="All classes and interfaces (except non-static nested types)">
+<FRAME src="org/libjpegturbo/turbojpeg/package-summary.html" name="classFrame" title="Package, class and interface descriptions" scrolling="yes">
+<NOFRAMES>
+<H2>
+Frame Alert</H2>
+
+<P>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<BR>
+Link to<A HREF="org/libjpegturbo/turbojpeg/package-summary.html">Non-frame version.</A>
+</NOFRAMES>
+</FRAMESET>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJ.html b/java/doc/org/libjpegturbo/turbojpeg/TJ.html
new file mode 100644
index 0000000..86e33d6
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJ.html
@@ -0,0 +1,944 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:04 CDT 2011 -->
+<TITLE>
+TJ
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="TJ";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV CLASS&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJ.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJ.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.libjpegturbo.turbojpeg</FONT>
+<BR>
+Class TJ</H2>
+<PRE>
+java.lang.Object
+  <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><B>org.libjpegturbo.turbojpeg.TJ</B>
+</PRE>
+<HR>
+<DL>
+<DT><PRE>public final class <B>TJ</B><DT>extends java.lang.Object</DL>
+</PRE>
+
+<P>
+TurboJPEG utility class (cannot be instantiated)
+<P>
+
+<P>
+<HR>
+
+<P>
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_BOTTOMUP">FLAG_BOTTOMUP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The uncompressed source/destination image is stored in bottom-up (Windows,
+ OpenGL) order, not top-down (X11) order.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_FASTUPSAMPLE">FLAG_FASTUPSAMPLE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Use fast, inaccurate chrominance upsampling routines in the JPEG
+ decompressor (libjpeg and libjpeg-turbo versions only.)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCEMMX">FLAG_FORCEMMX</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Turn off CPU auto-detection and force TurboJPEG to use MMX code
+ (IPP and 32-bit libjpeg-turbo versions only.)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE">FLAG_FORCESSE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Turn off CPU auto-detection and force TurboJPEG to use SSE code
+ (32-bit IPP and 32-bit libjpeg-turbo versions only.)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE2">FLAG_FORCESSE2</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Turn off CPU auto-detection and force TurboJPEG to use SSE2 code
+ (32-bit IPP and 32-bit libjpeg-turbo versions only.)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#FLAG_FORCESSE3">FLAG_FORCESSE3</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Turn off CPU auto-detection and force TurboJPEG to use SSE3 code
+(64-bit IPP version only.)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMPF">NUMPF</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The number of pixel formats</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#NUMSAMP">NUMSAMP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The number of chrominance subsampling options</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGR">PF_BGR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BGR pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_BGRX">PF_BGRX</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BGRX pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_GRAY">PF_GRAY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Grayscale pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGB">PF_RGB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RGB pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_RGBX">PF_RGBX</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RGBX pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XBGR">PF_XBGR</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XBGR pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#PF_XRGB">PF_XRGB</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XRGB pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_420">SAMP_420</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4:2:0 chrominance subsampling.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_422">SAMP_422</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4:2:2 chrominance subsampling.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_440">SAMP_440</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4:4:0 chrominance subsampling.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_444">SAMP_444</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4:4:4 chrominance subsampling (no chrominance subsampling).</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_GRAY">SAMP_GRAY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Grayscale.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#TJ()">TJ</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSize(int, int)">bufSize</A></B>(int&nbsp;width,
+        int&nbsp;height)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the maximum size of the buffer (in bytes) required to hold a JPEG
+ image with the given width and height.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSizeYUV(int, int, int)">bufSizeYUV</A></B>(int&nbsp;width,
+           int&nbsp;height,
+           int&nbsp;subsamp)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the size of the buffer (in bytes) required to hold a YUV planar
+ image with the given width, height, and level of chrominance subsampling.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getBlueOffset(int)">getBlueOffset</A></B>(int&nbsp;pixelFormat)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For the given pixel format, returns the number of bytes that the blue
+ component is offset from the start of the pixel.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getGreenOffset(int)">getGreenOffset</A></B>(int&nbsp;pixelFormat)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For the given pixel format, returns the number of bytes that the green
+ component is offset from the start of the pixel.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUHeight(int)">getMCUHeight</A></B>(int&nbsp;subsamp)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the MCU block height for the given level of chrominance
+ subsampling.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUWidth(int)">getMCUWidth</A></B>(int&nbsp;subsamp)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the MCU block width for the given level of chrominance
+ subsampling.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getPixelSize(int)">getPixelSize</A></B>(int&nbsp;pixelFormat)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the pixel size (in bytes) of the given pixel format.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getRedOffset(int)">getRedOffset</A></B>(int&nbsp;pixelFormat)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;For the given pixel format, returns the number of bytes that the red
+ component is offset from the start of the pixel.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getScalingFactors()">getScalingFactors</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns a list of fractional scaling factors that the JPEG decompressor in
+ this implementation of TurboJPEG supports.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="NUMSAMP"><!-- --></A><H3>
+NUMSAMP</H3>
+<PRE>
+public static final int <B>NUMSAMP</B></PRE>
+<DL>
+<DD>The number of chrominance subsampling options
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.NUMSAMP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SAMP_444"><!-- --></A><H3>
+SAMP_444</H3>
+<PRE>
+public static final int <B>SAMP_444</B></PRE>
+<DL>
+<DD>4:4:4 chrominance subsampling (no chrominance subsampling).  The JPEG
+ or YUV image will contain one chrominance component for every pixel in the
+ source image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.SAMP_444">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SAMP_422"><!-- --></A><H3>
+SAMP_422</H3>
+<PRE>
+public static final int <B>SAMP_422</B></PRE>
+<DL>
+<DD>4:2:2 chrominance subsampling.  The JPEG or YUV image will contain one
+ chrominance component for every 2x1 block of pixels in the source image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.SAMP_422">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SAMP_420"><!-- --></A><H3>
+SAMP_420</H3>
+<PRE>
+public static final int <B>SAMP_420</B></PRE>
+<DL>
+<DD>4:2:0 chrominance subsampling.  The JPEG or YUV image will contain one
+ chrominance component for every 2x2 block of pixels in the source image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.SAMP_420">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SAMP_GRAY"><!-- --></A><H3>
+SAMP_GRAY</H3>
+<PRE>
+public static final int <B>SAMP_GRAY</B></PRE>
+<DL>
+<DD>Grayscale.  The JPEG or YUV image will contain no chrominance components.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.SAMP_GRAY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="SAMP_440"><!-- --></A><H3>
+SAMP_440</H3>
+<PRE>
+public static final int <B>SAMP_440</B></PRE>
+<DL>
+<DD>4:4:0 chrominance subsampling.  The JPEG or YUV image will contain one
+ chrominance component for every 1x2 block of pixels in the source image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.SAMP_440">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="NUMPF"><!-- --></A><H3>
+NUMPF</H3>
+<PRE>
+public static final int <B>NUMPF</B></PRE>
+<DL>
+<DD>The number of pixel formats
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.NUMPF">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_RGB"><!-- --></A><H3>
+PF_RGB</H3>
+<PRE>
+public static final int <B>PF_RGB</B></PRE>
+<DL>
+<DD>RGB pixel format.  The red, green, and blue components in the image are
+ stored in 3-byte pixels in the order R, G, B from lowest to highest byte
+ address within each pixel.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_RGB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_BGR"><!-- --></A><H3>
+PF_BGR</H3>
+<PRE>
+public static final int <B>PF_BGR</B></PRE>
+<DL>
+<DD>BGR pixel format.  The red, green, and blue components in the image are
+ stored in 3-byte pixels in the order B, G, R from lowest to highest byte
+ address within each pixel.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_BGR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_RGBX"><!-- --></A><H3>
+PF_RGBX</H3>
+<PRE>
+public static final int <B>PF_RGBX</B></PRE>
+<DL>
+<DD>RGBX pixel format.  The red, green, and blue components in the image are
+ stored in 4-byte pixels in the order R, G, B from lowest to highest byte
+ address within each pixel.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_RGBX">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_BGRX"><!-- --></A><H3>
+PF_BGRX</H3>
+<PRE>
+public static final int <B>PF_BGRX</B></PRE>
+<DL>
+<DD>BGRX pixel format.  The red, green, and blue components in the image are
+ stored in 4-byte pixels in the order B, G, R from lowest to highest byte
+ address within each pixel.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_BGRX">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_XBGR"><!-- --></A><H3>
+PF_XBGR</H3>
+<PRE>
+public static final int <B>PF_XBGR</B></PRE>
+<DL>
+<DD>XBGR pixel format.  The red, green, and blue components in the image are
+ stored in 4-byte pixels in the order R, G, B from highest to lowest byte
+ address within each pixel.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_XBGR">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_XRGB"><!-- --></A><H3>
+PF_XRGB</H3>
+<PRE>
+public static final int <B>PF_XRGB</B></PRE>
+<DL>
+<DD>XRGB pixel format.  The red, green, and blue components in the image are
+ stored in 4-byte pixels in the order B, G, R from highest to lowest byte
+ address within each pixel.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_XRGB">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="PF_GRAY"><!-- --></A><H3>
+PF_GRAY</H3>
+<PRE>
+public static final int <B>PF_GRAY</B></PRE>
+<DL>
+<DD>Grayscale pixel format.  Each 1-byte pixel represents a luminance
+ (brightness) level from 0 to 255.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.PF_GRAY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FLAG_BOTTOMUP"><!-- --></A><H3>
+FLAG_BOTTOMUP</H3>
+<PRE>
+public static final int <B>FLAG_BOTTOMUP</B></PRE>
+<DL>
+<DD>The uncompressed source/destination image is stored in bottom-up (Windows,
+ OpenGL) order, not top-down (X11) order.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_BOTTOMUP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FLAG_FORCEMMX"><!-- --></A><H3>
+FLAG_FORCEMMX</H3>
+<PRE>
+public static final int <B>FLAG_FORCEMMX</B></PRE>
+<DL>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use MMX code
+ (IPP and 32-bit libjpeg-turbo versions only.)
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_FORCEMMX">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FLAG_FORCESSE"><!-- --></A><H3>
+FLAG_FORCESSE</H3>
+<PRE>
+public static final int <B>FLAG_FORCESSE</B></PRE>
+<DL>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use SSE code
+ (32-bit IPP and 32-bit libjpeg-turbo versions only.)
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_FORCESSE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FLAG_FORCESSE2"><!-- --></A><H3>
+FLAG_FORCESSE2</H3>
+<PRE>
+public static final int <B>FLAG_FORCESSE2</B></PRE>
+<DL>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use SSE2 code
+ (32-bit IPP and 32-bit libjpeg-turbo versions only.)
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_FORCESSE2">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FLAG_FORCESSE3"><!-- --></A><H3>
+FLAG_FORCESSE3</H3>
+<PRE>
+public static final int <B>FLAG_FORCESSE3</B></PRE>
+<DL>
+<DD>Turn off CPU auto-detection and force TurboJPEG to use SSE3 code
+(64-bit IPP version only.)
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_FORCESSE3">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="FLAG_FASTUPSAMPLE"><!-- --></A><H3>
+FLAG_FASTUPSAMPLE</H3>
+<PRE>
+public static final int <B>FLAG_FASTUPSAMPLE</B></PRE>
+<DL>
+<DD>Use fast, inaccurate chrominance upsampling routines in the JPEG
+ decompressor (libjpeg and libjpeg-turbo versions only.)
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJ.FLAG_FASTUPSAMPLE">Constant Field Values</A></DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="TJ()"><!-- --></A><H3>
+TJ</H3>
+<PRE>
+public <B>TJ</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="getMCUWidth(int)"><!-- --></A><H3>
+getMCUWidth</H3>
+<PRE>
+public static int <B>getMCUWidth</B>(int&nbsp;subsamp)
+                       throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the MCU block width for the given level of chrominance
+ subsampling.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>subsamp</CODE> - the level of chrominance subsampling (one of
+ <code>SAMP_*</code>)
+<DT><B>Returns:</B><DD>the MCU block width for the given level of chrominance subsampling
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMCUHeight(int)"><!-- --></A><H3>
+getMCUHeight</H3>
+<PRE>
+public static int <B>getMCUHeight</B>(int&nbsp;subsamp)
+                        throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the MCU block height for the given level of chrominance
+ subsampling.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>subsamp</CODE> - the level of chrominance subsampling (one of
+ <code>SAMP_*</code>)
+<DT><B>Returns:</B><DD>the MCU block height for the given level of chrominance
+ subsampling
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getPixelSize(int)"><!-- --></A><H3>
+getPixelSize</H3>
+<PRE>
+public static int <B>getPixelSize</B>(int&nbsp;pixelFormat)
+                        throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the pixel size (in bytes) of the given pixel format.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>pixelFormat</CODE> - the pixel format (one of <code>PF_*</code>)
+<DT><B>Returns:</B><DD>the pixel size (in bytes) of the given pixel format
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getRedOffset(int)"><!-- --></A><H3>
+getRedOffset</H3>
+<PRE>
+public static int <B>getRedOffset</B>(int&nbsp;pixelFormat)
+                        throws java.lang.Exception</PRE>
+<DL>
+<DD>For the given pixel format, returns the number of bytes that the red
+ component is offset from the start of the pixel.  For instance, if a pixel
+ of format <code>TJ.PF_BGRX</code> is stored in <code>char pixel[]</code>,
+ then the red component will be
+ <code>pixel[TJ.getRedOffset(TJ.PF_BGRX)]</code>.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>pixelFormat</CODE> - the pixel format (one of <code>PF_*</code>)
+<DT><B>Returns:</B><DD>the red offset for the given pixel format
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getGreenOffset(int)"><!-- --></A><H3>
+getGreenOffset</H3>
+<PRE>
+public static int <B>getGreenOffset</B>(int&nbsp;pixelFormat)
+                          throws java.lang.Exception</PRE>
+<DL>
+<DD>For the given pixel format, returns the number of bytes that the green
+ component is offset from the start of the pixel.  For instance, if a pixel
+ of format <code>TJ.PF_BGRX</code> is stored in <code>char pixel[]</code>,
+ then the green component will be
+ <code>pixel[TJ.getGreenOffset(TJ.PF_BGRX)]</code>.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>pixelFormat</CODE> - the pixel format (one of <code>PF_*</code>)
+<DT><B>Returns:</B><DD>the green offset for the given pixel format
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getBlueOffset(int)"><!-- --></A><H3>
+getBlueOffset</H3>
+<PRE>
+public static int <B>getBlueOffset</B>(int&nbsp;pixelFormat)
+                         throws java.lang.Exception</PRE>
+<DL>
+<DD>For the given pixel format, returns the number of bytes that the blue
+ component is offset from the start of the pixel.  For instance, if a pixel
+ of format <code>TJ.PF_BGRX</code> is stored in <code>char pixel[]</code>,
+ then the blue component will be
+ <code>pixel[TJ.getBlueOffset(TJ.PF_BGRX)]</code>.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>pixelFormat</CODE> - the pixel format (one of <code>PF_*</code>)
+<DT><B>Returns:</B><DD>the blue offset for the given pixel format
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="bufSize(int, int)"><!-- --></A><H3>
+bufSize</H3>
+<PRE>
+public static int <B>bufSize</B>(int&nbsp;width,
+                          int&nbsp;height)
+                   throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the maximum size of the buffer (in bytes) required to hold a JPEG
+ image with the given width and height.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>width</CODE> - the width (in pixels) of the JPEG image<DD><CODE>height</CODE> - the height (in pixels) of the JPEG image
+<DT><B>Returns:</B><DD>the maximum size of the buffer (in bytes) required to hold a JPEG
+ image with the given width and height
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="bufSizeYUV(int, int, int)"><!-- --></A><H3>
+bufSizeYUV</H3>
+<PRE>
+public static int <B>bufSizeYUV</B>(int&nbsp;width,
+                             int&nbsp;height,
+                             int&nbsp;subsamp)
+                      throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the size of the buffer (in bytes) required to hold a YUV planar
+ image with the given width, height, and level of chrominance subsampling.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>width</CODE> - the width (in pixels) of the YUV image<DD><CODE>height</CODE> - the height (in pixels) of the YUV image<DD><CODE>subsamp</CODE> - the level of chrominance subsampling used in the YUV
+ image
+<DT><B>Returns:</B><DD>the size of the buffer (in bytes) required to hold a YUV planar
+ image with the given width, height, and level of chrominance subsampling
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getScalingFactors()"><!-- --></A><H3>
+getScalingFactors</H3>
+<PRE>
+public static <A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>[] <B>getScalingFactors</B>()
+                                           throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns a list of fractional scaling factors that the JPEG decompressor in
+ this implementation of TurboJPEG supports.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>a list of fractional scaling factors that the JPEG decompressor in
+ this implementation of TurboJPEG supports
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV CLASS&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJ.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJ.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
new file mode 100644
index 0000000..b9a8fc4
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJCompressor.html
@@ -0,0 +1,696 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+TJCompressor
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="TJCompressor";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJCompressor.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJCompressor.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.libjpegturbo.turbojpeg</FONT>
+<BR>
+Class TJCompressor</H2>
+<PRE>
+java.lang.Object
+  <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><B>org.libjpegturbo.turbojpeg.TJCompressor</B>
+</PRE>
+<HR>
+<DL>
+<DT><PRE>public class <B>TJCompressor</B><DT>extends java.lang.Object</DL>
+</PRE>
+
+<P>
+TurboJPEG compressor
+<P>
+
+<P>
+<HR>
+
+<P>
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#TJCompressor()">TJCompressor</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG compressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#TJCompressor(byte[], int, int, int, int)">TJCompressor</A></B>(byte[]&nbsp;srcImage,
+             int&nbsp;width,
+             int&nbsp;pitch,
+             int&nbsp;height,
+             int&nbsp;pixelFormat)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG compressor instance and associate the uncompressed
+ source image stored in <code>srcImage</code> with the newly-created
+ instance.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#close()">close</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Free the native structures associated with this compressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#compress(java.awt.image.BufferedImage, byte[], int)">compress</A></B>(java.awt.image.BufferedImage&nbsp;srcImage,
+         byte[]&nbsp;dstBuf,
+         int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compress the uncompressed source image stored in <code>srcImage</code>
+ and output a JPEG image to the given destination buffer.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#compress(java.awt.image.BufferedImage, int)">compress</A></B>(java.awt.image.BufferedImage&nbsp;srcImage,
+         int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compress the uncompressed source image stored in <code>srcImage</code>
+ and return a buffer containing a JPEG image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#compress(byte[], int)">compress</A></B>(byte[]&nbsp;dstBuf,
+         int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compress the uncompressed source image associated with this compressor
+ instance and output a JPEG image to the given destination buffer.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#compress(int)">compress</A></B>(int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compress the uncompressed source image associated with this compressor
+ instance and return a buffer containing a JPEG image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(java.awt.image.BufferedImage, byte[], int)">encodeYUV</A></B>(java.awt.image.BufferedImage&nbsp;srcImage,
+          byte[]&nbsp;dstBuf,
+          int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Encode the uncompressed source image stored in <code>srcImage</code>
+ and output a YUV planar image to the given destination buffer.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(java.awt.image.BufferedImage, int)">encodeYUV</A></B>(java.awt.image.BufferedImage&nbsp;srcImage,
+          int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Encode the uncompressed source image stored in <code>srcImage</code>
+ and return a buffer containing a YUV planar image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(byte[], int)">encodeYUV</A></B>(byte[]&nbsp;dstBuf,
+          int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Encode the uncompressed source image associated with this compressor
+ instance and output a YUV planar image to the given destination buffer.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(int)">encodeYUV</A></B>(int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Encode the uncompressed source image associated with this compressor
+ instance and return a buffer containing a YUV planar image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#finalize()">finalize</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#getCompressedSize()">getCompressedSize</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the size of the image (in bytes) generated by the most recent
+ compress/encode operation.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setJPEGQuality(int)">setJPEGQuality</A></B>(int&nbsp;quality)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the JPEG image quality level for subsequent compress operations.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)">setSourceImage</A></B>(byte[]&nbsp;srcImage,
+               int&nbsp;width,
+               int&nbsp;pitch,
+               int&nbsp;height,
+               int&nbsp;pixelFormat)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Associate an uncompressed source image with this compressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSubsamp(int)">setSubsamp</A></B>(int&nbsp;newSubsamp)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the level of chrominance subsampling for subsequent compress/encode
+ operations.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="TJCompressor()"><!-- --></A><H3>
+TJCompressor</H3>
+<PRE>
+public <B>TJCompressor</B>()
+             throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG compressor instance.
+<P>
+<DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<HR>
+
+<A NAME="TJCompressor(byte[], int, int, int, int)"><!-- --></A><H3>
+TJCompressor</H3>
+<PRE>
+public <B>TJCompressor</B>(byte[]&nbsp;srcImage,
+                    int&nbsp;width,
+                    int&nbsp;pitch,
+                    int&nbsp;height,
+                    int&nbsp;pixelFormat)
+             throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG compressor instance and associate the uncompressed
+ source image stored in <code>srcImage</code> with the newly-created
+ instance.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>srcImage</CODE> - see <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)"><CODE>setSourceImage(byte[], int, int, int, int)</CODE></A> for description<DD><CODE>width</CODE> - see <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)"><CODE>setSourceImage(byte[], int, int, int, int)</CODE></A> for description<DD><CODE>pitch</CODE> - see <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)"><CODE>setSourceImage(byte[], int, int, int, int)</CODE></A> for description<DD><CODE>height</CODE> - see <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)"><CODE>setSourceImage(byte[], int, int, int, int)</CODE></A> for description<DD><CODE>pixelFormat</CODE> - see <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#setSourceImage(byte[], int, int, int, int)"><CODE>setSourceImage(byte[], int, int, int, int)</CODE></A> for description
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="setSourceImage(byte[], int, int, int, int)"><!-- --></A><H3>
+setSourceImage</H3>
+<PRE>
+public void <B>setSourceImage</B>(byte[]&nbsp;srcImage,
+                           int&nbsp;width,
+                           int&nbsp;pitch,
+                           int&nbsp;height,
+                           int&nbsp;pixelFormat)
+                    throws java.lang.Exception</PRE>
+<DL>
+<DD>Associate an uncompressed source image with this compressor instance.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>srcImage</CODE> - image buffer containing RGB or grayscale pixels to be
+ compressed<DD><CODE>width</CODE> - width (in pixels) of the source image<DD><CODE>pitch</CODE> - bytes per line of the source image.  Normally, this should be
+ <code>width * TJ.pixelSize(pixelFormat)</code> if the source image is
+ unpadded, but you can use this parameter to, for instance, specify that
+ the scanlines in the source image are padded to 4-byte boundaries, as is
+ the case for Windows bitmaps.  You can also be clever and use this
+ parameter to skip lines, etc.  Setting this parameter to 0 is the
+ equivalent of setting it to <code>width *
+ TJ.pixelSize(pixelFormat)</code>.<DD><CODE>height</CODE> - height (in pixels) of the source image<DD><CODE>pixelFormat</CODE> - pixel format of the source image (one of
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.PF_*</CODE></A>)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setSubsamp(int)"><!-- --></A><H3>
+setSubsamp</H3>
+<PRE>
+public void <B>setSubsamp</B>(int&nbsp;newSubsamp)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Set the level of chrominance subsampling for subsequent compress/encode
+ operations.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newSubsamp</CODE> - the new level of chrominance subsampling (one of
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.SAMP_*</CODE></A>)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setJPEGQuality(int)"><!-- --></A><H3>
+setJPEGQuality</H3>
+<PRE>
+public void <B>setJPEGQuality</B>(int&nbsp;quality)
+                    throws java.lang.Exception</PRE>
+<DL>
+<DD>Set the JPEG image quality level for subsequent compress operations.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>quality</CODE> - the new JPEG image quality level (1 to 100, 1 = worst,
+ 100 = best)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="compress(byte[], int)"><!-- --></A><H3>
+compress</H3>
+<PRE>
+public void <B>compress</B>(byte[]&nbsp;dstBuf,
+                     int&nbsp;flags)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Compress the uncompressed source image associated with this compressor
+ instance and output a JPEG image to the given destination buffer.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>dstBuf</CODE> - buffer which will receive the JPEG image.  Use
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSize(int, int)"><CODE>TJ.bufSize(int, int)</CODE></A> to determine the maximum size for this buffer based on
+ the image width and height.<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="compress(int)"><!-- --></A><H3>
+compress</H3>
+<PRE>
+public byte[] <B>compress</B>(int&nbsp;flags)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Compress the uncompressed source image associated with this compressor
+ instance and return a buffer containing a JPEG image.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a buffer containing a JPEG image.  The length of this buffer will
+ not be equal to the size of the JPEG image.  Use <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#getCompressedSize()"><CODE>getCompressedSize()</CODE></A> to obtain the size of the JPEG image.
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="compress(java.awt.image.BufferedImage, byte[], int)"><!-- --></A><H3>
+compress</H3>
+<PRE>
+public void <B>compress</B>(java.awt.image.BufferedImage&nbsp;srcImage,
+                     byte[]&nbsp;dstBuf,
+                     int&nbsp;flags)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Compress the uncompressed source image stored in <code>srcImage</code>
+ and output a JPEG image to the given destination buffer.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>srcImage</CODE> - a <code>BufferedImage</code> instance containing RGB or
+ grayscale pixels to be compressed<DD><CODE>dstBuf</CODE> - buffer which will receive the JPEG image.  Use
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSize(int, int)"><CODE>TJ.bufSize(int, int)</CODE></A> to determine the maximum size for this buffer based on
+ the image width and height.<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="compress(java.awt.image.BufferedImage, int)"><!-- --></A><H3>
+compress</H3>
+<PRE>
+public byte[] <B>compress</B>(java.awt.image.BufferedImage&nbsp;srcImage,
+                       int&nbsp;flags)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Compress the uncompressed source image stored in <code>srcImage</code>
+ and return a buffer containing a JPEG image.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>srcImage</CODE> - a <code>BufferedImage</code> instance containing RGB or
+ grayscale pixels to be compressed<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a buffer containing a JPEG image.  The length of this buffer will
+ not be equal to the size of the JPEG image.  Use <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#getCompressedSize()"><CODE>getCompressedSize()</CODE></A> to obtain the size of the JPEG image.
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="encodeYUV(byte[], int)"><!-- --></A><H3>
+encodeYUV</H3>
+<PRE>
+public void <B>encodeYUV</B>(byte[]&nbsp;dstBuf,
+                      int&nbsp;flags)
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Encode the uncompressed source image associated with this compressor
+ instance and output a YUV planar image to the given destination buffer.
+ This method uses the accelerated color conversion routines in
+ TurboJPEG's underlying codec to produce a planar YUV image that is
+ suitable for direct video display.  Specifically, if the chrominance
+ components are subsampled along the horizontal dimension, then the width
+ of the luminance plane is padded to 2 in the output image (same goes for
+ the height of the luminance plane, if the chrominance components are
+ subsampled along the vertical dimension.)  Also, each line of each plane
+ in the output image is padded to 4 bytes.  Although this will work with
+ any subsampling option, it is really only useful in combination with
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#SAMP_420"><CODE>TJ.SAMP_420</CODE></A>, which produces an image compatible with the I420 (AKA
+ "YUV420P") format.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>dstBuf</CODE> - buffer which will receive the YUV planar image.  Use
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSizeYUV(int, int, int)"><CODE>TJ.bufSizeYUV(int, int, int)</CODE></A> to determine the appropriate size for this buffer
+ based on the image width, height, and level of chrominance subsampling.<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="encodeYUV(int)"><!-- --></A><H3>
+encodeYUV</H3>
+<PRE>
+public byte[] <B>encodeYUV</B>(int&nbsp;flags)
+                 throws java.lang.Exception</PRE>
+<DL>
+<DD>Encode the uncompressed source image associated with this compressor
+ instance and return a buffer containing a YUV planar image.  See
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(byte[], int)"><CODE>encodeYUV(byte[], int)</CODE></A> for more detail.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a buffer containing a YUV planar image
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="encodeYUV(java.awt.image.BufferedImage, byte[], int)"><!-- --></A><H3>
+encodeYUV</H3>
+<PRE>
+public void <B>encodeYUV</B>(java.awt.image.BufferedImage&nbsp;srcImage,
+                      byte[]&nbsp;dstBuf,
+                      int&nbsp;flags)
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Encode the uncompressed source image stored in <code>srcImage</code>
+ and output a YUV planar image to the given destination buffer.  See
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(byte[], int)"><CODE>encodeYUV(byte[], int)</CODE></A> for more detail.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>srcImage</CODE> - a <code>BufferedImage</code> instance containing RGB or
+ grayscale pixels to be encoded<DD><CODE>dstBuf</CODE> - buffer which will receive the YUV planar image.  Use
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSizeYUV(int, int, int)"><CODE>TJ.bufSizeYUV(int, int, int)</CODE></A> to determine the appropriate size for this buffer
+ based on the image width, height, and level of chrominance subsampling.<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="encodeYUV(java.awt.image.BufferedImage, int)"><!-- --></A><H3>
+encodeYUV</H3>
+<PRE>
+public byte[] <B>encodeYUV</B>(java.awt.image.BufferedImage&nbsp;srcImage,
+                        int&nbsp;flags)
+                 throws java.lang.Exception</PRE>
+<DL>
+<DD>Encode the uncompressed source image stored in <code>srcImage</code>
+ and return a buffer containing a YUV planar image.  See
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(byte[], int)"><CODE>encodeYUV(byte[], int)</CODE></A> for more detail.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>srcImage</CODE> - a <code>BufferedImage</code> instance containing RGB or
+ grayscale pixels to be encoded<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a buffer containing a YUV planar image
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getCompressedSize()"><!-- --></A><H3>
+getCompressedSize</H3>
+<PRE>
+public int <B>getCompressedSize</B>()</PRE>
+<DL>
+<DD>Returns the size of the image (in bytes) generated by the most recent
+ compress/encode operation.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the size of the image (in bytes) generated by the most recent
+ compress/encode operation</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="close()"><!-- --></A><H3>
+close</H3>
+<PRE>
+public void <B>close</B>()
+           throws java.lang.Exception</PRE>
+<DL>
+<DD>Free the native structures associated with this compressor instance.
+<P>
+<DD><DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="finalize()"><!-- --></A><H3>
+finalize</H3>
+<PRE>
+protected void <B>finalize</B>()
+                 throws java.lang.Throwable</PRE>
+<DL>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>finalize</CODE> in class <CODE>java.lang.Object</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Throwable</CODE></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJCompressor.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJCompressor.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html
new file mode 100644
index 0000000..f610afe
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJDecompressor.html
@@ -0,0 +1,948 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+TJDecompressor
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="TJDecompressor";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJDecompressor.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJDecompressor.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.libjpegturbo.turbojpeg</FONT>
+<BR>
+Class TJDecompressor</H2>
+<PRE>
+java.lang.Object
+  <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><B>org.libjpegturbo.turbojpeg.TJDecompressor</B>
+</PRE>
+<DL>
+<DT><B>Direct Known Subclasses:</B> <DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A></DD>
+</DL>
+<HR>
+<DL>
+<DT><PRE>public class <B>TJDecompressor</B><DT>extends java.lang.Object</DL>
+</PRE>
+
+<P>
+TurboJPEG decompressor
+<P>
+
+<P>
+<HR>
+
+<P>
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;long</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#handle">handle</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegBuf">jpegBuf</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegBufSize">jpegBufSize</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegHeight">jpegHeight</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegSubsamp">jpegSubsamp</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegWidth">jpegWidth</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#TJDecompressor()">TJDecompressor</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG decompresssor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#TJDecompressor(byte[])">TJDecompressor</A></B>(byte[]&nbsp;jpegImage)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG decompressor instance and associate the JPEG image
+ stored in <code>jpegImage</code> with the newly-created instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#TJDecompressor(byte[], int)">TJDecompressor</A></B>(byte[]&nbsp;jpegImage,
+               int&nbsp;imageSize)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG decompressor instance and associate the JPEG image
+ of length <code>imageSize</code> bytes stored in <code>jpegImage</code>
+ with the newly-created instance.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#close()">close</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Free the native structures associated with this decompressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(java.awt.image.BufferedImage, int)">decompress</A></B>(java.awt.image.BufferedImage&nbsp;dstImage,
+           int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decompress the JPEG source image associated with this decompressor
+ instance and output a decompressed image to the given
+ <code>BufferedImage</code> instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)">decompress</A></B>(byte[]&nbsp;dstBuf,
+           int&nbsp;desiredWidth,
+           int&nbsp;pitch,
+           int&nbsp;desiredHeight,
+           int&nbsp;pixelFormat,
+           int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decompress the JPEG source image associated with this decompressor
+ instance and output a decompressed image to the given destination buffer.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.awt.image.BufferedImage</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(int, int, int, int)">decompress</A></B>(int&nbsp;desiredWidth,
+           int&nbsp;desiredHeight,
+           int&nbsp;bufferedImageType,
+           int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decompress the JPEG source image associated with this decompressor
+ instance and return a <code>BufferedImage</code> instance containing the
+ decompressed image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(int, int, int, int, int)">decompress</A></B>(int&nbsp;desiredWidth,
+           int&nbsp;pitch,
+           int&nbsp;desiredHeight,
+           int&nbsp;pixelFormat,
+           int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decompress the JPEG source image associated with this decompressor
+ instance and return a buffer containing the decompressed image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(byte[], int)">decompressToYUV</A></B>(byte[]&nbsp;dstBuf,
+                int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decompress the JPEG source image associated with this decompressor
+ instance and output a YUV planar image to the given destination buffer.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(int)">decompressToYUV</A></B>(int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Decompress the JPEG source image associated with this decompressor
+ instance and return a buffer containing a YUV planar image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#finalize()">finalize</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getHeight()">getHeight</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the height of the JPEG image associated with this decompressor
+ instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;byte[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getJPEGBuf()">getJPEGBuf</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the JPEG image buffer associated with this decompressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getJPEGSize()">getJPEGSize</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the size of the JPEG image (in bytes) associated with this
+ decompressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledHeight(int, int)">getScaledHeight</A></B>(int&nbsp;desiredWidth,
+                int&nbsp;desiredHeight)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the height of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledWidth(int, int)">getScaledWidth</A></B>(int&nbsp;desiredWidth,
+               int&nbsp;desiredHeight)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the width of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getSubsamp()">getSubsamp</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the level of chrominance subsampling used in the JPEG image
+ associated with this decompressor instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getWidth()">getWidth</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the width of the JPEG image associated with this decompressor
+ instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#setJPEGImage(byte[], int)">setJPEGImage</A></B>(byte[]&nbsp;jpegImage,
+             int&nbsp;imageSize)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Associate the JPEG image of length <code>imageSize</code> bytes stored in
+ <code>jpegImage</code> with this decompressor instance.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="handle"><!-- --></A><H3>
+handle</H3>
+<PRE>
+protected long <B>handle</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="jpegBuf"><!-- --></A><H3>
+jpegBuf</H3>
+<PRE>
+protected byte[] <B>jpegBuf</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="jpegBufSize"><!-- --></A><H3>
+jpegBufSize</H3>
+<PRE>
+protected int <B>jpegBufSize</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="jpegWidth"><!-- --></A><H3>
+jpegWidth</H3>
+<PRE>
+protected int <B>jpegWidth</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="jpegHeight"><!-- --></A><H3>
+jpegHeight</H3>
+<PRE>
+protected int <B>jpegHeight</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="jpegSubsamp"><!-- --></A><H3>
+jpegSubsamp</H3>
+<PRE>
+protected int <B>jpegSubsamp</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="TJDecompressor()"><!-- --></A><H3>
+TJDecompressor</H3>
+<PRE>
+public <B>TJDecompressor</B>()
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG decompresssor instance.
+<P>
+<DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<HR>
+
+<A NAME="TJDecompressor(byte[])"><!-- --></A><H3>
+TJDecompressor</H3>
+<PRE>
+public <B>TJDecompressor</B>(byte[]&nbsp;jpegImage)
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG decompressor instance and associate the JPEG image
+ stored in <code>jpegImage</code> with the newly-created instance.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>jpegImage</CODE> - JPEG image buffer (size of the JPEG image is assumed to
+ be the length of the array)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<HR>
+
+<A NAME="TJDecompressor(byte[], int)"><!-- --></A><H3>
+TJDecompressor</H3>
+<PRE>
+public <B>TJDecompressor</B>(byte[]&nbsp;jpegImage,
+                      int&nbsp;imageSize)
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG decompressor instance and associate the JPEG image
+ of length <code>imageSize</code> bytes stored in <code>jpegImage</code>
+ with the newly-created instance.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>jpegImage</CODE> - JPEG image buffer<DD><CODE>imageSize</CODE> - size of the JPEG image (in bytes)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="setJPEGImage(byte[], int)"><!-- --></A><H3>
+setJPEGImage</H3>
+<PRE>
+public void <B>setJPEGImage</B>(byte[]&nbsp;jpegImage,
+                         int&nbsp;imageSize)
+                  throws java.lang.Exception</PRE>
+<DL>
+<DD>Associate the JPEG image of length <code>imageSize</code> bytes stored in
+ <code>jpegImage</code> with this decompressor instance.  This image will
+ be used as the source image for subsequent decompress operations.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>jpegImage</CODE> - JPEG image buffer<DD><CODE>imageSize</CODE> - size of the JPEG image (in bytes)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getWidth()"><!-- --></A><H3>
+getWidth</H3>
+<PRE>
+public int <B>getWidth</B>()
+             throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the width of the JPEG image associated with this decompressor
+ instance.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the width of the JPEG image associated with this decompressor
+ instance
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getHeight()"><!-- --></A><H3>
+getHeight</H3>
+<PRE>
+public int <B>getHeight</B>()
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the height of the JPEG image associated with this decompressor
+ instance.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the height of the JPEG image associated with this decompressor
+ instance
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getSubsamp()"><!-- --></A><H3>
+getSubsamp</H3>
+<PRE>
+public int <B>getSubsamp</B>()
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the level of chrominance subsampling used in the JPEG image
+ associated with this decompressor instance.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the level of chrominance subsampling used in the JPEG image
+ associated with this decompressor instance
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getJPEGBuf()"><!-- --></A><H3>
+getJPEGBuf</H3>
+<PRE>
+public byte[] <B>getJPEGBuf</B>()
+                  throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the JPEG image buffer associated with this decompressor instance.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the JPEG image buffer associated with this decompressor instance
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getJPEGSize()"><!-- --></A><H3>
+getJPEGSize</H3>
+<PRE>
+public int <B>getJPEGSize</B>()
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the size of the JPEG image (in bytes) associated with this
+ decompressor instance.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the size of the JPEG image (in bytes) associated with this
+ decompressor instance
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getScaledWidth(int, int)"><!-- --></A><H3>
+getScaledWidth</H3>
+<PRE>
+public int <B>getScaledWidth</B>(int&nbsp;desiredWidth,
+                          int&nbsp;desiredHeight)
+                   throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the width of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>desiredWidth</CODE> - desired width (in pixels) of the decompressed image.
+ Setting this to 0 is the same as setting it to the width of the JPEG image
+ (in other words, the width will not be considered when determining the
+ scaled image size.)<DD><CODE>desiredHeight</CODE> - desired height (in pixels) of the decompressed image.
+ Setting this to 0 is the same as setting it to the height of the JPEG
+ image (in other words, the height will not be considered when determining
+ the scaled image size.)
+<DT><B>Returns:</B><DD>the width of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getScaledHeight(int, int)"><!-- --></A><H3>
+getScaledHeight</H3>
+<PRE>
+public int <B>getScaledHeight</B>(int&nbsp;desiredWidth,
+                           int&nbsp;desiredHeight)
+                    throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns the height of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>desiredWidth</CODE> - desired width (in pixels) of the decompressed image.
+ Setting this to 0 is the same as setting it to the width of the JPEG image
+ (in other words, the width will not be considered when determining the
+ scaled image size.)<DD><CODE>desiredHeight</CODE> - desired height (in pixels) of the decompressed image.
+ Setting this to 0 is the same as setting it to the height of the JPEG
+ image (in other words, the height will not be considered when determining
+ the scaled image size.)
+<DT><B>Returns:</B><DD>the height of the largest scaled down image that the TurboJPEG
+ decompressor can generate without exceeding the desired image width and
+ height
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="decompress(byte[], int, int, int, int, int)"><!-- --></A><H3>
+decompress</H3>
+<PRE>
+public void <B>decompress</B>(byte[]&nbsp;dstBuf,
+                       int&nbsp;desiredWidth,
+                       int&nbsp;pitch,
+                       int&nbsp;desiredHeight,
+                       int&nbsp;pixelFormat,
+                       int&nbsp;flags)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and output a decompressed image to the given destination buffer.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>dstBuf</CODE> - buffer which will receive the decompressed image.  This
+ buffer should normally be <code>pitch * scaledHeight</code> bytes in size,
+ where <code>scaledHeight</code> can be determined by calling <code>
+ scalingFactor.<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#getScaled(int)"><CODE>getScaled</CODE></A>(jpegHeight)
+ </code> with one of the scaling factors returned from <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getScalingFactors()"><CODE>TJ.getScalingFactors()</CODE></A> or by calling <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledHeight(int, int)"><CODE>getScaledHeight(int, int)</CODE></A>.<DD><CODE>desiredWidth</CODE> - desired width (in pixels) of the decompressed image.
+ If the desired image dimensions are smaller than the dimensions of the
+ JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG
+ decompressor to generate the largest possible image that will fit within
+ the desired dimensions.  Setting this to 0 is the same as setting it to
+ the width of the JPEG image (in other words, the width will not be
+ considered when determining the scaled image size.)<DD><CODE>pitch</CODE> - bytes per line of the destination image.  Normally, this
+ should be set to <code>scaledWidth * TJ.pixelSize(pixelFormat)</code> if
+ the decompressed image is unpadded, but you can use this to, for instance,
+ pad each line of the decompressed image to a 4-byte boundary.  NOTE:
+ <code>scaledWidth</code> can be determined by calling <code>
+ scalingFactor.<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#getScaled(int)"><CODE>getScaled</CODE></A>(jpegWidth)
+ </code> or by calling <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledWidth(int, int)"><CODE>getScaledWidth(int, int)</CODE></A>.  Setting this parameter to
+ 0 is the equivalent of setting it to <code>scaledWidth *
+ TJ.pixelSize(pixelFormat)</code>.<DD><CODE>desiredHeight</CODE> - desired height (in pixels) of the decompressed image.
+ If the desired image dimensions are smaller than the dimensions of the
+ JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG
+ decompressor to generate the largest possible image that will fit within
+ the desired dimensions.  Setting this to 0 is the same as setting it to
+ the height of the JPEG image (in other words, the height will not be
+ considered when determining the scaled image size.)<DD><CODE>pixelFormat</CODE> - pixel format of the decompressed image (one of
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.PF_*</CODE></A>)<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="decompress(int, int, int, int, int)"><!-- --></A><H3>
+decompress</H3>
+<PRE>
+public byte[] <B>decompress</B>(int&nbsp;desiredWidth,
+                         int&nbsp;pitch,
+                         int&nbsp;desiredHeight,
+                         int&nbsp;pixelFormat,
+                         int&nbsp;flags)
+                  throws java.lang.Exception</PRE>
+<DL>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and return a buffer containing the decompressed image.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>desiredWidth</CODE> - see
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)"><CODE>decompress(byte[], int, int, int, int, int)</CODE></A> for description<DD><CODE>pitch</CODE> - see
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)"><CODE>decompress(byte[], int, int, int, int, int)</CODE></A> for description<DD><CODE>desiredHeight</CODE> - see
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)"><CODE>decompress(byte[], int, int, int, int, int)</CODE></A> for description<DD><CODE>pixelFormat</CODE> - pixel format of the decompressed image (one of
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.PF_*</CODE></A>)<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a buffer containing the decompressed image
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="decompressToYUV(byte[], int)"><!-- --></A><H3>
+decompressToYUV</H3>
+<PRE>
+public void <B>decompressToYUV</B>(byte[]&nbsp;dstBuf,
+                            int&nbsp;flags)
+                     throws java.lang.Exception</PRE>
+<DL>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and output a YUV planar image to the given destination buffer.
+ This method performs JPEG decompression but leaves out the color
+ conversion step, so a planar YUV image is generated instead of an RGB
+ image.  The padding of the planes in this image is the same as the images
+ generated by <A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html#encodeYUV(byte[], int)"><CODE>TJCompressor.encodeYUV(byte[], int)</CODE></A>.  Note that, if
+ the width or height of the image is not an even multiple of the MCU block
+ size (see <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUWidth(int)"><CODE>TJ.getMCUWidth(int)</CODE></A> and <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUHeight(int)"><CODE>TJ.getMCUHeight(int)</CODE></A>), then an
+ intermediate buffer copy will be performed within TurboJPEG.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>dstBuf</CODE> - buffer which will receive the YUV planar image.  Use
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSizeYUV(int, int, int)"><CODE>TJ.bufSizeYUV(int, int, int)</CODE></A> to determine the appropriate size for this buffer
+ based on the image width, height, and level of chrominance subsampling.<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="decompressToYUV(int)"><!-- --></A><H3>
+decompressToYUV</H3>
+<PRE>
+public byte[] <B>decompressToYUV</B>(int&nbsp;flags)
+                       throws java.lang.Exception</PRE>
+<DL>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and return a buffer containing a YUV planar image.  See <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(byte[], int)"><CODE>decompressToYUV(byte[], int)</CODE></A> for more detail.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a buffer containing a YUV planar image
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="decompress(java.awt.image.BufferedImage, int)"><!-- --></A><H3>
+decompress</H3>
+<PRE>
+public void <B>decompress</B>(java.awt.image.BufferedImage&nbsp;dstImage,
+                       int&nbsp;flags)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and output a decompressed image to the given
+ <code>BufferedImage</code> instance.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>dstImage</CODE> - a <code>BufferedImage</code> instance which will receive
+ the decompressed image<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="decompress(int, int, int, int)"><!-- --></A><H3>
+decompress</H3>
+<PRE>
+public java.awt.image.BufferedImage <B>decompress</B>(int&nbsp;desiredWidth,
+                                               int&nbsp;desiredHeight,
+                                               int&nbsp;bufferedImageType,
+                                               int&nbsp;flags)
+                                        throws java.lang.Exception</PRE>
+<DL>
+<DD>Decompress the JPEG source image associated with this decompressor
+ instance and return a <code>BufferedImage</code> instance containing the
+ decompressed image.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>desiredWidth</CODE> - see
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)"><CODE>decompress(byte[], int, int, int, int, int)</CODE></A> for description<DD><CODE>desiredHeight</CODE> - see
+ <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)"><CODE>decompress(byte[], int, int, int, int, int)</CODE></A> for description<DD><CODE>bufferedImageType</CODE> - the image type of the newly-created
+ <code>BufferedImage</code> instance (for instance,
+ <code>BufferedImage.TYPE_INT_RGB</code>)<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>a <code>BufferedImage</code> instance containing the
+ decompressed image
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="close()"><!-- --></A><H3>
+close</H3>
+<PRE>
+public void <B>close</B>()
+           throws java.lang.Exception</PRE>
+<DL>
+<DD>Free the native structures associated with this decompressor instance.
+<P>
+<DD><DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="finalize()"><!-- --></A><H3>
+finalize</H3>
+<PRE>
+protected void <B>finalize</B>()
+                 throws java.lang.Throwable</PRE>
+<DL>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>finalize</CODE> in class <CODE>java.lang.Object</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Throwable</CODE></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJDecompressor.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJDecompressor.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html b/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html
new file mode 100644
index 0000000..867f418
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJScalingFactor.html
@@ -0,0 +1,358 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+TJScalingFactor
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="TJScalingFactor";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJScalingFactor.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJScalingFactor.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.libjpegturbo.turbojpeg</FONT>
+<BR>
+Class TJScalingFactor</H2>
+<PRE>
+java.lang.Object
+  <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><B>org.libjpegturbo.turbojpeg.TJScalingFactor</B>
+</PRE>
+<HR>
+<DL>
+<DT><PRE>public class <B>TJScalingFactor</B><DT>extends java.lang.Object</DL>
+</PRE>
+
+<P>
+Fractional scaling factor
+<P>
+
+<P>
+<HR>
+
+<P>
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#TJScalingFactor(int, int)">TJScalingFactor</A></B>(int&nbsp;num,
+                int&nbsp;denom)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#equals(org.libjpegturbo.turbojpeg.TJScalingFactor)">equals</A></B>(<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>&nbsp;other)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns true or false, depending on whether this instance and
+ <code>other</code> have the same numerator and denominator.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#getDenom()">getDenom</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns denominator</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#getNum()">getNum</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns numerator</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#getScaled(int)">getScaled</A></B>(int&nbsp;dimension)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the scaled value of <code>dimension</code>.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html#isOne()">isOne</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns true or false, depending on whether this instance is equal to
+ 1/1.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="TJScalingFactor(int, int)"><!-- --></A><H3>
+TJScalingFactor</H3>
+<PRE>
+public <B>TJScalingFactor</B>(int&nbsp;num,
+                       int&nbsp;denom)
+                throws java.lang.Exception</PRE>
+<DL>
+<DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="getNum()"><!-- --></A><H3>
+getNum</H3>
+<PRE>
+public int <B>getNum</B>()</PRE>
+<DL>
+<DD>Returns numerator
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>numerator</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDenom()"><!-- --></A><H3>
+getDenom</H3>
+<PRE>
+public int <B>getDenom</B>()</PRE>
+<DL>
+<DD>Returns denominator
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>denominator</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getScaled(int)"><!-- --></A><H3>
+getScaled</H3>
+<PRE>
+public int <B>getScaled</B>(int&nbsp;dimension)</PRE>
+<DL>
+<DD>Returns the scaled value of <code>dimension</code>.  This function
+ performs the integer equivalent of
+ <code>ceil(dimension * scalingFactor)</code>.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the scaled value of <code>dimension</code></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="equals(org.libjpegturbo.turbojpeg.TJScalingFactor)"><!-- --></A><H3>
+equals</H3>
+<PRE>
+public boolean <B>equals</B>(<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A>&nbsp;other)</PRE>
+<DL>
+<DD>Returns true or false, depending on whether this instance and
+ <code>other</code> have the same numerator and denominator.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true or false, depending on whether this instance and
+ <code>other</code> have the same numerator and denominator</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="isOne()"><!-- --></A><H3>
+isOne</H3>
+<PRE>
+public boolean <B>isOne</B>()</PRE>
+<DL>
+<DD>Returns true or false, depending on whether this instance is equal to
+ 1/1.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true or false, depending on whether this instance is equal to
+ 1/1</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJScalingFactor.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJScalingFactor.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html
new file mode 100644
index 0000000..fecccea
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransform.html
@@ -0,0 +1,719 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+TJTransform
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="TJTransform";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJTransform.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJTransform.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;<A HREF="#nested_classes_inherited_from_class_java.awt.geom.Rectangle2D">NESTED</A>&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.awt.Rectangle">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.libjpegturbo.turbojpeg</FONT>
+<BR>
+Class TJTransform</H2>
+<PRE>
+java.lang.Object
+  <IMG SRC="../../../resources/inherit.gif" ALT="extended by ">java.awt.geom.RectangularShape
+      <IMG SRC="../../../resources/inherit.gif" ALT="extended by ">java.awt.geom.Rectangle2D
+          <IMG SRC="../../../resources/inherit.gif" ALT="extended by ">java.awt.Rectangle
+              <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><B>org.libjpegturbo.turbojpeg.TJTransform</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.awt.Shape, java.io.Serializable, java.lang.Cloneable</DD>
+</DL>
+<HR>
+<DL>
+<DT><PRE>public class <B>TJTransform</B><DT>extends java.awt.Rectangle</DL>
+</PRE>
+
+<P>
+Lossless transform parameters
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../serialized-form.html#org.libjpegturbo.turbojpeg.TJTransform">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+<A NAME="nested_class_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Nested Class Summary</B></FONT></TH>
+</TR>
+</TABLE>
+&nbsp;<A NAME="nested_classes_inherited_from_class_java.awt.geom.Rectangle2D"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Nested classes/interfaces inherited from class java.awt.geom.Rectangle2D</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>java.awt.geom.Rectangle2D.Double, java.awt.geom.Rectangle2D.Float</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#NUMOP">NUMOP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The number of lossless transform operations</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#op">op</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transform operation (one of <code>OP_*</code>)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_HFLIP">OP_HFLIP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flip (mirror) image horizontally.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_NONE">OP_NONE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Do not transform the position of the image pixels.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT180">OP_ROT180</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rotate image 180 degrees.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT270">OP_ROT270</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rotate image counter-clockwise by 90 degrees.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_ROT90">OP_ROT90</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rotate image clockwise by 90 degrees.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_TRANSPOSE">OP_TRANSPOSE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transpose image (flip/mirror along upper left to lower right axis).</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_TRANSVERSE">OP_TRANSVERSE</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transverse transpose image (flip/mirror along upper right to lower left
+ axis).</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OP_VFLIP">OP_VFLIP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Flip (mirror) image vertically.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_CROP">OPT_CROP</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This option will enable lossless cropping.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_GRAY">OPT_GRAY</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This option will discard the color data in the input image and produce
+ a grayscale output image.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT">OPT_PERFECT</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This option will cause <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>TJTransformer.transform()</CODE></A> to throw an exception if the transform is not
+ perfect.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_TRIM">OPT_TRIM</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;This option will discard any partial MCU blocks that cannot be
+ transformed.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#options">options</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Transform options (bitwise OR of one or more of <code>OPT_*</code>)</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_java.awt.Rectangle"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Fields inherited from class java.awt.Rectangle</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>height, width, x, y</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_java.awt.geom.Rectangle2D"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Fields inherited from class java.awt.geom.Rectangle2D</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>OUT_BOTTOM, OUT_LEFT, OUT_RIGHT, OUT_TOP</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform()">TJTransform</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a new lossless transform instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform(int, int, int, int, int, int)">TJTransform</A></B>(int&nbsp;x,
+            int&nbsp;y,
+            int&nbsp;w,
+            int&nbsp;h,
+            int&nbsp;op,
+            int&nbsp;options)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a new lossless transform instance with the given parameters.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform(java.awt.Rectangle, int, int)">TJTransform</A></B>(java.awt.Rectangle&nbsp;r,
+            int&nbsp;op,
+            int&nbsp;options)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a new lossless transform instance with the given parameters.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TH>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.awt.Rectangle"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.awt.Rectangle</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>add, add, add, contains, contains, contains, contains, createIntersection, createUnion, equals, getBounds, getBounds2D, getHeight, getLocation, getSize, getWidth, getX, getY, grow, inside, intersection, intersects, isEmpty, move, outcode, reshape, resize, setBounds, setBounds, setLocation, setLocation, setRect, setSize, setSize, toString, translate, union</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.awt.geom.Rectangle2D"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.awt.geom.Rectangle2D</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>add, add, add, contains, contains, getPathIterator, getPathIterator, hashCode, intersect, intersects, intersectsLine, intersectsLine, outcode, setFrame, setRect, union</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.awt.geom.RectangularShape"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.awt.geom.RectangularShape</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, contains, contains, getCenterX, getCenterY, getFrame, getMaxX, getMaxY, getMinX, getMinY, intersects, setFrame, setFrame, setFrameFromCenter, setFrameFromCenter, setFrameFromDiagonal, setFrameFromDiagonal</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>finalize, getClass, notify, notifyAll, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.awt.Shape"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from interface java.awt.Shape</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>contains, contains, contains, contains, getPathIterator, getPathIterator, intersects, intersects</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="NUMOP"><!-- --></A><H3>
+NUMOP</H3>
+<PRE>
+public static final int <B>NUMOP</B></PRE>
+<DL>
+<DD>The number of lossless transform operations
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.NUMOP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_NONE"><!-- --></A><H3>
+OP_NONE</H3>
+<PRE>
+public static final int <B>OP_NONE</B></PRE>
+<DL>
+<DD>Do not transform the position of the image pixels.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_NONE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_HFLIP"><!-- --></A><H3>
+OP_HFLIP</H3>
+<PRE>
+public static final int <B>OP_HFLIP</B></PRE>
+<DL>
+<DD>Flip (mirror) image horizontally.  This transform is imperfect if there
+ are any partial MCU blocks on the right edge.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_HFLIP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_VFLIP"><!-- --></A><H3>
+OP_VFLIP</H3>
+<PRE>
+public static final int <B>OP_VFLIP</B></PRE>
+<DL>
+<DD>Flip (mirror) image vertically.  This transform is imperfect if there are
+ any partial MCU blocks on the bottom edge.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_VFLIP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_TRANSPOSE"><!-- --></A><H3>
+OP_TRANSPOSE</H3>
+<PRE>
+public static final int <B>OP_TRANSPOSE</B></PRE>
+<DL>
+<DD>Transpose image (flip/mirror along upper left to lower right axis).  This
+ transform is always perfect.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_TRANSPOSE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_TRANSVERSE"><!-- --></A><H3>
+OP_TRANSVERSE</H3>
+<PRE>
+public static final int <B>OP_TRANSVERSE</B></PRE>
+<DL>
+<DD>Transverse transpose image (flip/mirror along upper right to lower left
+ axis).  This transform is imperfect if there are any partial MCU blocks in
+ the image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_TRANSVERSE">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_ROT90"><!-- --></A><H3>
+OP_ROT90</H3>
+<PRE>
+public static final int <B>OP_ROT90</B></PRE>
+<DL>
+<DD>Rotate image clockwise by 90 degrees.  This transform is imperfect if
+ there are any partial MCU blocks on the bottom edge.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_ROT90">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_ROT180"><!-- --></A><H3>
+OP_ROT180</H3>
+<PRE>
+public static final int <B>OP_ROT180</B></PRE>
+<DL>
+<DD>Rotate image 180 degrees.  This transform is imperfect if there are any
+ partial MCU blocks in the image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_ROT180">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OP_ROT270"><!-- --></A><H3>
+OP_ROT270</H3>
+<PRE>
+public static final int <B>OP_ROT270</B></PRE>
+<DL>
+<DD>Rotate image counter-clockwise by 90 degrees.  This transform is imperfect
+ if there are any partial MCU blocks on the right edge.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#OPT_PERFECT"><CODE>OPT_PERFECT</CODE></A>, 
+<A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OP_ROT270">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OPT_PERFECT"><!-- --></A><H3>
+OPT_PERFECT</H3>
+<PRE>
+public static final int <B>OPT_PERFECT</B></PRE>
+<DL>
+<DD>This option will cause <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>TJTransformer.transform()</CODE></A> to throw an exception if the transform is not
+ perfect.  Lossless transforms operate on MCU blocks, whose size depends on
+ the level of chrominance subsampling used.  If the image's width or height
+ is not evenly divisible by the MCU block size (see <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUWidth(int)"><CODE>TJ.getMCUWidth(int)</CODE></A>
+ and <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUHeight(int)"><CODE>TJ.getMCUHeight(int)</CODE></A>), then there will be partial MCU blocks on the
+ right and/or bottom edges.   It is not possible to move these partial MCU
+ blocks to the top or left of the image, so any transform that would
+ require that is "imperfect."  If this option is not specified, then any
+ 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.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_PERFECT">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OPT_TRIM"><!-- --></A><H3>
+OPT_TRIM</H3>
+<PRE>
+public static final int <B>OPT_TRIM</B></PRE>
+<DL>
+<DD>This option will discard any partial MCU blocks that cannot be
+ transformed.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_TRIM">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OPT_CROP"><!-- --></A><H3>
+OPT_CROP</H3>
+<PRE>
+public static final int <B>OPT_CROP</B></PRE>
+<DL>
+<DD>This option will enable lossless cropping.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_CROP">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="OPT_GRAY"><!-- --></A><H3>
+OPT_GRAY</H3>
+<PRE>
+public static final int <B>OPT_GRAY</B></PRE>
+<DL>
+<DD>This option will discard the color data in the input image and produce
+ a grayscale output image.
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="../../../constant-values.html#org.libjpegturbo.turbojpeg.TJTransform.OPT_GRAY">Constant Field Values</A></DL>
+</DL>
+<HR>
+
+<A NAME="op"><!-- --></A><H3>
+op</H3>
+<PRE>
+public int <B>op</B></PRE>
+<DL>
+<DD>Transform operation (one of <code>OP_*</code>)
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="options"><!-- --></A><H3>
+options</H3>
+<PRE>
+public int <B>options</B></PRE>
+<DL>
+<DD>Transform options (bitwise OR of one or more of <code>OPT_*</code>)
+<P>
+<DL>
+</DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="TJTransform()"><!-- --></A><H3>
+TJTransform</H3>
+<PRE>
+public <B>TJTransform</B>()</PRE>
+<DL>
+<DD>Create a new lossless transform instance.
+<P>
+</DL>
+<HR>
+
+<A NAME="TJTransform(int, int, int, int, int, int)"><!-- --></A><H3>
+TJTransform</H3>
+<PRE>
+public <B>TJTransform</B>(int&nbsp;x,
+                   int&nbsp;y,
+                   int&nbsp;w,
+                   int&nbsp;h,
+                   int&nbsp;op,
+                   int&nbsp;options)
+            throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a new lossless transform instance with the given parameters.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>x</CODE> - the left boundary of the cropping region.  This must be evenly
+ divisible by the MCU block width (see <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUWidth(int)"><CODE>TJ.getMCUWidth(int)</CODE></A>)<DD><CODE>y</CODE> - the upper boundary of the cropping region.  This must be evenly
+ divisible by the MCU block height (see <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#getMCUHeight(int)"><CODE>TJ.getMCUHeight(int)</CODE></A>)<DD><CODE>w</CODE> - the width of the cropping region.  Setting this to 0 is the
+ equivalent of setting it to the width of the source JPEG image - x.<DD><CODE>h</CODE> - the height of the cropping region.  Setting this to 0 is the
+ equivalent of setting it to the height of the source JPEG image - y.<DD><CODE>op</CODE> - one of the transform operations (<code>OP_*</code>)<DD><CODE>options</CODE> - the bitwise OR of one or more of the transform options
+ (<code>OPT_*</code>)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<HR>
+
+<A NAME="TJTransform(java.awt.Rectangle, int, int)"><!-- --></A><H3>
+TJTransform</H3>
+<PRE>
+public <B>TJTransform</B>(java.awt.Rectangle&nbsp;r,
+                   int&nbsp;op,
+                   int&nbsp;options)
+            throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a new lossless transform instance with the given parameters.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>r</CODE> - a <code>Rectangle</code> instance which specifies the cropping
+ region.  See <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html#TJTransform(int, int, int, int, int, int)"><CODE>TJTransform(int, int, int, int, int, int)</CODE></A> for more
+ detail.<DD><CODE>op</CODE> - one of the transform operations (<code>OP_*</code>)<DD><CODE>options</CODE> - the bitwise OR of one or more of the transform options
+ (<code>OPT_*</code>)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJTransform.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJTransform.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;<A HREF="#nested_classes_inherited_from_class_java.awt.geom.Rectangle2D">NESTED</A>&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#methods_inherited_from_class_java.awt.Rectangle">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;METHOD</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html
new file mode 100644
index 0000000..d3da485
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/TJTransformer.html
@@ -0,0 +1,427 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+TJTransformer
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="TJTransformer";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;NEXT CLASS</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJTransformer.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJTransformer.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_org.libjpegturbo.turbojpeg.TJDecompressor">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+<FONT SIZE="-1">
+org.libjpegturbo.turbojpeg</FONT>
+<BR>
+Class TJTransformer</H2>
+<PRE>
+java.lang.Object
+  <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">org.libjpegturbo.turbojpeg.TJDecompressor</A>
+      <IMG SRC="../../../resources/inherit.gif" ALT="extended by "><B>org.libjpegturbo.turbojpeg.TJTransformer</B>
+</PRE>
+<HR>
+<DL>
+<DT><PRE>public class <B>TJTransformer</B><DT>extends <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A></DL>
+</PRE>
+
+<P>
+TurboJPEG lossless transformer
+<P>
+
+<P>
+<HR>
+
+<P>
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TH>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_org.libjpegturbo.turbojpeg.TJDecompressor"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Fields inherited from class org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A></B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#handle">handle</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegBuf">jpegBuf</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegBufSize">jpegBufSize</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegHeight">jpegHeight</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegSubsamp">jpegSubsamp</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#jpegWidth">jpegWidth</A></CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#TJTransformer()">TJTransformer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG lossless transformer instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#TJTransformer(byte[])">TJTransformer</A></B>(byte[]&nbsp;jpegImage)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG lossless transformer instance and associate the JPEG
+ image stored in <code>jpegImage</code> with the newly-created instance.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#TJTransformer(byte[], int)">TJTransformer</A></B>(byte[]&nbsp;jpegImage,
+              int&nbsp;imageSize)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Create a TurboJPEG lossless transformer instance and associate the JPEG
+ image of length <code>imageSize</code> bytes stored in
+ <code>jpegImage</code> with the newly-created instance.</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#getTransformedSizes()">getTransformedSizes</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns an array containing the sizes of the transformed JPEG images from
+ the most recent call to <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>transform()</CODE></A>.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)">transform</A></B>(byte[][]&nbsp;dstBufs,
+          <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>[]&nbsp;transforms,
+          int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Losslessly transform the JPEG image associated with this transformer
+ instance into one or more JPEG images stored in the given destination
+ buffers.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(org.libjpegturbo.turbojpeg.TJTransform[], int)">transform</A></B>(<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>[]&nbsp;transforms,
+          int&nbsp;flags)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Losslessly transform the JPEG image associated with this transformer
+ instance and return an array of <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJDecompressor</CODE></A> instances, each of
+ which has a transformed JPEG image associated with it.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_org.libjpegturbo.turbojpeg.TJDecompressor"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A></B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#close()">close</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(java.awt.image.BufferedImage, int)">decompress</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(byte[], int, int, int, int, int)">decompress</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(int, int, int, int)">decompress</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompress(int, int, int, int, int)">decompress</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(byte[], int)">decompressToYUV</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#decompressToYUV(int)">decompressToYUV</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#finalize()">finalize</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getHeight()">getHeight</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getJPEGBuf()">getJPEGBuf</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getJPEGSize()">getJPEGSize</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledHeight(int, int)">getScaledHeight</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getScaledWidth(int, int)">getScaledWidth</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getSubsamp()">getSubsamp</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#getWidth()">getWidth</A>, <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html#setJPEGImage(byte[], int)">setJPEGImage</A></CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left"><B>Methods inherited from class java.lang.Object</B></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="TJTransformer()"><!-- --></A><H3>
+TJTransformer</H3>
+<PRE>
+public <B>TJTransformer</B>()
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG lossless transformer instance.
+<P>
+<DL>
+
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<HR>
+
+<A NAME="TJTransformer(byte[])"><!-- --></A><H3>
+TJTransformer</H3>
+<PRE>
+public <B>TJTransformer</B>(byte[]&nbsp;jpegImage)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG lossless transformer instance and associate the JPEG
+ image stored in <code>jpegImage</code> with the newly-created instance.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>jpegImage</CODE> - JPEG image buffer (size of the JPEG image is assumed to
+ be the length of the array)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+<HR>
+
+<A NAME="TJTransformer(byte[], int)"><!-- --></A><H3>
+TJTransformer</H3>
+<PRE>
+public <B>TJTransformer</B>(byte[]&nbsp;jpegImage,
+                     int&nbsp;imageSize)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Create a TurboJPEG lossless transformer instance and associate the JPEG
+ image of length <code>imageSize</code> bytes stored in
+ <code>jpegImage</code> with the newly-created instance.
+<P>
+<DL>
+<DT><B>Parameters:</B><DD><CODE>jpegImage</CODE> - JPEG image buffer<DD><CODE>imageSize</CODE> - size of the JPEG image (in bytes)
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TH>
+</TR>
+</TABLE>
+
+<A NAME="transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><!-- --></A><H3>
+transform</H3>
+<PRE>
+public void <B>transform</B>(byte[][]&nbsp;dstBufs,
+                      <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>[]&nbsp;transforms,
+                      int&nbsp;flags)
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Losslessly transform the JPEG image associated with this transformer
+ instance into one or more JPEG images stored in the given destination
+ buffers.  Lossless transforms work by moving the raw coefficients from one
+ JPEG image structure to another without altering the values of the
+ coefficients.  While this is typically faster than decompressing the
+ image, transforming it, and re-compressing it, lossless transforms are not
+ free.  Each lossless transform requires reading and Huffman decoding all
+ of the coefficients in the source image, regardless of the size of the
+ destination image.  Thus, this method provides a means of generating
+ multiple transformed images from the same source or of applying multiple
+ transformations simultaneously, in order to eliminate the need to read the
+ source coefficients multiple times.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>dstBufs</CODE> - an array of image buffers.  <code>dstbufs[i]</code> will
+ receive a JPEG image that has been transformed using the parameters in
+ <code>transforms[i]</code>.  Use <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html#bufSize(int, int)"><CODE>TJ.bufSize(int, int)</CODE></A> to determine the
+ maximum size for each buffer based on the cropped width and height.<DD><CODE>transforms</CODE> - an array of <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJTransform</CODE></A> instances, each of
+ which specifies the transform parameters and/or cropping region for the
+ corresponding transformed output image<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="transform(org.libjpegturbo.turbojpeg.TJTransform[], int)"><!-- --></A><H3>
+transform</H3>
+<PRE>
+public <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A>[] <B>transform</B>(<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A>[]&nbsp;transforms,
+                                  int&nbsp;flags)
+                           throws java.lang.Exception</PRE>
+<DL>
+<DD>Losslessly transform the JPEG image associated with this transformer
+ instance and return an array of <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJDecompressor</CODE></A> instances, each of
+ which has a transformed JPEG image associated with it.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>transforms</CODE> - an array of <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJTransform</CODE></A> instances, each of
+ which specifies the transform parameters and/or cropping region for the
+ corresponding transformed output image<DD><CODE>flags</CODE> - the bitwise OR of one or more of <A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJ.FLAG_*</CODE></A>
+<DT><B>Returns:</B><DD>an array of <A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><CODE>TJDecompressor</CODE></A> instances, each of
+ which has a transformed JPEG image associated with it
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getTransformedSizes()"><!-- --></A><H3>
+getTransformedSizes</H3>
+<PRE>
+public int[] <B>getTransformedSizes</B>()
+                          throws java.lang.Exception</PRE>
+<DL>
+<DD>Returns an array containing the sizes of the transformed JPEG images from
+ the most recent call to <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>transform()</CODE></A>.
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an array containing the sizes of the transformed JPEG images from
+ the most recent call to <A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html#transform(byte[][], org.libjpegturbo.turbojpeg.TJTransform[], int)"><CODE>transform()</CODE></A>
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;NEXT CLASS</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/TJTransformer.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="TJTransformer.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_org.libjpegturbo.turbojpeg.TJDecompressor">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/package-frame.html b/java/doc/org/libjpegturbo/turbojpeg/package-frame.html
new file mode 100644
index 0000000..4338f9b
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/package-frame.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+org.libjpegturbo.turbojpeg
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+
+</HEAD>
+
+<BODY BGCOLOR="white">
+<FONT size="+1" CLASS="FrameTitleFont">
+<A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html" target="classFrame">org.libjpegturbo.turbojpeg</A></FONT>
+<TABLE BORDER="0" WIDTH="100%" SUMMARY="">
+<TR>
+<TD NOWRAP><FONT size="+1" CLASS="FrameHeadingFont">
+Classes</FONT>&nbsp;
+<FONT CLASS="FrameItemFont">
+<BR>
+<A HREF="TJ.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJ</A>
+<BR>
+<A HREF="TJCompressor.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJCompressor</A>
+<BR>
+<A HREF="TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJDecompressor</A>
+<BR>
+<A HREF="TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJScalingFactor</A>
+<BR>
+<A HREF="TJTransform.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJTransform</A>
+<BR>
+<A HREF="TJTransformer.html" title="class in org.libjpegturbo.turbojpeg" target="classFrame">TJTransformer</A></FONT></TD>
+</TR>
+</TABLE>
+
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/package-summary.html b/java/doc/org/libjpegturbo/turbojpeg/package-summary.html
new file mode 100644
index 0000000..733d88d
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/package-summary.html
@@ -0,0 +1,173 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+org.libjpegturbo.turbojpeg
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="org.libjpegturbo.turbojpeg";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV PACKAGE&nbsp;
+&nbsp;NEXT PACKAGE</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/package-summary.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<H2>
+Package org.libjpegturbo.turbojpeg
+</H2>
+
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Class Summary</B></FONT></TH>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD WIDTH="15%"><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg">TJ</A></B></TD>
+<TD>TurboJPEG utility class (cannot be instantiated)</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD WIDTH="15%"><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg">TJCompressor</A></B></TD>
+<TD>TurboJPEG compressor</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD WIDTH="15%"><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg">TJDecompressor</A></B></TD>
+<TD>TurboJPEG decompressor</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD WIDTH="15%"><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg">TJScalingFactor</A></B></TD>
+<TD>Fractional scaling factor</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD WIDTH="15%"><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">TJTransform</A></B></TD>
+<TD>Lossless transform parameters</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD WIDTH="15%"><B><A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg">TJTransformer</A></B></TD>
+<TD>TurboJPEG lossless transformer</TD>
+</TR>
+</TABLE>
+&nbsp;
+
+<P>
+<DL>
+</DL>
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV PACKAGE&nbsp;
+&nbsp;NEXT PACKAGE</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/package-summary.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="package-summary.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/org/libjpegturbo/turbojpeg/package-tree.html b/java/doc/org/libjpegturbo/turbojpeg/package-tree.html
new file mode 100644
index 0000000..ee04a10
--- /dev/null
+++ b/java/doc/org/libjpegturbo/turbojpeg/package-tree.html
@@ -0,0 +1,156 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+org.libjpegturbo.turbojpeg Class Hierarchy
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="../../../stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="org.libjpegturbo.turbojpeg Class Hierarchy";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/package-tree.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="package-tree.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<CENTER>
+<H2>
+Hierarchy For Package org.libjpegturbo.turbojpeg
+</H2>
+</CENTER>
+<H2>
+Class Hierarchy
+</H2>
+<UL>
+<LI TYPE="circle">java.lang.Object<UL>
+<LI TYPE="circle">java.awt.geom.RectangularShape (implements java.lang.Cloneable, java.awt.Shape)
+<UL>
+<LI TYPE="circle">java.awt.geom.Rectangle2D<UL>
+<LI TYPE="circle">java.awt.Rectangle (implements java.io.Serializable, java.awt.Shape)
+<UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>TJTransform</B></A></UL>
+</UL>
+</UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><B>TJ</B></A><LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJCompressor</B></A><LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJDecompressor</B></A><UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg"><B>TJTransformer</B></A></UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="../../../org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJScalingFactor</B></A></UL>
+</UL>
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="../../../help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="../../../index.html?org/libjpegturbo/turbojpeg/package-tree.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="package-tree.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="../../../allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/overview-tree.html b/java/doc/overview-tree.html
new file mode 100644
index 0000000..8a19a88
--- /dev/null
+++ b/java/doc/overview-tree.html
@@ -0,0 +1,158 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+Class Hierarchy
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="Class Hierarchy";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?overview-tree.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="overview-tree.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<CENTER>
+<H2>
+Hierarchy For All Packages</H2>
+</CENTER>
+<DL>
+<DT><B>Package Hierarchies:</B><DD><A HREF="org/libjpegturbo/turbojpeg/package-tree.html">org.libjpegturbo.turbojpeg</A></DL>
+<HR>
+<H2>
+Class Hierarchy
+</H2>
+<UL>
+<LI TYPE="circle">java.lang.Object<UL>
+<LI TYPE="circle">java.awt.geom.RectangularShape (implements java.lang.Cloneable, java.awt.Shape)
+<UL>
+<LI TYPE="circle">java.awt.geom.Rectangle2D<UL>
+<LI TYPE="circle">java.awt.Rectangle (implements java.io.Serializable, java.awt.Shape)
+<UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg"><B>TJTransform</B></A></UL>
+</UL>
+</UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJ.html" title="class in org.libjpegturbo.turbojpeg"><B>TJ</B></A><LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJCompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJCompressor</B></A><LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJDecompressor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJDecompressor</B></A><UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJTransformer.html" title="class in org.libjpegturbo.turbojpeg"><B>TJTransformer</B></A></UL>
+<LI TYPE="circle">org.libjpegturbo.turbojpeg.<A HREF="org/libjpegturbo/turbojpeg/TJScalingFactor.html" title="class in org.libjpegturbo.turbojpeg"><B>TJScalingFactor</B></A></UL>
+</UL>
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?overview-tree.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="overview-tree.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/package-list b/java/doc/package-list
new file mode 100644
index 0000000..918d936
--- /dev/null
+++ b/java/doc/package-list
@@ -0,0 +1 @@
+org.libjpegturbo.turbojpeg
diff --git a/java/doc/resources/inherit.gif b/java/doc/resources/inherit.gif
new file mode 100644
index 0000000..c814867
--- /dev/null
+++ b/java/doc/resources/inherit.gif
Binary files differ
diff --git a/java/doc/serialized-form.html b/java/doc/serialized-form.html
new file mode 100644
index 0000000..90d6ff8
--- /dev/null
+++ b/java/doc/serialized-form.html
@@ -0,0 +1,191 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc (build 1.6.0_24) on Fri Apr 01 20:49:05 CDT 2011 -->
+<TITLE>
+Serialized Form
+</TITLE>
+
+<META NAME="date" CONTENT="2011-04-01">
+
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+
+<SCRIPT type="text/javascript">
+function windowTitle()
+{
+    if (location.href.indexOf('is-external=true') == -1) {
+        parent.document.title="Serialized Form";
+    }
+}
+</SCRIPT>
+<NOSCRIPT>
+</NOSCRIPT>
+
+</HEAD>
+
+<BODY BGCOLOR="white" onload="windowTitle();">
+<HR>
+
+
+<!-- ========= START OF TOP NAVBAR ======= -->
+<A NAME="navbar_top"><!-- --></A>
+<A HREF="#skip-navbar_top" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?serialized-form.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="serialized-form.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_top"></A>
+<!-- ========= END OF TOP NAVBAR ========= -->
+
+<HR>
+<CENTER>
+<H1>
+Serialized Form</H1>
+</CENTER>
+<HR SIZE="4" NOSHADE>
+
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="center"><FONT SIZE="+2">
+<B>Package</B> <B>org.libjpegturbo.turbojpeg</B></FONT></TH>
+</TR>
+</TABLE>
+
+<P>
+<A NAME="org.libjpegturbo.turbojpeg.TJTransform"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TH ALIGN="left" COLSPAN="2"><FONT SIZE="+2">
+<B>Class <A HREF="org/libjpegturbo/turbojpeg/TJTransform.html" title="class in org.libjpegturbo.turbojpeg">org.libjpegturbo.turbojpeg.TJTransform</A> extends java.awt.Rectangle implements Serializable</B></FONT></TH>
+</TR>
+</TABLE>
+
+<P>
+<B>serialVersionUID:&nbsp;</B>-127367705761430371L
+
+<P>
+<A NAME="serializedForm"><!-- --></A>
+<TABLE BORDER="1" WIDTH="100%" CELLPADDING="3" CELLSPACING="0" SUMMARY="">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TH ALIGN="left" COLSPAN="1"><FONT SIZE="+2">
+<B>Serialized Fields</B></FONT></TH>
+</TR>
+</TABLE>
+
+<H3>
+op</H3>
+<PRE>
+int <B>op</B></PRE>
+<DL>
+<DD>Transform operation (one of <code>OP_*</code>)
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+<H3>
+options</H3>
+<PRE>
+int <B>options</B></PRE>
+<DL>
+<DD>Transform options (bitwise OR of one or more of <code>OPT_*</code>)
+<P>
+<DL>
+</DL>
+</DL>
+
+<P>
+<HR>
+
+
+<!-- ======= START OF BOTTOM NAVBAR ====== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<A HREF="#skip-navbar_bottom" title="Skip navigation links"></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0" SUMMARY="">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3" SUMMARY="">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-summary.html"><FONT CLASS="NavBarFont1"><B>Package</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="org/libjpegturbo/turbojpeg/package-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html?serialized-form.html" target="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="serialized-form.html" target="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;<SCRIPT type="text/javascript">
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html"><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+  <A HREF="allclasses-noframe.html"><B>All Classes</B></A>
+</NOSCRIPT>
+
+
+</FONT></TD>
+</TR>
+</TABLE>
+<A NAME="skip-navbar_bottom"></A>
+<!-- ======== END OF BOTTOM NAVBAR ======= -->
+
+<HR>
+
+</BODY>
+</HTML>
diff --git a/java/doc/stylesheet.css b/java/doc/stylesheet.css
new file mode 100644
index 0000000..6ea9e51
--- /dev/null
+++ b/java/doc/stylesheet.css
@@ -0,0 +1,29 @@
+/* Javadoc style sheet */
+
+/* Define colors, fonts and other style attributes here to override the defaults */
+
+/* Page background color */
+body { background-color: #FFFFFF; color:#000000 }
+
+/* Headings */
+h1 { font-size: 145% }
+
+/* Table colors */
+.TableHeadingColor     { background: #CCCCFF; color:#000000 } /* Dark mauve */
+.TableSubHeadingColor  { background: #EEEEFF; color:#000000 } /* Light mauve */
+.TableRowColor         { background: #FFFFFF; color:#000000 } /* White */
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont   { font-size: 100%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+.FrameHeadingFont { font-size:  90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+.FrameItemFont    { font-size:  90%; font-family: Helvetica, Arial, sans-serif; color:#000000 }
+
+/* Navigation bar fonts and colors */
+.NavBarCell1    { background-color:#EEEEFF; color:#000000} /* Light mauve */
+.NavBarCell1Rev { background-color:#00008B; color:#FFFFFF} /* Dark Blue */
+.NavBarFont1    { font-family: Arial, Helvetica, sans-serif; color:#000000;color:#000000;}
+.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;color:#FFFFFF;}
+
+.NavBarCell2    { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
+.NavBarCell3    { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF; color:#000000}
+
diff --git a/java/org/libjpegturbo/turbojpeg/TJ.java b/java/org/libjpegturbo/turbojpeg/TJ.java
new file mode 100644
index 0000000..3941b53
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJ.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+/**
+ * TurboJPEG utility class (cannot be instantiated)
+ */
+final public class TJ {
+
+
+  /**
+   * The number of chrominance subsampling options
+   */
+  final public static int NUMSAMP   = 5;
+  /**
+   * 4:4:4 chrominance subsampling (no chrominance subsampling).  The JPEG
+   * or YUV image will contain one chrominance component for every pixel in the
+   * source image.
+   */
+  final public static int SAMP_444  = 0;
+  /**
+   * 4:2:2 chrominance subsampling.  The JPEG or YUV image will contain one
+   * chrominance component for every 2x1 block of pixels in the source image.
+   */
+  final public static int SAMP_422  = 1;
+  /**
+   * 4:2:0 chrominance subsampling.  The JPEG or YUV image will contain one
+   * chrominance component for every 2x2 block of pixels in the source image.
+   */
+  final public static int SAMP_420  = 2;
+  /**
+   * Grayscale.  The JPEG or YUV image will contain no chrominance components.
+   */
+  final public static int SAMP_GRAY = 3;
+  /**
+   * 4:4:0 chrominance subsampling.  The JPEG or YUV image will contain one
+   * chrominance component for every 1x2 block of pixels in the source image.
+   */
+  final public static int SAMP_440  = 4;
+
+
+  /**
+   * Returns the MCU block width for the given level of chrominance
+   * subsampling.
+   *
+   * @param subsamp the level of chrominance subsampling (one of
+   * <code>SAMP_*</code>)
+   *
+   * @return the MCU block width for the given level of chrominance subsampling
+   */
+  public static int getMCUWidth(int subsamp) throws Exception {
+    if(subsamp < 0 || subsamp >= NUMSAMP)
+      throw new Exception("Invalid subsampling type");
+    return mcuWidth[subsamp];
+  }
+
+  final private static int mcuWidth[] = {
+    8, 16, 16, 8, 8
+  };
+
+
+  /**
+   * Returns the MCU block height for the given level of chrominance
+   * subsampling.
+   *
+   * @param subsamp the level of chrominance subsampling (one of
+   * <code>SAMP_*</code>)
+   *
+   * @return the MCU block height for the given level of chrominance
+   * subsampling
+   */
+  public static int getMCUHeight(int subsamp) throws Exception {
+    if(subsamp < 0 || subsamp >= NUMSAMP)
+      throw new Exception("Invalid subsampling type");
+    return mcuHeight[subsamp];
+  }
+
+  final private static int mcuHeight[] = {
+    8, 8, 16, 8, 16
+  };
+
+
+  /**
+   * The number of pixel formats
+   */
+  final public static int NUMPF    = 7;
+  /**
+   * RGB pixel format.  The red, green, and blue components in the image are
+   * stored in 3-byte pixels in the order R, G, B from lowest to highest byte
+   * address within each pixel.
+   */
+  final public static int PF_RGB  = 0;
+  /**
+   * BGR pixel format.  The red, green, and blue components in the image are
+   * stored in 3-byte pixels in the order B, G, R from lowest to highest byte
+   * address within each pixel.
+   */
+  final public static int PF_BGR  = 1;
+  /**
+   * RGBX pixel format.  The red, green, and blue components in the image are
+   * stored in 4-byte pixels in the order R, G, B from lowest to highest byte
+   * address within each pixel.
+   */
+  final public static int PF_RGBX = 2;
+  /**
+   * BGRX pixel format.  The red, green, and blue components in the image are
+   * stored in 4-byte pixels in the order B, G, R from lowest to highest byte
+   * address within each pixel.
+   */
+  final public static int PF_BGRX = 3;
+  /**
+   * XBGR pixel format.  The red, green, and blue components in the image are
+   * stored in 4-byte pixels in the order R, G, B from highest to lowest byte
+   * address within each pixel.
+   */
+  final public static int PF_XBGR = 4;
+  /**
+   * XRGB pixel format.  The red, green, and blue components in the image are
+   * stored in 4-byte pixels in the order B, G, R from highest to lowest byte
+   * address within each pixel.
+   */
+  final public static int PF_XRGB = 5;
+  /**
+   * Grayscale pixel format.  Each 1-byte pixel represents a luminance
+   * (brightness) level from 0 to 255.
+   */
+  final public static int PF_GRAY = 6;
+
+
+  /**
+   * Returns the pixel size (in bytes) of the given pixel format.
+   *
+   * @param pixelFormat the pixel format (one of <code>PF_*</code>)
+   *
+   * @return the pixel size (in bytes) of the given pixel format
+   */
+  public static int getPixelSize(int pixelFormat) throws Exception {
+    if(pixelFormat < 0 || pixelFormat >= NUMPF)
+      throw new Exception("Invalid pixel format");
+    return pixelSize[pixelFormat];
+  }
+
+  final private static int pixelSize[] = {
+    3, 3, 4, 4, 4, 4, 1
+  };
+
+
+  /**
+   * For the given pixel format, returns the number of bytes that the red
+   * component is offset from the start of the pixel.  For instance, if a pixel
+   * of format <code>TJ.PF_BGRX</code> is stored in <code>char pixel[]</code>,
+   * then the red component will be
+   * <code>pixel[TJ.getRedOffset(TJ.PF_BGRX)]</code>.
+   *
+   * @param pixelFormat the pixel format (one of <code>PF_*</code>)
+   *
+   * @return the red offset for the given pixel format
+   */
+  public static int getRedOffset(int pixelFormat) throws Exception {
+    if(pixelFormat < 0 || pixelFormat >= NUMPF)
+      throw new Exception("Invalid pixel format");
+    return redOffset[pixelFormat];
+  }
+
+  final private static int redOffset[] = {
+    0, 2, 0, 2, 3, 1, 0
+  };
+
+
+  /**
+   * For the given pixel format, returns the number of bytes that the green
+   * component is offset from the start of the pixel.  For instance, if a pixel
+   * of format <code>TJ.PF_BGRX</code> is stored in <code>char pixel[]</code>,
+   * then the green component will be
+   * <code>pixel[TJ.getGreenOffset(TJ.PF_BGRX)]</code>.
+   *
+   * @param pixelFormat the pixel format (one of <code>PF_*</code>)
+   *
+   * @return the green offset for the given pixel format
+   */
+  public static int getGreenOffset(int pixelFormat) throws Exception {
+    if(pixelFormat < 0 || pixelFormat >= NUMPF)
+      throw new Exception("Invalid pixel format");
+    return greenOffset[pixelFormat];
+  }
+
+  final private static int greenOffset[] = {
+    1, 1, 1, 1, 2, 2, 0
+  };
+
+
+  /**
+   * For the given pixel format, returns the number of bytes that the blue
+   * component is offset from the start of the pixel.  For instance, if a pixel
+   * of format <code>TJ.PF_BGRX</code> is stored in <code>char pixel[]</code>,
+   * then the blue component will be
+   * <code>pixel[TJ.getBlueOffset(TJ.PF_BGRX)]</code>.
+   *
+   * @param pixelFormat the pixel format (one of <code>PF_*</code>)
+   *
+   * @return the blue offset for the given pixel format
+   */
+  public static int getBlueOffset(int pixelFormat) throws Exception {
+    if(pixelFormat < 0 || pixelFormat >= NUMPF)
+      throw new Exception("Invalid pixel format");
+    return blueOffset[pixelFormat];
+  }
+
+  final private static int blueOffset[] = {
+    2, 0, 2, 0, 1, 3, 0
+  };
+
+
+  /**
+   * The uncompressed source/destination image is stored in bottom-up (Windows,
+   * OpenGL) order, not top-down (X11) order.
+   */
+  final public static int FLAG_BOTTOMUP     = 2;
+  /**
+   * Turn off CPU auto-detection and force TurboJPEG to use MMX code
+   * (IPP and 32-bit libjpeg-turbo versions only.)
+   */
+  final public static int FLAG_FORCEMMX     = 8;
+  /**
+   * Turn off CPU auto-detection and force TurboJPEG to use SSE code
+   * (32-bit IPP and 32-bit libjpeg-turbo versions only.)
+   */
+  final public static int FLAG_FORCESSE     = 16;
+  /**
+   * Turn off CPU auto-detection and force TurboJPEG to use SSE2 code
+   * (32-bit IPP and 32-bit libjpeg-turbo versions only.)
+   */
+  final public static int FLAG_FORCESSE2    = 32;
+  /**
+   * Turn off CPU auto-detection and force TurboJPEG to use SSE3 code
+   *(64-bit IPP version only.)
+   */
+  final public static int FLAG_FORCESSE3    = 128;
+  /**
+   * Use fast, inaccurate chrominance upsampling routines in the JPEG
+   * decompressor (libjpeg and libjpeg-turbo versions only.)
+   */
+  final public static int FLAG_FASTUPSAMPLE = 256;
+
+
+  /**
+   * Returns the maximum size of the buffer (in bytes) required to hold a JPEG
+   * image with the given width and height.
+   *
+   * @param width the width (in pixels) of the JPEG image
+   *
+   * @param height the height (in pixels) of the JPEG image
+   *
+   * @return the maximum size of the buffer (in bytes) required to hold a JPEG
+   * image with the given width and height 
+   */
+  public native static int bufSize(int width, int height)
+    throws Exception;
+
+  /**
+   * Returns the size of the buffer (in bytes) required to hold a YUV planar
+   * image with the given width, height, and level of chrominance subsampling.
+   *
+   * @param width the width (in pixels) of the YUV image
+   *
+   * @param height the height (in pixels) of the YUV image
+   *
+   * @param subsamp the level of chrominance subsampling used in the YUV
+   * image
+   *
+   * @return the size of the buffer (in bytes) required to hold a YUV planar
+   * image with the given width, height, and level of chrominance subsampling
+   */
+  public native static int bufSizeYUV(int width, int height,
+    int subsamp)
+    throws Exception;
+
+  /**
+   * Returns a list of fractional scaling factors that the JPEG decompressor in
+   * this implementation of TurboJPEG supports.
+   *
+   * @return a list of fractional scaling factors that the JPEG decompressor in
+   * this implementation of TurboJPEG supports
+   */
+  public native static TJScalingFactor[] getScalingFactors()
+    throws Exception;
+
+  static {
+    TJLoader.load();
+  }
+};
diff --git a/java/org/libjpegturbo/turbojpeg/TJCompressor.java b/java/org/libjpegturbo/turbojpeg/TJCompressor.java
new file mode 100644
index 0000000..de32227
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJCompressor.java
@@ -0,0 +1,460 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+import java.awt.image.*;
+import java.nio.*;
+
+/**
+ * TurboJPEG compressor
+ */
+public class TJCompressor {
+
+  private final static String NO_ASSOC_ERROR =
+    "No source image is associated with this instance";
+
+  /**
+   * Create a TurboJPEG compressor instance.
+   */
+  public TJCompressor() throws Exception {
+    init();
+  }
+
+  /**
+   * Create a TurboJPEG compressor instance and associate the uncompressed
+   * source image stored in <code>srcImage</code> with the newly-created
+   * instance.
+   *
+   * @param srcImage see {@link #setSourceImage} for description
+   *
+   * @param width see {@link #setSourceImage} for description
+   *
+   * @param pitch see {@link #setSourceImage} for description
+   *
+   * @param height see {@link #setSourceImage} for description
+   *
+   * @param pixelFormat see {@link #setSourceImage} for description
+   */
+  public TJCompressor(byte[] srcImage, int width, int pitch, int height,
+    int pixelFormat) throws Exception {
+    setSourceImage(srcImage, width, pitch, height, pixelFormat);
+  }
+
+  /**
+   * Associate an uncompressed source image with this compressor instance.
+   *
+   * @param srcImage image buffer containing RGB or grayscale pixels to be
+   * compressed
+   *
+   * @param width width (in pixels) of the source image
+   *
+   * @param pitch bytes per line of the source image.  Normally, this should be
+   * <code>width * TJ.pixelSize(pixelFormat)</code> if the source image is
+   * unpadded, but you can use this parameter to, for instance, specify that
+   * the scanlines in the source image are padded to 4-byte boundaries, as is
+   * the case for Windows bitmaps.  You can also be clever and use this
+   * parameter to skip lines, etc.  Setting this parameter to 0 is the
+   * equivalent of setting it to <code>width *
+   * TJ.pixelSize(pixelFormat)</code>.
+   *
+   * @param height height (in pixels) of the source image
+   *
+   * @param pixelFormat pixel format of the source image (one of
+   * {@link TJ TJ.PF_*})
+   */
+  public void setSourceImage(byte[] srcImage, int width, int pitch,
+    int height, int pixelFormat) throws Exception {
+    if(handle == 0) init();
+    if(srcImage == null || width < 1 || height < 1 || pitch < 0
+      || pixelFormat < 0 || pixelFormat >= TJ.NUMPF)
+      throw new Exception("Invalid argument in setSourceImage()");
+    srcBuf = srcImage;
+    srcWidth = width;
+    if(pitch == 0) srcPitch = width * TJ.getPixelSize(pixelFormat);
+    else srcPitch = pitch;
+    srcHeight = height;
+    srcPixelFormat = pixelFormat;
+  }
+
+  /**
+   * Set the level of chrominance subsampling for subsequent compress/encode
+   * operations.
+   *
+   * @param newSubsamp the new level of chrominance subsampling (one of
+   * {@link TJ TJ.SAMP_*})
+   */
+  public void setSubsamp(int newSubsamp) throws Exception {
+    if(newSubsamp < 0 || newSubsamp >= TJ.NUMSAMP)
+      throw new Exception("Invalid argument in setSubsamp()");
+    subsamp = newSubsamp;
+  }
+
+  /**
+   * Set the JPEG image quality level for subsequent compress operations.
+   *
+   * @param quality the new JPEG image quality level (1 to 100, 1 = worst,
+   * 100 = best)
+   */
+  public void setJPEGQuality(int quality) throws Exception {
+    if(quality < 1 || quality > 100)
+      throw new Exception("Invalid argument in setJPEGQuality()");
+    jpegQuality = quality;
+  }
+
+  /**
+   * Compress the uncompressed source image associated with this compressor
+   * instance and output a JPEG image to the given destination buffer.
+   *
+   * @param dstBuf buffer which will receive the JPEG image.  Use
+   * {@link TJ#bufSize} to determine the maximum size for this buffer based on
+   * the image width and height.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void compress(byte[] dstBuf, int flags) throws Exception {
+    if(dstBuf == null || flags < 0)
+      throw new Exception("Invalid argument in compress()");
+    if(srcBuf == null) throw new Exception(NO_ASSOC_ERROR);
+    if(jpegQuality < 0) throw new Exception("JPEG Quality not set");
+    if(subsamp < 0) throw new Exception("Subsampling level not set");
+    compressedSize = compress(srcBuf, srcWidth, srcPitch,
+      srcHeight, srcPixelFormat, dstBuf, subsamp, jpegQuality, flags);
+  }
+
+  /**
+   * Compress the uncompressed source image associated with this compressor
+   * instance and return a buffer containing a JPEG image.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a buffer containing a JPEG image.  The length of this buffer will
+   * not be equal to the size of the JPEG image.  Use {@link
+   * #getCompressedSize} to obtain the size of the JPEG image.
+   */
+  public byte[] compress(int flags) throws Exception {
+    if(srcWidth < 1 || srcHeight < 1)
+      throw new Exception(NO_ASSOC_ERROR);
+    byte[] buf = new byte[TJ.bufSize(srcWidth, srcHeight)];
+    compress(buf, flags);
+    return buf;
+  }
+
+  /**
+   * Compress the uncompressed source image stored in <code>srcImage</code>
+   * and output a JPEG image to the given destination buffer.
+   *
+   * @param srcImage a <code>BufferedImage</code> instance containing RGB or
+   * grayscale pixels to be compressed
+   *
+   * @param dstBuf buffer which will receive the JPEG image.  Use
+   * {@link TJ#bufSize} to determine the maximum size for this buffer based on
+   * the image width and height.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void compress(BufferedImage srcImage, byte[] dstBuf, int flags)
+    throws Exception {
+    if(srcImage == null || dstBuf == null || flags < 0)
+      throw new Exception("Invalid argument in compress()");
+    int width = srcImage.getWidth();
+    int height = srcImage.getHeight();
+    int pixelFormat;  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_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;
+      default:
+        throw new Exception("Unsupported BufferedImage format");
+    }
+    WritableRaster wr = srcImage.getRaster();
+    if(jpegQuality < 0) throw new Exception("JPEG Quality not set");
+    if(subsamp < 0) throw new Exception("Subsampling level not set");
+    if(intPixels) {
+      SinglePixelPackedSampleModel sm =
+        (SinglePixelPackedSampleModel)srcImage.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+      int[] buf = db.getData();
+      compressedSize = compress(buf, width, pitch, height, pixelFormat, dstBuf,
+        subsamp, jpegQuality, flags);
+    }
+    else {
+      ComponentSampleModel sm =
+        (ComponentSampleModel)srcImage.getSampleModel();
+      int pixelSize = sm.getPixelStride();
+      if(pixelSize != TJ.getPixelSize(pixelFormat))
+        throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
+      int pitch = sm.getScanlineStride();
+      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+      byte[] buf = db.getData();
+      compressedSize = compress(buf, width, pitch, height, pixelFormat, dstBuf,
+        subsamp, jpegQuality, flags);
+    }
+  }
+
+  /**
+   * Compress the uncompressed source image stored in <code>srcImage</code>
+   * and return a buffer containing a JPEG image.
+   *
+   * @param srcImage a <code>BufferedImage</code> instance containing RGB or
+   * grayscale pixels to be compressed
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a buffer containing a JPEG image.  The length of this buffer will
+   * not be equal to the size of the JPEG image.  Use {@link
+   * #getCompressedSize} to obtain the size of the JPEG image.
+   */
+  public byte[] compress(BufferedImage srcImage, int flags) throws Exception {
+    int width = srcImage.getWidth();
+    int height = srcImage.getHeight();
+    byte[] buf = new byte[TJ.bufSize(width, height)];
+    compress(srcImage, buf, flags);
+    return buf;
+  }
+
+  /**
+   * Encode the uncompressed source image associated with this compressor
+   * instance and output a YUV planar image to the given destination buffer.
+   * This method uses the accelerated color conversion routines in
+   * TurboJPEG's underlying codec to produce a planar YUV image that is
+   * suitable for direct video display.  Specifically, if the chrominance
+   * components are subsampled along the horizontal dimension, then the width
+   * of the luminance plane is padded to 2 in the output image (same goes for
+   * the height of the luminance plane, if the chrominance components are
+   * subsampled along the vertical dimension.)  Also, each line of each plane
+   * in the output image is padded to 4 bytes.  Although this will work with
+   * any subsampling option, it is really only useful in combination with
+   * {@link TJ#SAMP_420}, which produces an image compatible with the I420 (AKA
+   * "YUV420P") format.
+   *
+   * @param dstBuf buffer which will receive the YUV planar image.  Use
+   * {@link TJ#bufSizeYUV} to determine the appropriate size for this buffer
+   * based on the image width, height, and level of chrominance subsampling.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void encodeYUV(byte[] dstBuf, int flags) throws Exception {
+    if(dstBuf == null || flags < 0)
+      throw new Exception("Invalid argument in compress()");
+    if(srcBuf == null) throw new Exception(NO_ASSOC_ERROR);
+    if(subsamp < 0) throw new Exception("Subsampling level not set");
+    encodeYUV(srcBuf, srcWidth, srcPitch, srcHeight,
+      srcPixelFormat, dstBuf, subsamp, flags);
+    compressedSize = TJ.bufSizeYUV(srcWidth, srcHeight, subsamp);
+  }
+
+  /**
+   * Encode the uncompressed source image associated with this compressor
+   * instance and return a buffer containing a YUV planar image.  See
+   * {@link #encodeYUV(byte[], int)} for more detail.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a buffer containing a YUV planar image
+   */
+  public byte[] encodeYUV(int flags) throws Exception {
+    if(srcWidth < 1 || srcHeight < 1)
+      throw new Exception(NO_ASSOC_ERROR);
+    if(subsamp < 0) throw new Exception("Subsampling level not set");
+    byte[] buf = new byte[TJ.bufSizeYUV(srcWidth, srcHeight, subsamp)];
+    encodeYUV(buf, flags);
+    return buf;
+  }
+
+  /**
+   * Encode the uncompressed source image stored in <code>srcImage</code>
+   * and output a YUV planar image to the given destination buffer.  See
+   * {@link #encodeYUV(byte[], int)} for more detail.
+   *
+   * @param srcImage a <code>BufferedImage</code> instance containing RGB or
+   * grayscale pixels to be encoded
+   *
+   * @param dstBuf buffer which will receive the YUV planar image.  Use
+   * {@link TJ#bufSizeYUV} to determine the appropriate size for this buffer
+   * based on the image width, height, and level of chrominance subsampling.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void encodeYUV(BufferedImage srcImage, byte[] dstBuf, int flags)
+    throws Exception {
+    if(srcImage == null || dstBuf == null || flags < 0)
+      throw new Exception("Invalid argument in encodeYUV()");
+    int width = srcImage.getWidth();
+    int height = srcImage.getHeight();
+    int pixelFormat;  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_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;
+      default:
+        throw new Exception("Unsupported BufferedImage format");
+    }
+    WritableRaster wr = srcImage.getRaster();
+    if(subsamp < 0) throw new Exception("Subsampling level not set");
+    if(intPixels) {
+      SinglePixelPackedSampleModel sm =
+        (SinglePixelPackedSampleModel)srcImage.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+      int[] buf = db.getData();
+      encodeYUV(buf, width, pitch, height, pixelFormat, dstBuf, subsamp,
+        flags);
+    }
+    else {
+      ComponentSampleModel sm =
+        (ComponentSampleModel)srcImage.getSampleModel();
+      int pixelSize = sm.getPixelStride();
+      if(pixelSize != TJ.getPixelSize(pixelFormat))
+        throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
+      int pitch = sm.getScanlineStride();
+      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+      byte[] buf = db.getData();
+      encodeYUV(buf, width, pitch, height, pixelFormat, dstBuf, subsamp,
+        flags);
+    }
+    compressedSize = TJ.bufSizeYUV(width, height, subsamp);
+  }
+
+  /**
+   * Encode the uncompressed source image stored in <code>srcImage</code>
+   * and return a buffer containing a YUV planar image.  See
+   * {@link #encodeYUV(byte[], int)} for more detail.
+   *
+   * @param srcImage a <code>BufferedImage</code> instance containing RGB or
+   * grayscale pixels to be encoded
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a buffer containing a YUV planar image
+   */
+  public byte[] encodeYUV(BufferedImage srcImage, int flags)
+    throws Exception {
+    if(subsamp < 0) throw new Exception("Subsampling level not set");
+    int width = srcImage.getWidth();
+    int height = srcImage.getHeight();
+    byte[] buf = new byte[TJ.bufSizeYUV(width, height, subsamp)];
+    encodeYUV(srcImage, buf, flags);
+    return buf;
+  }
+
+  /**
+   * Returns the size of the image (in bytes) generated by the most recent
+   * compress/encode operation.
+   *
+   * @return the size of the image (in bytes) generated by the most recent
+   * compress/encode operation
+   */
+  public int getCompressedSize() {
+    return compressedSize;
+  }
+
+  /**
+   * Free the native structures associated with this compressor instance.
+   */
+  public void close() throws Exception {
+    destroy();
+  }
+
+  protected void finalize() throws Throwable {
+    try {
+      close();
+    }
+    catch(Exception e) {}
+    finally {
+      super.finalize();
+    }
+  };
+
+  private native void init() throws Exception;
+
+  private native void destroy() throws Exception;
+
+  // JPEG size in bytes is returned
+  private native int compress(byte[] srcBuf, int width, int pitch,
+    int height, int pixelFormat, byte[] dstbuf, int jpegSubsamp, int jpegQual,
+    int flags) throws Exception;
+
+  private native int compress(int[] srcBuf, int width, int pitch,
+    int height, int pixelFormat, byte[] dstbuf, int jpegSubsamp, int jpegQual,
+    int flags) throws Exception;
+
+  private native void encodeYUV(byte[] srcBuf, int width, int pitch,
+    int height, int pixelFormat, byte[] dstbuf, int subsamp, int flags)
+    throws Exception;
+
+  private native void encodeYUV(int[] srcBuf, int width, int pitch,
+    int height, int pixelFormat, byte[] dstbuf, int subsamp, int flags)
+    throws Exception;
+
+  static {
+    TJLoader.load();
+  }
+
+  private long handle = 0;
+  private byte[] srcBuf = null;
+  private int srcWidth = 0;
+  private int srcHeight = 0;
+  private int srcPitch = 0;
+  private int srcPixelFormat = -1;
+  private int subsamp = -1;
+  private int jpegQuality = -1;
+  private int compressedSize = 0;
+  private ByteOrder byteOrder = null;
+};
diff --git a/java/org/libjpegturbo/turbojpeg/TJDecompressor.java b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java
new file mode 100644
index 0000000..b247847
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJDecompressor.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+import java.awt.image.*;
+import java.nio.*;
+
+/**
+ * TurboJPEG decompressor
+ */
+public class TJDecompressor {
+
+  private final static String NO_ASSOC_ERROR =
+    "No JPEG image is associated with this instance";
+
+  /**
+   * Create a TurboJPEG decompresssor instance.
+   */
+  public TJDecompressor() throws Exception {
+    init();
+  }
+
+  /**
+   * Create a TurboJPEG decompressor instance and associate the JPEG image
+   * stored in <code>jpegImage</code> with the newly-created instance.
+   *
+   * @param jpegImage JPEG image buffer (size of the JPEG image is assumed to
+   * be the length of the array)
+   */
+  public TJDecompressor(byte[] jpegImage) throws Exception {
+    init();
+    setJPEGImage(jpegImage, jpegImage.length);
+  }
+
+  /**
+   * Create a TurboJPEG decompressor instance and associate the JPEG image
+   * of length <code>imageSize</code> bytes stored in <code>jpegImage</code>
+   * with the newly-created instance.
+   *
+   * @param jpegImage JPEG image buffer
+   *
+   * @param imageSize size of the JPEG image (in bytes)
+   */
+  public TJDecompressor(byte[] jpegImage, int imageSize) throws Exception {
+    init();
+    setJPEGImage(jpegImage, imageSize);
+  }
+
+  /**
+   * Associate the JPEG image of length <code>imageSize</code> bytes stored in
+   * <code>jpegImage</code> with this decompressor instance.  This image will
+   * be used as the source image for subsequent decompress operations.
+   *
+   * @param jpegImage JPEG image buffer
+   *
+   * @param imageSize size of the JPEG image (in bytes)
+   */
+  public void setJPEGImage(byte[] jpegImage, int imageSize) throws Exception {
+    if(jpegImage == null || imageSize < 1)
+      throw new Exception("Invalid argument in setJPEGImage()");
+    jpegBuf = jpegImage;
+    jpegBufSize = imageSize;
+    decompressHeader(jpegBuf, jpegBufSize);
+  }
+
+  /**
+   * Returns the width of the JPEG image associated with this decompressor
+   * instance.
+   *
+   * @return the width of the JPEG image associated with this decompressor
+   * instance
+   */
+  public int getWidth() throws Exception {
+    if(jpegWidth < 1) throw new Exception(NO_ASSOC_ERROR);
+    return jpegWidth;
+  }
+
+  /**
+   * Returns the height of the JPEG image associated with this decompressor
+   * instance.
+   *
+   * @return the height of the JPEG image associated with this decompressor
+   * instance
+   */
+  public int getHeight() throws Exception {
+    if(jpegHeight < 1) throw new Exception(NO_ASSOC_ERROR);
+    return jpegHeight;
+  }
+
+  /**
+   * Returns the level of chrominance subsampling used in the JPEG image
+   * associated with this decompressor instance.
+   *
+   * @return the level of chrominance subsampling used in the JPEG image
+   * associated with this decompressor instance
+   */
+  public int getSubsamp() throws Exception {
+    if(jpegSubsamp < 0) throw new Exception(NO_ASSOC_ERROR);
+    if(jpegSubsamp >= TJ.NUMSAMP)
+      throw new Exception("JPEG header information is invalid");
+    return jpegSubsamp;
+  }
+
+  /**
+   * Returns the JPEG image buffer associated with this decompressor instance.
+   *
+   * @return the JPEG image buffer associated with this decompressor instance
+   */
+  public byte[] getJPEGBuf() throws Exception {
+    if(jpegBuf == null) throw new Exception(NO_ASSOC_ERROR);
+    return jpegBuf;
+  }
+
+  /**
+   * Returns the size of the JPEG image (in bytes) associated with this
+   * decompressor instance.
+   *
+   * @return the size of the JPEG image (in bytes) associated with this
+   * decompressor instance
+   */
+  public int getJPEGSize() throws Exception {
+    if(jpegBufSize < 1) throw new Exception(NO_ASSOC_ERROR);
+    return jpegBufSize;
+  }
+
+
+  /**
+   * Returns the width of the largest scaled down image that the TurboJPEG
+   * decompressor can generate without exceeding the desired image width and
+   * height.
+   *
+   * @param desiredWidth desired width (in pixels) of the decompressed image.
+   * Setting this to 0 is the same as setting it to the width of the JPEG image
+   * (in other words, the width will not be considered when determining the
+   * scaled image size.)
+   *
+   * @param desiredHeight desired height (in pixels) of the decompressed image.
+   * Setting this to 0 is the same as setting it to the height of the JPEG
+   * image (in other words, the height will not be considered when determining
+   * the scaled image size.)
+   *
+   * @return the width of the largest scaled down image that the TurboJPEG
+   * decompressor can generate without exceeding the desired image width and
+   * height
+   */
+  public int getScaledWidth(int desiredWidth, int desiredHeight)
+    throws Exception {
+    if(jpegWidth < 1 || jpegHeight < 1)
+      throw new Exception(NO_ASSOC_ERROR);
+    if(desiredWidth < 0 || desiredHeight < 0)
+      throw new Exception("Invalid argument in getScaledWidth()");
+    TJScalingFactor sf[] = TJ.getScalingFactors();
+    if(desiredWidth == 0) desiredWidth = jpegWidth;
+    if(desiredHeight == 0) desiredHeight = jpegHeight;
+    int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
+    for(int i = 0; i < sf.length; i++) {
+      scaledWidth = sf[i].getScaled(jpegWidth);
+      scaledHeight = sf[i].getScaled(jpegHeight);
+      if(scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
+        break;
+    }
+    if(scaledWidth > desiredWidth || scaledHeight > desiredHeight)
+      throw new Exception("Could not scale down to desired image dimensions");
+    return scaledWidth;
+  }
+
+  /**
+   * Returns the height of the largest scaled down image that the TurboJPEG
+   * decompressor can generate without exceeding the desired image width and
+   * height.
+   *
+   * @param desiredWidth desired width (in pixels) of the decompressed image.
+   * Setting this to 0 is the same as setting it to the width of the JPEG image
+   * (in other words, the width will not be considered when determining the
+   * scaled image size.)
+   *
+   * @param desiredHeight desired height (in pixels) of the decompressed image.
+   * Setting this to 0 is the same as setting it to the height of the JPEG
+   * image (in other words, the height will not be considered when determining
+   * the scaled image size.)
+   *
+   * @return the height of the largest scaled down image that the TurboJPEG
+   * decompressor can generate without exceeding the desired image width and
+   * height
+   */
+  public int getScaledHeight(int desiredWidth, int desiredHeight)
+    throws Exception {
+    if(jpegWidth < 1 || jpegHeight < 1)
+      throw new Exception(NO_ASSOC_ERROR);
+    if(desiredWidth < 0 || desiredHeight < 0)
+      throw new Exception("Invalid argument in getScaledHeight()");
+    TJScalingFactor sf[] = TJ.getScalingFactors();
+    if(desiredWidth == 0) desiredWidth = jpegWidth;
+    if(desiredHeight == 0) desiredHeight = jpegHeight;
+    int scaledWidth = jpegWidth, scaledHeight = jpegHeight;
+    for(int i = 0; i < sf.length; i++) {
+      scaledWidth = sf[i].getScaled(jpegWidth);
+      scaledHeight = sf[i].getScaled(jpegHeight);
+      if(scaledWidth <= desiredWidth && scaledHeight <= desiredHeight)
+        break;
+    }
+    if(scaledWidth > desiredWidth || scaledHeight > desiredHeight)
+      throw new Exception("Could not scale down to desired image dimensions");
+    return scaledHeight;
+  }
+
+  /**
+   * Decompress the JPEG source image associated with this decompressor
+   * instance and output a decompressed image to the given destination buffer.
+   *
+   * @param dstBuf buffer which will receive the decompressed image.  This
+   * buffer should normally be <code>pitch * scaledHeight</code> bytes in size,
+   * where <code>scaledHeight</code> can be determined by calling <code>
+   * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegHeight)
+   * </code> with one of the scaling factors returned from {@link
+   * TJ#getScalingFactors} or by calling {@link #getScaledHeight}.
+   *
+   * @param desiredWidth desired width (in pixels) of the decompressed image.
+   * If the desired image dimensions are smaller than the dimensions of the
+   * JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG
+   * decompressor to generate the largest possible image that will fit within
+   * the desired dimensions.  Setting this to 0 is the same as setting it to
+   * the width of the JPEG image (in other words, the width will not be
+   * considered when determining the scaled image size.)
+   *
+   * @param pitch bytes per line of the destination image.  Normally, this
+   * should be set to <code>scaledWidth * TJ.pixelSize(pixelFormat)</code> if
+   * the decompressed image is unpadded, but you can use this to, for instance,
+   * pad each line of the decompressed image to a 4-byte boundary.  NOTE:
+   * <code>scaledWidth</code> can be determined by calling <code>
+   * scalingFactor.{@link TJScalingFactor#getScaled getScaled}(jpegWidth)
+   * </code> or by calling {@link #getScaledWidth}.  Setting this parameter to
+   * 0 is the equivalent of setting it to <code>scaledWidth *
+   * TJ.pixelSize(pixelFormat)</code>.
+   *
+   * @param desiredHeight desired height (in pixels) of the decompressed image.
+   * If the desired image dimensions are smaller than the dimensions of the
+   * JPEG image being decompressed, then TurboJPEG will use scaling in the JPEG
+   * decompressor to generate the largest possible image that will fit within
+   * the desired dimensions.  Setting this to 0 is the same as setting it to
+   * the height of the JPEG image (in other words, the height will not be
+   * considered when determining the scaled image size.)
+   *
+   * @param pixelFormat pixel format of the decompressed image (one of
+   * {@link TJ TJ.PF_*})
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void decompress(byte[] dstBuf, int desiredWidth, int pitch,
+    int desiredHeight, int pixelFormat, int flags) throws Exception {
+    if(jpegBuf == null) throw new Exception(NO_ASSOC_ERROR);
+    if(dstBuf == null || desiredWidth < 0 || pitch < 0 || desiredHeight < 0
+      || pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
+      throw new Exception("Invalid argument in decompress()");
+    decompress(jpegBuf, jpegBufSize, dstBuf, desiredWidth, pitch,
+      desiredHeight, pixelFormat, flags);
+  }
+
+  /**
+   * Decompress the JPEG source image associated with this decompressor
+   * instance and return a buffer containing the decompressed image.
+   *
+   * @param desiredWidth see
+   * {@link #decompress(byte[], int, int, int, int, int)} for description
+   *
+   * @param pitch see
+   * {@link #decompress(byte[], int, int, int, int, int)} for description
+   *
+   * @param desiredHeight see
+   * {@link #decompress(byte[], int, int, int, int, int)} for description
+   *
+   * @param pixelFormat pixel format of the decompressed image (one of
+   * {@link TJ TJ.PF_*})
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a buffer containing the decompressed image
+   */
+  public byte[] decompress(int desiredWidth, int pitch, int desiredHeight,
+    int pixelFormat, int flags) throws Exception {
+    if(desiredWidth < 0 || pitch < 0 || desiredHeight < 0
+      || pixelFormat < 0 || pixelFormat >= TJ.NUMPF || flags < 0)
+      throw new Exception("Invalid argument in decompress()");
+    int pixelSize = TJ.getPixelSize(pixelFormat);
+    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
+    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
+    if(pitch == 0) pitch = scaledWidth * pixelSize;
+    byte[] buf = new byte[pitch * scaledHeight];
+    decompress(buf, desiredWidth, pitch, desiredHeight, pixelFormat, flags);
+    return buf;
+  }
+
+  /**
+   * Decompress the JPEG source image associated with this decompressor
+   * instance and output a YUV planar image to the given destination buffer.
+   * This method performs JPEG decompression but leaves out the color
+   * conversion step, so a planar YUV image is generated instead of an RGB
+   * image.  The padding of the planes in this image is the same as the images
+   * generated by {@link TJCompressor#encodeYUV(byte[], int)}.  Note that, if
+   * the width or height of the image is not an even multiple of the MCU block
+   * size (see {@link TJ#getMCUWidth} and {@link TJ#getMCUHeight}), then an
+   * intermediate buffer copy will be performed within TurboJPEG.
+   *
+   * @param dstBuf buffer which will receive the YUV planar image.  Use
+   * {@link TJ#bufSizeYUV} to determine the appropriate size for this buffer
+   * based on the image width, height, and level of chrominance subsampling.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void decompressToYUV(byte[] dstBuf, int flags) throws Exception {
+    if(jpegBuf == null) throw new Exception(NO_ASSOC_ERROR);
+    if(dstBuf == null || flags < 0)
+      throw new Exception("Invalid argument in decompressToYUV()");
+    decompressToYUV(jpegBuf, jpegBufSize, dstBuf, flags);
+  }
+
+  
+  /**
+   * Decompress the JPEG source image associated with this decompressor
+   * instance and return a buffer containing a YUV planar image.  See {@link
+   * #decompressToYUV(byte[], int)} for more detail.
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a buffer containing a YUV planar image
+   */
+  public byte[] decompressToYUV(int flags) throws Exception {
+    if(flags < 0)
+      throw new Exception("Invalid argument in decompressToYUV()");
+    if(jpegWidth < 1 || jpegHeight < 1 || jpegSubsamp < 0)
+      throw new Exception(NO_ASSOC_ERROR);
+    if(jpegSubsamp >= TJ.NUMSAMP)
+      throw new Exception("JPEG header information is invalid");
+    byte[] buf = new byte[TJ.bufSizeYUV(jpegWidth, jpegHeight, jpegSubsamp)];
+    decompressToYUV(buf, flags);
+    return buf;
+  }
+
+  /**
+   * Decompress the JPEG source image associated with this decompressor
+   * instance and output a decompressed image to the given
+   * <code>BufferedImage</code> instance.
+   *
+   * @param dstImage a <code>BufferedImage</code> instance which will receive
+   * the decompressed image
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void decompress(BufferedImage dstImage, int flags) throws Exception {
+    if(dstImage == null || flags < 0)
+      throw new Exception("Invalid argument in decompress()");
+    int desiredWidth = dstImage.getWidth();
+    int desiredHeight = dstImage.getHeight();
+    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
+    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
+    if(scaledWidth != desiredWidth || scaledHeight != desiredHeight)
+      throw new Exception("BufferedImage dimensions do not match a scaled image size that TurboJPEG is capable of generating.");
+    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_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;
+      default:
+        throw new Exception("Unsupported BufferedImage format");
+    }
+    WritableRaster wr = dstImage.getRaster();
+    if(intPixels) {
+      SinglePixelPackedSampleModel sm =
+        (SinglePixelPackedSampleModel)dstImage.getSampleModel();
+      int pitch = sm.getScanlineStride();
+      DataBufferInt db = (DataBufferInt)wr.getDataBuffer();
+      int[] buf = db.getData();
+      if(jpegBuf == null) throw new Exception(NO_ASSOC_ERROR);
+      decompress(jpegBuf, jpegBufSize, buf, scaledWidth, pitch, scaledHeight,
+        pixelFormat, flags);
+    }
+    else {
+      ComponentSampleModel sm =
+        (ComponentSampleModel)dstImage.getSampleModel();
+      int pixelSize = sm.getPixelStride();
+      if(pixelSize != TJ.getPixelSize(pixelFormat))
+        throw new Exception("Inconsistency between pixel format and pixel size in BufferedImage");
+      int pitch = sm.getScanlineStride();
+      DataBufferByte db = (DataBufferByte)wr.getDataBuffer();
+      byte[] buf = db.getData();
+      decompress(buf, scaledWidth, pitch, scaledHeight, pixelFormat, flags);
+    }
+  }
+
+  /**
+   * Decompress the JPEG source image associated with this decompressor
+   * instance and return a <code>BufferedImage</code> instance containing the
+   * decompressed image.
+   *
+   * @param desiredWidth see
+   * {@link #decompress(byte[], int, int, int, int, int)} for description
+   *
+   * @param desiredHeight see
+   * {@link #decompress(byte[], int, int, int, int, int)} for description
+   *
+   * @param bufferedImageType the image type of the newly-created
+   * <code>BufferedImage</code> instance (for instance,
+   * <code>BufferedImage.TYPE_INT_RGB</code>)
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   *
+   * @return a <code>BufferedImage</code> instance containing the
+   * decompressed image
+   */
+  public BufferedImage decompress(int desiredWidth, int desiredHeight,
+    int bufferedImageType, int flags) throws Exception {
+    if(desiredWidth < 0 || desiredHeight < 0 || flags < 0)
+      throw new Exception("Invalid argument in decompress()");
+    int scaledWidth = getScaledWidth(desiredWidth, desiredHeight);
+    int scaledHeight = getScaledHeight(desiredWidth, desiredHeight);
+    BufferedImage img = new BufferedImage(scaledWidth, scaledHeight,
+      bufferedImageType);
+    decompress(img, flags);
+    return img;
+  }
+
+  /**
+   * Free the native structures associated with this decompressor instance.
+   */
+  public void close() throws Exception {
+    destroy();
+  }
+
+  protected void finalize() throws Throwable {
+    try {
+      close();
+    }
+    catch(Exception e) {}
+    finally {
+      super.finalize();
+    }
+  };
+
+  private native void init() throws Exception;
+
+  private native void destroy() throws Exception;
+
+  private native void decompressHeader(byte[] srcBuf, int size)
+    throws Exception;
+
+  private native void decompress(byte[] srcBuf, int size, byte[] dstBuf,
+    int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags)
+    throws Exception;
+
+  private native void decompress(byte[] srcBuf, int size, int[] dstBuf,
+    int desiredWidth, int pitch, int desiredHeight, int pixelFormat, int flags)
+    throws Exception;
+
+  private native void decompressToYUV(byte[] srcBuf, int size, byte[] dstBuf,
+    int flags)
+    throws Exception;
+
+  static {
+    TJLoader.load();
+  }
+
+  protected long handle = 0;
+  protected byte[] jpegBuf = null;
+  protected int jpegBufSize = 0;
+  protected int jpegWidth = 0;
+  protected int jpegHeight = 0;
+  protected int jpegSubsamp = -1;
+  private ByteOrder byteOrder = null;
+};
diff --git a/java/org/libjpegturbo/turbojpeg/TJLoader.java b/java/org/libjpegturbo/turbojpeg/TJLoader.java
new file mode 100644
index 0000000..db77bba
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJLoader.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+final class TJLoader {
+  static void load() {
+    System.loadLibrary("turbojpeg");
+  }
+};
diff --git a/java/org/libjpegturbo/turbojpeg/TJLoader.java.in b/java/org/libjpegturbo/turbojpeg/TJLoader.java.in
new file mode 100644
index 0000000..22353a5
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJLoader.java.in
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+final class TJLoader {
+  static void load() {
+    System.loadLibrary("@TURBOJPEG_DLL_NAME@");
+  }
+};
diff --git a/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java b/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java
new file mode 100644
index 0000000..d71ceee
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJScalingFactor.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+/**
+ * Fractional scaling factor
+ */
+public class TJScalingFactor {
+
+  public TJScalingFactor(int num, int denom) throws Exception {
+    if(num < 1 || denom < 1)
+      throw new Exception("Numerator and denominator must be >= 1");
+    this.num = num;
+    this.denom = denom;
+  }
+
+  /**
+   * Returns numerator
+   * @return numerator
+   */
+  public int getNum() {
+    return num;
+  }
+
+  /**
+   * Returns denominator
+   * @return denominator
+   */
+  public int getDenom() {
+    return denom;
+  }
+
+  /**
+   * Returns the scaled value of <code>dimension</code>.  This function
+   * performs the integer equivalent of
+   * <code>ceil(dimension * scalingFactor)</code>.
+   * @return the scaled value of <code>dimension</code>
+   */
+  public int getScaled(int dimension) {
+    return (dimension * num + denom - 1) / denom;
+  }
+
+  /**
+   * Returns true or false, depending on whether this instance and
+   * <code>other</code> have the same numerator and denominator.
+   * @return true or false, depending on whether this instance and
+   * <code>other</code> have the same numerator and denominator
+   */
+  public boolean equals(TJScalingFactor other) {
+    return (this.num == other.num && this.denom == other.denom);
+  }
+
+  /**
+   * Returns true or false, depending on whether this instance is equal to
+   * 1/1.
+   * @return true or false, depending on whether this instance is equal to
+   * 1/1
+   */
+  public boolean isOne() {
+    return (num == 1 && denom == 1);
+  }
+
+  /**
+   * Numerator
+   */
+  private int num = 1;
+
+  /**
+   * Denominator
+   */
+  private int denom = 1;
+};
diff --git a/java/org/libjpegturbo/turbojpeg/TJTransform.java b/java/org/libjpegturbo/turbojpeg/TJTransform.java
new file mode 100644
index 0000000..3f4eb38
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJTransform.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+import java.awt.*;
+
+/**
+ * Lossless transform parameters
+ */
+public class TJTransform extends Rectangle {
+
+  private static final long serialVersionUID = -127367705761430371L;
+
+
+  /**
+   * The number of lossless transform operations
+   */
+  final public static int NUMOP         = 8;
+  /**
+   * Do not transform the position of the image pixels.
+   */
+  final public static int OP_NONE       = 0;
+  /**
+   * Flip (mirror) image horizontally.  This transform is imperfect if there
+   * are any partial MCU blocks on the right edge.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_HFLIP      = 1;
+  /**
+   * Flip (mirror) image vertically.  This transform is imperfect if there are
+   * any partial MCU blocks on the bottom edge.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_VFLIP      = 2;
+  /**
+   * Transpose image (flip/mirror along upper left to lower right axis).  This
+   * transform is always perfect.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_TRANSPOSE  = 3;
+  /**
+   * Transverse transpose image (flip/mirror along upper right to lower left
+   * axis).  This transform is imperfect if there are any partial MCU blocks in
+   * the image.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_TRANSVERSE = 4;
+  /**
+   * Rotate image clockwise by 90 degrees.  This transform is imperfect if
+   * there are any partial MCU blocks on the bottom edge.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_ROT90      = 5;
+  /**
+   * Rotate image 180 degrees.  This transform is imperfect if there are any
+   * partial MCU blocks in the image.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_ROT180     = 6;
+  /**
+   * Rotate image counter-clockwise by 90 degrees.  This transform is imperfect
+   * if there are any partial MCU blocks on the right edge.
+   * @see #OPT_PERFECT
+   */
+  final public static int OP_ROT270     = 7;
+
+
+  /**
+   * This option will cause {@link TJTransformer#transform
+   * TJTransformer.transform()} to throw an exception if the transform is not
+   * perfect.  Lossless transforms operate on MCU blocks, whose size depends on
+   * the level of chrominance subsampling used.  If the image's width or height
+   * is not evenly divisible by the MCU block size (see {@link TJ#getMCUWidth}
+   * and {@link TJ#getMCUHeight}), then there will be partial MCU blocks on the
+   * right and/or bottom edges.   It is not possible to move these partial MCU
+   * blocks to the top or left of the image, so any transform that would
+   * require that is "imperfect."  If this option is not specified, then any
+   * 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.
+   */
+  final public static int OPT_PERFECT = 1;
+  /**
+   * This option will discard any partial MCU blocks that cannot be
+   * transformed.
+   */
+  final public static int OPT_TRIM    = 2;
+  /**
+   * This option will enable lossless cropping.
+   */
+  final public static int OPT_CROP    = 4;
+  /**
+   * This option will discard the color data in the input image and produce
+   * a grayscale output image.
+   */
+  final public static int OPT_GRAY    = 8;
+
+  
+  /**
+   * Create a new lossless transform instance.
+   */
+  public TJTransform() {
+  }
+
+  /**
+   * Create a new lossless transform instance with the given parameters.
+   *
+   * @param x the left boundary of the cropping region.  This must be evenly
+   * divisible by the MCU block width (see {@link TJ#getMCUWidth})
+   *
+   * @param y the upper boundary of the cropping region.  This must be evenly
+   * divisible by the MCU block height (see {@link TJ#getMCUHeight})
+   *
+   * @param w the width of the cropping region.  Setting this to 0 is the
+   * equivalent of setting it to the width of the source JPEG image - x.
+   *
+   * @param h the height of the cropping region.  Setting this to 0 is the
+   * equivalent of setting it to the height of the source JPEG image - y.
+   *
+   * @param op one of the transform operations (<code>OP_*</code>)
+   *
+   * @param options the bitwise OR of one or more of the transform options
+   * (<code>OPT_*</code>)
+   */
+  public TJTransform(int x, int y, int w, int h, int op, int options)
+    throws Exception {
+    super(x, y, w, h);
+    this.op = op;  this.options = options;
+  }
+
+  /**
+   * Create a new lossless transform instance with the given parameters.
+   *
+   * @param r a <code>Rectangle</code> instance which specifies the cropping
+   * region.  See {@link #TJTransform(int, int, int, int, int, int)} for more
+   * detail.
+   *
+   * @param op one of the transform operations (<code>OP_*</code>)
+   *
+   * @param options the bitwise OR of one or more of the transform options
+   * (<code>OPT_*</code>)
+   */
+  public TJTransform(Rectangle r, int op, int options) throws Exception {
+    super(r);
+    this.op = op;  this.options = options;
+  }
+
+  /**
+   * Transform operation (one of <code>OP_*</code>)
+   */
+  public int op = 0;
+
+  /**
+   * Transform options (bitwise OR of one or more of <code>OPT_*</code>)
+   */
+  public int options = 0;
+}
diff --git a/java/org/libjpegturbo/turbojpeg/TJTransformer.java b/java/org/libjpegturbo/turbojpeg/TJTransformer.java
new file mode 100644
index 0000000..78c4c9d
--- /dev/null
+++ b/java/org/libjpegturbo/turbojpeg/TJTransformer.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.libjpegturbo.turbojpeg;
+
+/**
+ * TurboJPEG lossless transformer
+ */
+public class TJTransformer extends TJDecompressor {
+
+  /**
+   * Create a TurboJPEG lossless transformer instance.
+   */
+  public TJTransformer() throws Exception {
+    init();
+  }
+
+  /**
+   * Create a TurboJPEG lossless transformer instance and associate the JPEG
+   * image stored in <code>jpegImage</code> with the newly-created instance.
+   *
+   * @param jpegImage JPEG image buffer (size of the JPEG image is assumed to
+   * be the length of the array)
+   */
+  public TJTransformer(byte[] jpegImage) throws Exception {
+    init();
+    setJPEGImage(jpegImage, jpegImage.length);
+  }
+
+  /**
+   * Create a TurboJPEG lossless transformer instance and associate the JPEG
+   * image of length <code>imageSize</code> bytes stored in
+   * <code>jpegImage</code> with the newly-created instance.
+   *
+   * @param jpegImage JPEG image buffer
+   *
+   * @param imageSize size of the JPEG image (in bytes)
+   */
+  public TJTransformer(byte[] jpegImage, int imageSize) throws Exception {
+    init();
+    setJPEGImage(jpegImage, imageSize);
+  }
+
+  /**
+   * Losslessly transform the JPEG image associated with this transformer
+   * instance into one or more JPEG images stored in the given destination
+   * buffers.  Lossless transforms work by moving the raw coefficients from one
+   * JPEG image structure to another without altering the values of the
+   * coefficients.  While this is typically faster than decompressing the
+   * image, transforming it, and re-compressing it, lossless transforms are not
+   * free.  Each lossless transform requires reading and Huffman decoding all
+   * of the coefficients in the source image, regardless of the size of the
+   * destination image.  Thus, this method provides a means of generating
+   * multiple transformed images from the same source or of applying multiple
+   * transformations simultaneously, in order to eliminate the need to read the
+   * source coefficients multiple times.
+   *
+   * @param dstBufs an array of image buffers.  <code>dstbufs[i]</code> will
+   * receive a JPEG image that has been transformed using the parameters in
+   * <code>transforms[i]</code>.  Use {@link TJ#bufSize} to determine the
+   * maximum size for each buffer based on the cropped width and height.
+   *
+   * @param transforms an array of {@link TJTransform} instances, each of
+   * which specifies the transform parameters and/or cropping region for the
+   * corresponding transformed output image
+   *
+   * @param flags the bitwise OR of one or more of {@link TJ TJ.FLAG_*}
+   */
+  public void transform(byte[][] dstBufs, TJTransform[] transforms,
+    int flags) throws Exception {
+    if(jpegBuf == null) throw new Exception("JPEG buffer not initialized");
+    transformedSizes = transform(jpegBuf, jpegBufSize, dstBufs, transforms,
+      flags);
+  }
+  
+  /**
+   * Losslessly transform the JPEG image associated with this transformer
+   * instance and return an array of {@link TJDecompressor} instances, each of
+   * which has a transformed JPEG image associated with it.
+   *
+   * @param transforms an array of {@link TJTransform} instances, each of
+   * 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 TJ.FLAG_*}
+   */
+  public TJDecompressor[] transform(TJTransform[] transforms, int flags)
+    throws Exception {
+    byte[][] dstBufs = new byte[transforms.length][];
+    if(jpegWidth < 1 || jpegHeight < 1)
+      throw new Exception("JPEG buffer not initialized");
+    for(int i = 0; i < transforms.length; i++) {
+      int w = jpegWidth, h = jpegHeight;
+      if((transforms[i].options & TJTransform.OPT_CROP) != 0) {
+        if(transforms[i].width != 0) w = transforms[i].width;
+        if(transforms[i].height != 0) h = transforms[i].height;
+      }
+      dstBufs[i] = new byte[TJ.bufSize(w, h)];
+    }
+    TJDecompressor[] tjd = new TJDecompressor[transforms.length];
+    transform(dstBufs, transforms, flags);
+    for(int i = 0; i < transforms.length; i++)
+      tjd[i] = new TJDecompressor(dstBufs[i], transformedSizes[i]);
+    return tjd;
+  }
+  
+  /**
+   * Returns an array containing the sizes of the transformed JPEG images from
+   * the most recent call to {@link #transform transform()}.
+   *
+   * @return an array containing the sizes of the transformed JPEG images from
+   * the most recent call to {@link #transform transform()}
+   */
+  public int[] getTransformedSizes() throws Exception {
+    if(transformedSizes == null)
+      throw new Exception("No image has been transformed yet");
+    return transformedSizes;
+  }
+
+  private native void init() throws Exception;
+
+  private native int[] transform(byte[] srcBuf, int srcSize, byte[][] dstBufs,
+    TJTransform[] transforms, int flags) throws Exception;
+
+  static {
+    TJLoader.load();
+  }
+
+  private int[] transformedSizes = null;
+};
diff --git a/java/org_libjpegturbo_turbojpeg_TJ.h b/java/org_libjpegturbo_turbojpeg_TJ.h
new file mode 100644
index 0000000..ab68bd5
--- /dev/null
+++ b/java/org_libjpegturbo_turbojpeg_TJ.h
@@ -0,0 +1,77 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_libjpegturbo_turbojpeg_TJ */
+
+#ifndef _Included_org_libjpegturbo_turbojpeg_TJ
+#define _Included_org_libjpegturbo_turbojpeg_TJ
+#ifdef __cplusplus
+extern "C" {
+#endif
+#undef org_libjpegturbo_turbojpeg_TJ_NUMSAMP
+#define org_libjpegturbo_turbojpeg_TJ_NUMSAMP 5L
+#undef org_libjpegturbo_turbojpeg_TJ_SAMP_444
+#define org_libjpegturbo_turbojpeg_TJ_SAMP_444 0L
+#undef org_libjpegturbo_turbojpeg_TJ_SAMP_422
+#define org_libjpegturbo_turbojpeg_TJ_SAMP_422 1L
+#undef org_libjpegturbo_turbojpeg_TJ_SAMP_420
+#define org_libjpegturbo_turbojpeg_TJ_SAMP_420 2L
+#undef org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY
+#define org_libjpegturbo_turbojpeg_TJ_SAMP_GRAY 3L
+#undef org_libjpegturbo_turbojpeg_TJ_SAMP_440
+#define org_libjpegturbo_turbojpeg_TJ_SAMP_440 4L
+#undef org_libjpegturbo_turbojpeg_TJ_NUMPF
+#define org_libjpegturbo_turbojpeg_TJ_NUMPF 7L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_RGB
+#define org_libjpegturbo_turbojpeg_TJ_PF_RGB 0L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_BGR
+#define org_libjpegturbo_turbojpeg_TJ_PF_BGR 1L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_RGBX
+#define org_libjpegturbo_turbojpeg_TJ_PF_RGBX 2L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_BGRX
+#define org_libjpegturbo_turbojpeg_TJ_PF_BGRX 3L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_XBGR
+#define org_libjpegturbo_turbojpeg_TJ_PF_XBGR 4L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_XRGB
+#define org_libjpegturbo_turbojpeg_TJ_PF_XRGB 5L
+#undef org_libjpegturbo_turbojpeg_TJ_PF_GRAY
+#define org_libjpegturbo_turbojpeg_TJ_PF_GRAY 6L
+#undef org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP
+#define org_libjpegturbo_turbojpeg_TJ_FLAG_BOTTOMUP 2L
+#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX
+#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCEMMX 8L
+#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE
+#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE 16L
+#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE2
+#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE2 32L
+#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE3
+#define org_libjpegturbo_turbojpeg_TJ_FLAG_FORCESSE3 128L
+#undef org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE
+#define org_libjpegturbo_turbojpeg_TJ_FLAG_FASTUPSAMPLE 256L
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJ
+ * Method:    bufSize
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
+  (JNIEnv *, jclass, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJ
+ * Method:    bufSizeYUV
+ * Signature: (III)I
+ */
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV
+  (JNIEnv *, jclass, jint, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJ
+ * Method:    getScalingFactors
+ * Signature: ()[Lorg/libjpegturbo/turbojpeg/TJ/ScalingFactor;
+ */
+JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
+  (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/java/org_libjpegturbo_turbojpeg_TJCompressor.h b/java/org_libjpegturbo_turbojpeg_TJCompressor.h
new file mode 100644
index 0000000..59f81e3
--- /dev/null
+++ b/java/org_libjpegturbo_turbojpeg_TJCompressor.h
@@ -0,0 +1,61 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_libjpegturbo_turbojpeg_TJCompressor */
+
+#ifndef _Included_org_libjpegturbo_turbojpeg_TJCompressor
+#define _Included_org_libjpegturbo_turbojpeg_TJCompressor
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJCompressor
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJCompressor
+ * Method:    destroy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJCompressor
+ * Method:    compress
+ * Signature: ([BIIII[BIII)I
+ */
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
+  (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jbyteArray, jint, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJCompressor
+ * Method:    compress
+ * Signature: ([IIIII[BIII)I
+ */
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
+  (JNIEnv *, jobject, jintArray, jint, jint, jint, jint, jbyteArray, jint, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJCompressor
+ * Method:    encodeYUV
+ * Signature: ([BIIII[BII)V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
+  (JNIEnv *, jobject, jbyteArray, jint, jint, jint, jint, jbyteArray, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJCompressor
+ * Method:    encodeYUV
+ * Signature: ([IIIII[BII)V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
+  (JNIEnv *, jobject, jintArray, jint, jint, jint, jint, jbyteArray, jint, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/java/org_libjpegturbo_turbojpeg_TJDecompressor.h b/java/org_libjpegturbo_turbojpeg_TJDecompressor.h
new file mode 100644
index 0000000..6b67296
--- /dev/null
+++ b/java/org_libjpegturbo_turbojpeg_TJDecompressor.h
@@ -0,0 +1,61 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_libjpegturbo_turbojpeg_TJDecompressor */
+
+#ifndef _Included_org_libjpegturbo_turbojpeg_TJDecompressor
+#define _Included_org_libjpegturbo_turbojpeg_TJDecompressor
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
+ * Method:    destroy
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
+ * Method:    decompressHeader
+ * Signature: ([BI)V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
+  (JNIEnv *, jobject, jbyteArray, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
+ * Method:    decompress
+ * Signature: ([BI[BIIIII)V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
+  (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint, jint, jint, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
+ * Method:    decompress
+ * Signature: ([BI[IIIIII)V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
+  (JNIEnv *, jobject, jbyteArray, jint, jintArray, jint, jint, jint, jint, jint);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJDecompressor
+ * Method:    decompressToYUV
+ * Signature: ([BI[BI)V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV
+  (JNIEnv *, jobject, jbyteArray, jint, jbyteArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/java/org_libjpegturbo_turbojpeg_TJTransformer.h b/java/org_libjpegturbo_turbojpeg_TJTransformer.h
new file mode 100644
index 0000000..a9dad4d
--- /dev/null
+++ b/java/org_libjpegturbo_turbojpeg_TJTransformer.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class org_libjpegturbo_turbojpeg_TJTransformer */
+
+#ifndef _Included_org_libjpegturbo_turbojpeg_TJTransformer
+#define _Included_org_libjpegturbo_turbojpeg_TJTransformer
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJTransformer
+ * Method:    init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
+  (JNIEnv *, jobject);
+
+/*
+ * Class:     org_libjpegturbo_turbojpeg_TJTransformer
+ * Method:    transform
+ * Signature: ([BI[[B[Lorg/libjpegturbo/turbojpeg/TJTransform;I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
+  (JNIEnv *, jobject, jbyteArray, jint, jobjectArray, jobjectArray, jint);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/jccolor.c b/jccolor.c
index b374c8b..9559aa5 100644
--- a/jccolor.c
+++ b/jccolor.c
@@ -81,74 +81,6 @@
 #define TABLE_SIZE	(8*(MAXJSAMPLE+1))
 
 
-#if BITS_IN_JSAMPLE == 8
-
-static const unsigned char red_lut[256] = {
-  0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 ,
-  5 , 5 , 5 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 8 , 8 , 8 , 9 , 9 , 9 ,
-  10, 10, 10, 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14,
-  14, 15, 15, 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19,
-  19, 19, 20, 20, 20, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 24,
-  24, 24, 25, 25, 25, 25, 26, 26, 26, 27, 27, 27, 28, 28, 28, 28,
-  29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33,
-  33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 38, 38,
-  38, 39, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 42, 43,
-  43, 43, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 47, 47, 47, 48,
-  48, 48, 48, 49, 49, 49, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52,
-  53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 56, 56, 56, 57, 57, 57,
-  57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 60, 61, 61, 61, 62, 62,
-  62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 65, 66, 66, 66, 67,
-  67, 67, 68, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 71,
-  72, 72, 72, 73, 73, 73, 74, 74, 74, 74, 75, 75, 75, 76, 76, 76
-};
-
-static const unsigned char green_lut[256] = {
-  0  , 1  , 1  , 2  , 2  , 3  , 4  , 4  , 5  , 5  , 6  , 6  ,
-  7  , 8  , 8  , 9  , 9  , 10 , 11 , 11 , 12 , 12 , 13 , 14 ,
-  14 , 15 , 15 , 16 , 16 , 17 , 18 , 18 , 19 , 19 , 20 , 21 ,
-  21 , 22 , 22 , 23 , 23 , 24 , 25 , 25 , 26 , 26 , 27 , 28 ,
-  28 , 29 , 29 , 30 , 31 , 31 , 32 , 32 , 33 , 33 , 34 , 35 ,
-  35 , 36 , 36 , 37 , 38 , 38 , 39 , 39 , 40 , 41 , 41 , 42 ,
-  42 , 43 , 43 , 44 , 45 , 45 , 46 , 46 , 47 , 48 , 48 , 49 ,
-  49 , 50 , 50 , 51 , 52 , 52 , 53 , 53 , 54 , 55 , 55 , 56 ,
-  56 , 57 , 58 , 58 , 59 , 59 , 60 , 60 , 61 , 62 , 62 , 63 ,
-  63 , 64 , 65 , 65 , 66 , 66 , 67 , 68 , 68 , 69 , 69 , 70 ,
-  70 , 71 , 72 , 72 , 73 , 73 , 74 , 75 , 75 , 76 , 76 , 77 ,
-  77 , 78 , 79 , 79 , 80 , 80 , 81 , 82 , 82 , 83 , 83 , 84 ,
-  85 , 85 , 86 , 86 , 87 , 87 , 88 , 89 , 89 , 90 , 90 , 91 ,
-  92 , 92 , 93 , 93 , 94 , 95 , 95 , 96 , 96 , 97 , 97 , 98 ,
-  99 , 99 , 100, 100, 101, 102, 102, 103, 103, 104, 104, 105,
-  106, 106, 107, 107, 108, 109, 109, 110, 110, 111, 112, 112,
-  113, 113, 114, 114, 115, 116, 116, 117, 117, 118, 119, 119,
-  120, 120, 121, 122, 122, 123, 123, 124, 124, 125, 126, 126,
-  127, 127, 128, 129, 129, 130, 130, 131, 131, 132, 133, 133,
-  134, 134, 135, 136, 136, 137, 137, 138, 139, 139, 140, 140,
-  141, 141, 142, 143, 143, 144, 144, 145, 146, 146, 147, 147,
-  148, 149, 149, 150
-};
-
-static const unsigned char blue_lut[256] = {
-  0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 2 , 2 ,
-  2 , 2 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 4 ,
-  4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ,
-  5 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 6 , 7 , 7 , 7 , 7 , 7 , 7 ,
-  7 , 7 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 8 , 9 , 9 , 9 , 9 , 9 ,
-  9 , 9 , 9 , 9 , 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11,
-  11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13,
-  13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14,
-  15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
-  16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18,
-  18, 18, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 20, 20, 20,
-  20, 20, 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22,
-  22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, 23, 24,
-  24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25,
-  26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27,
-  27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29
-};
-
-#endif
-
-
 /*
  * Initialize for RGB->YCC colorspace conversion.
  */
@@ -209,6 +141,10 @@
   register JSAMPROW outptr0, outptr1, outptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->image_width;
+  int rindex = rgb_red[cinfo->in_color_space];
+  int gindex = rgb_green[cinfo->in_color_space];
+  int bindex = rgb_blue[cinfo->in_color_space];
+  int rgbstride = rgb_pixelsize[cinfo->in_color_space];
 
   while (--num_rows >= 0) {
     inptr = *input_buf++;
@@ -217,10 +153,10 @@
     outptr2 = output_buf[2][output_row];
     output_row++;
     for (col = 0; col < num_cols; col++) {
-      r = GETJSAMPLE(inptr[rgb_red[cinfo->in_color_space]]);
-      g = GETJSAMPLE(inptr[rgb_green[cinfo->in_color_space]]);
-      b = GETJSAMPLE(inptr[rgb_blue[cinfo->in_color_space]]);
-      inptr += rgb_pixelsize[cinfo->in_color_space];
+      r = GETJSAMPLE(inptr[rindex]);
+      g = GETJSAMPLE(inptr[gindex]);
+      b = GETJSAMPLE(inptr[bindex]);
+      inptr += rgbstride;
       /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
        * must be too; we do not need an explicit range-limiting operation.
        * Hence the value being shifted is never negative, and we don't
@@ -258,13 +194,12 @@
 		  JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
 		  JDIMENSION output_row, int num_rows)
 {
-  #if BITS_IN_JSAMPLE != 8
   my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
+  register int r, g, b;
   register INT32 * ctab = cconvert->rgb_ycc_tab;
-  #endif
   register JSAMPROW inptr;
   register JSAMPROW outptr;
-  JSAMPLE *maxoutptr;
+  register JDIMENSION col;
   JDIMENSION num_cols = cinfo->image_width;
   int rindex = rgb_red[cinfo->in_color_space];
   int gindex = rgb_green[cinfo->in_color_space];
@@ -274,20 +209,16 @@
   while (--num_rows >= 0) {
     inptr = *input_buf++;
     outptr = output_buf[0][output_row];
-    maxoutptr = &outptr[num_cols];
     output_row++;
-    for (; outptr < maxoutptr; outptr++, inptr += rgbstride) {
+    for (col = 0; col < num_cols; col++) {
+      r = GETJSAMPLE(inptr[rindex]);
+      g = GETJSAMPLE(inptr[gindex]);
+      b = GETJSAMPLE(inptr[bindex]);
+      inptr += rgbstride;
       /* Y */
-      #if BITS_IN_JSAMPLE == 8
-      *outptr = red_lut[inptr[rindex]] + green_lut[inptr[gindex]]
-	    + blue_lut[inptr[bindex]];
-      #else
-      *outptr = (JSAMPLE)
-	    ((ctab[GETJSAMPLE(inptr[rindex])+R_Y_OFF]
-	     + ctab[GETJSAMPLE(inptr[gindex])+G_Y_OFF]
-	     + ctab[GETJSAMPLE(inptr[bindex])+B_Y_OFF])
-	     >> SCALEBITS);
-      #endif
+      outptr[col] = (JSAMPLE)
+		((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
+		 >> SCALEBITS);
     }
   }
 }
@@ -489,8 +420,12 @@
              cinfo->in_color_space == JCS_EXT_BGRX ||
              cinfo->in_color_space == JCS_EXT_XBGR ||
              cinfo->in_color_space == JCS_EXT_XRGB) {
-      cconvert->pub.start_pass = rgb_ycc_start;
-      cconvert->pub.color_convert = rgb_gray_convert;
+      if (jsimd_can_rgb_gray())
+        cconvert->pub.color_convert = jsimd_rgb_gray_convert;
+      else {
+        cconvert->pub.start_pass = rgb_ycc_start;
+        cconvert->pub.color_convert = rgb_gray_convert;
+      }
     } else if (cinfo->in_color_space == JCS_YCbCr)
       cconvert->pub.color_convert = grayscale_convert;
     else
diff --git a/jdcolor.c b/jdcolor.c
index bc73b3f..0af024c 100644
--- a/jdcolor.c
+++ b/jdcolor.c
@@ -130,6 +130,10 @@
   register JSAMPROW inptr0, inptr1, inptr2;
   register JDIMENSION col;
   JDIMENSION num_cols = cinfo->output_width;
+  int rindex = rgb_red[cinfo->out_color_space];
+  int gindex = rgb_green[cinfo->out_color_space];
+  int bindex = rgb_blue[cinfo->out_color_space];
+  int rgbstride = rgb_pixelsize[cinfo->out_color_space];
   /* copy these pointers into registers if possible */
   register JSAMPLE * range_limit = cinfo->sample_range_limit;
   register int * Crrtab = cconvert->Cr_r_tab;
@@ -149,12 +153,12 @@
       cb = GETJSAMPLE(inptr1[col]);
       cr = GETJSAMPLE(inptr2[col]);
       /* Range-limiting is essential due to noise introduced by DCT losses. */
-      outptr[rgb_red[cinfo->out_color_space]] =   range_limit[y + Crrtab[cr]];
-      outptr[rgb_green[cinfo->out_color_space]] = range_limit[y +
+      outptr[rindex] =   range_limit[y + Crrtab[cr]];
+      outptr[gindex] = range_limit[y +
 			      ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
 						 SCALEBITS))];
-      outptr[rgb_blue[cinfo->out_color_space]] =  range_limit[y + Cbbtab[cb]];
-      outptr += rgb_pixelsize[cinfo->out_color_space];
+      outptr[bindex] =  range_limit[y + Cbbtab[cb]];
+      outptr += rgbstride;
     }
   }
 }
diff --git a/jpegtran.c b/jpegtran.c
index 73dbe53..f861464 100644
--- a/jpegtran.c
+++ b/jpegtran.c
@@ -142,6 +142,7 @@
   transformoption.trim = FALSE;
   transformoption.force_grayscale = FALSE;
   transformoption.crop = FALSE;
+  transformoption.slow_hflip = FALSE;
   cinfo->err->trace_level = 0;
 
   /* Scan command line options, adjust parameters */
diff --git a/jpegut.c b/jpegut.c
index 3bbcb89..a96dbbf 100644
--- a/jpegut.c
+++ b/jpegut.c
@@ -17,23 +17,35 @@
 #include <stdlib.h>
 #include <string.h>
 #include "./rrtimer.h"
+#include "./rrutil.h"
 #include "./turbojpeg.h"
-#ifndef _WIN32
- #define stricmp strcasecmp
-#endif
 
 #define _catch(f) {if((f)==-1) {printf("TJPEG: %s\n", tjGetErrorStr());  bailout();}}
 
-const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
-const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
-const int _hsf[NUMSUBOPT]={1, 2, 2, 1};
-const int _vsf[NUMSUBOPT]={1, 1, 2, 1};
+const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"};
+const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"};
+
+#define NUMPF 7
+enum {RGB=0, BGR, RGBX, BGRX, XBGR, XRGB, GRAY};
+const int _ps[NUMPF]={3, 3, 4, 4, 4, 4, 1};
+const int _roffset[NUMPF]={0, 2, 0, 2, 3, 1, 0};
+const int _goffset[NUMPF]={1, 1, 1, 1, 2, 2, 0};
+const int _boffset[NUMPF]={2, 0, 2, 0, 1, 3, 0};
+const int _flags[NUMPF]={0, TJ_BGR, 0, TJ_BGR, TJ_BGR|TJ_ALPHAFIRST,
+	TJ_ALPHAFIRST, 0};
+const char *_pfstr[NUMPF]={"RGB", "BGR", "RGBX", "BGRX", "XBGR", "XRGB",
+	"Grayscale"};
+
+const int _3byteformats[]={RGB, BGR};
+const int _4byteformats[]={RGBX, BGRX, XBGR, XRGB};
+const int _onlygray[]={GRAY};
+const int _onlyrgb[]={RGB};
 
 enum {YUVENCODE=1, YUVDECODE};
 int yuv=0;
 
 int exitstatus=0;
-#define bailout() {exitstatus=-1;  goto finally;}
+#define bailout() {exitstatus=-1;  goto bailout;}
 
 int pixels[9][3]=
 {
@@ -48,13 +60,13 @@
 	{255, 0, 0}
 };
 
-void initbuf(unsigned char *buf, int w, int h, int ps, int flags)
+void initbuf(unsigned char *buf, int w, int h, int pf, int flags)
 {
-	int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
-		_i, j;
-	if(flags&TJ_ALPHAFIRST) {roffset++;  goffset++;  boffset++;}
+	int ps=_ps[pf], i, _i, j;
+	int roffset=_roffset[pf], goffset=_goffset[pf], boffset=_boffset[pf];
+
 	memset(buf, 0, w*h*ps);
-	if(ps==1)
+	if(pf==GRAY)
 	{
 		for(_i=0; _i<16; _i++)
 		{
@@ -103,109 +115,6 @@
 	}
 }
 
-void dumpbuf(unsigned char *buf, int w, int h, int ps, int flags)
-{
-	int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
-		j;
-	printf("\n");
-	for(i=0; i<h; i++)
-	{
-		for(j=0; j<w; j++)
-		{
-			printf("%.3d/%.3d/%.3d ", buf[(w*i+j)*ps+roffset],
-				buf[(w*i+j)*ps+goffset], buf[(w*i+j)*ps+boffset]);
-		}
-		printf("\n");
-	}
-}
-
-int checkbuf(unsigned char *buf, int w, int h, int ps, int subsamp, int flags)
-{
-	int roffset=(flags&TJ_BGR)?2:0, goffset=1, boffset=(flags&TJ_BGR)?0:2, i,
-		_i, j;
-	if(flags&TJ_ALPHAFIRST) {roffset++;  goffset++;  boffset++;}
-	if(ps==1) roffset=goffset=boffset=0;
-	if(subsamp==TJ_GRAYSCALE)
-	{
-		for(_i=0; _i<16; _i++)
-		{
-			if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-			for(j=0; j<w; j++)
-			{
-				unsigned char r=buf[(w*i+j)*ps+roffset],
-					g=buf[(w*i+j)*ps+goffset],
-					b=buf[(w*i+j)*ps+boffset];
-				if(((_i/8)+(j/8))%2==0)
-				{
-					if(r<253 || g<253 || b<253) return 0;
-				}
-				else
-				{
-					if(r<74 || r>78 || g<74 || g>78 || b<74 || b>78) return 0;
-				}
-			}
-		}
-		for(_i=16; _i<h; _i++)
-		{
-			if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-			for(j=0; j<w; j++)
-			{
-				unsigned char r=buf[(w*i+j)*ps+roffset],
-					g=buf[(w*i+j)*ps+goffset],
-					b=buf[(w*i+j)*ps+boffset];
-				if(((_i/8)+(j/8))%2==0)
-				{
-					if(r>2 || g>2 || b>2) return 0;
-				}
-				else
-				{
-					if(r<224 || r>228 || g<224 || g>228 || b<224 || b>228) return 0;
-				}
-			}
-		}
-	}
-	else
-	{
-		for(_i=0; _i<16; _i++)
-		{
-			if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-			for(j=0; j<w; j++)
-			{
-				if(buf[(w*i+j)*ps+roffset]<253) return 0;
-				if(((_i/8)+(j/8))%2==0)
-				{
-					if(buf[(w*i+j)*ps+goffset]<253) return 0;
-					if(buf[(w*i+j)*ps+boffset]<253) return 0;
-				}
-				else
-				{
-					if(buf[(w*i+j)*ps+goffset]>2) return 0;
-					if(buf[(w*i+j)*ps+boffset]>2) return 0;
-				}
-			}
-		}
-		for(_i=16; _i<h; _i++)
-		{
-			if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
-			for(j=0; j<w; j++)
-			{
-				if(buf[(w*i+j)*ps+boffset]>2) return 0;
-				if(((_i/8)+(j/8))%2==0)
-				{
-					if(buf[(w*i+j)*ps+roffset]>2) return 0;
-					if(buf[(w*i+j)*ps+goffset]>2) return 0;
-				}
-				else
-				{
-					if(buf[(w*i+j)*ps+roffset]<253) return 0;
-					if(buf[(w*i+j)*ps+goffset]<253) return 0;
-				}
-			}
-		}
-	}
-	return 1;
-}
-
 #define checkval(v, cv) { \
 	if(v<cv-1 || v>cv+1) { \
 		printf("\nComp. %s at %d,%d should be %d, not %d\n", #v, i, j, cv, v); \
@@ -224,12 +133,88 @@
 		retval=0;  goto bailout; \
 	}}
 
+int checkbuf(unsigned char *buf, int w, int h, int pf, int subsamp,
+	int scale_num, int scale_denom, int flags)
+{
+	int ps=_ps[pf];
+	int roffset=_roffset[pf], goffset=_goffset[pf], boffset=_boffset[pf];
+	int i, _i, j, retval=1;
+	int halfway=16*scale_num/scale_denom, blocksize=8*scale_num/scale_denom;
+
+	for(_i=0; _i<halfway; _i++)
+	{
+		if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
+		for(j=0; j<w; j++)
+		{
+			unsigned char r=buf[(w*i+j)*ps+roffset],
+				g=buf[(w*i+j)*ps+goffset],
+				b=buf[(w*i+j)*ps+boffset];
+			if(((_i/blocksize)+(j/blocksize))%2==0)
+			{
+				checkval255(r);  checkval255(g);  checkval255(b);
+			}
+			else
+			{
+				if(subsamp==TJ_GRAYSCALE)
+				{
+					checkval(r, 76);  checkval(g, 76);  checkval(b, 76);
+				}
+				else
+				{
+					checkval255(r);  checkval0(g);  checkval0(b);
+				}
+			}
+		}
+	}
+	for(_i=halfway; _i<h; _i++)
+	{
+		if(flags&TJ_BOTTOMUP) i=h-_i-1;  else i=_i;
+		for(j=0; j<w; j++)
+		{
+			unsigned char r=buf[(w*i+j)*ps+roffset],
+				g=buf[(w*i+j)*ps+goffset],
+				b=buf[(w*i+j)*ps+boffset];
+			if(((_i/blocksize)+(j/blocksize))%2==0)
+			{
+				checkval0(r);  checkval0(g);  checkval0(b);
+			}
+			else
+			{
+				if(subsamp==TJ_GRAYSCALE)
+				{
+					checkval(r, 226);  checkval(g, 226);  checkval(b, 226);
+				}
+				else
+				{
+					checkval255(r);  checkval255(g);  checkval0(b);
+				}
+			}
+		}
+	}
+
+	bailout:
+	if(retval==0)
+	{
+		printf("\n");
+		for(i=0; i<h; i++)
+		{
+			for(j=0; j<w; j++)
+			{
+				printf("%.3d/%.3d/%.3d ", buf[(w*i+j)*ps+roffset],
+					buf[(w*i+j)*ps+goffset], buf[(w*i+j)*ps+boffset]);
+			}
+			printf("\n");
+		}
+	}
+	return retval;
+}
+
 #define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
 
 int checkbufyuv(unsigned char *buf, int w, int h, int subsamp)
 {
 	int i, j;
-	int hsf=_hsf[subsamp], vsf=_vsf[subsamp];
+	int hsf=tjmcuw[subsamp]/8, vsf=tjmcuh[subsamp]/8;
 	int pw=PAD(w, hsf), ph=PAD(h, vsf);
 	int cw=pw/hsf, ch=ph/vsf;
 	int ypitch=PAD(pw, 4), uvpitch=PAD(cw, 4);
@@ -318,7 +303,8 @@
 	return retval;
 }
 
-void writejpeg(unsigned char *jpegbuf, unsigned long jpgbufsize, char *filename)
+void writejpeg(unsigned char *jpegbuf, unsigned long jpgbufsize,
+	char *filename)
 {
 	FILE *outfile=NULL;
 	if((outfile=fopen(filename, "wb"))==NULL)
@@ -332,60 +318,50 @@
 		bailout();
 	}
 
-	finally:
+	bailout:
 	if(outfile) fclose(outfile);
 }
 
 void gentestjpeg(tjhandle hnd, unsigned char *jpegbuf, unsigned long *size,
-	int w, int h, int ps, char *basefilename, int subsamp, int qual, int flags)
+	int w, int h, int pf, char *basefilename, int subsamp, int qual, int flags)
 {
 	char tempstr[1024];  unsigned char *bmpbuf=NULL;
-	const char *pixformat;  double t;
+	int ps=_ps[pf];  double t;
 
-	if(flags&TJ_BGR)
-	{
-		if(ps==3) pixformat="BGR";
-		else {if(flags&TJ_ALPHAFIRST) pixformat="XBGR";  else pixformat="BGRX";}
-	}
-	else
-	{
-		if(ps==3) pixformat="RGB";
-		else {if(flags&TJ_ALPHAFIRST) pixformat="XRGB";  else pixformat="RGBX";}
-	}
-	if(ps==1) pixformat="Grayscale";
 	if(yuv==YUVENCODE)
-		printf("%s %s -> %s YUV ... ", pixformat,
+		printf("%s %s -> %s YUV ... ", _pfstr[pf],
 			(flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ", _subnamel[subsamp]);
 	else
-		printf("%s %s -> %s Q%d ... ", pixformat,
+		printf("%s %s -> %s Q%d ... ", _pfstr[pf],
 			(flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ", _subnamel[subsamp], qual);
 
 	if((bmpbuf=(unsigned char *)malloc(w*h*ps+1))==NULL)
 	{
 		printf("ERROR: Could not allocate buffer\n");  bailout();
 	}
-	initbuf(bmpbuf, w, h, ps, flags);
+	initbuf(bmpbuf, w, h, pf, flags);
 	memset(jpegbuf, 0,
 		yuv==YUVENCODE? TJBUFSIZEYUV(w, h, subsamp):TJBUFSIZE(w, h));
 
 	t=rrtime();
 	if(yuv==YUVENCODE)
 	{
-		_catch(tjEncodeYUV(hnd, bmpbuf, w, 0, h, ps, jpegbuf, subsamp, flags));
+		_catch(tjEncodeYUV(hnd, bmpbuf, w, 0, h, ps, jpegbuf, subsamp,
+			flags|_flags[pf]));
 		*size=TJBUFSIZEYUV(w, h, subsamp);
 	}
 	else
 	{
 		_catch(tjCompress(hnd, bmpbuf, w, 0, h, ps, jpegbuf, size, subsamp, qual,
-			flags));
+			flags|_flags[pf]));
 	}
 	t=rrtime()-t;
 
 	if(yuv==YUVENCODE)
-		sprintf(tempstr, "%s_enc_%s_%s_%s.yuv", basefilename, pixformat,
+		snprintf(tempstr, 1024, "%s_enc_%s_%s_%s.yuv", basefilename, _pfstr[pf],
 			(flags&TJ_BOTTOMUP)? "BU":"TD", _subnames[subsamp]);
 	else
-		sprintf(tempstr, "%s_enc_%s_%s_%sQ%d.jpg", basefilename, pixformat,
+		snprintf(tempstr, 1024, "%s_enc_%s_%s_%s_Q%d.jpg", basefilename, _pfstr[pf],
 			(flags&TJ_BOTTOMUP)? "BU":"TD", _subnames[subsamp], qual);
 	writejpeg(jpegbuf, *size, tempstr);
 	if(yuv==YUVENCODE)
@@ -396,44 +372,43 @@
 	else printf("Done.");
 	printf("  %f ms\n  Result in %s\n", t*1000., tempstr);
 
-	finally:
+	bailout:
 	if(bmpbuf) free(bmpbuf);
 }
 
-void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
-	int w, int h, int ps, char *basefilename, int subsamp, int flags)
+void _gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
+	int w, int h, int pf, char *basefilename, int subsamp, int flags,
+	int scale_num, int scale_denom)
 {
 	unsigned char *bmpbuf=NULL;
-	const char *pixformat;  int _w=0, _h=0;  double t;
+	int _hdrw=0, _hdrh=0, _hdrsubsamp=-1;  double t;
+	int scaledw=(w*scale_num+scale_denom-1)/scale_denom;
+	int scaledh=(h*scale_num+scale_denom-1)/scale_denom;
+	int ps=_ps[pf];
 	unsigned long size=0;
 
 	if(yuv==YUVENCODE) return;
 
-	if(flags&TJ_BGR)
-	{
-		if(ps==3) pixformat="BGR";
-		else {if(flags&TJ_ALPHAFIRST) pixformat="XBGR";  else pixformat="BGRX";}
-	}
-	else
-	{
-		if(ps==3) pixformat="RGB";
-		else {if(flags&TJ_ALPHAFIRST) pixformat="XRGB";  else pixformat="RGBX";}
-	}
-	if(ps==1) pixformat="Grayscale";
 	if(yuv==YUVDECODE)
 		printf("JPEG -> YUV %s ... ", _subnames[subsamp]);
 	else
-		printf("JPEG -> %s %s ... ", pixformat,
+	{
+		printf("JPEG -> %s %s ", _pfstr[pf],
 			(flags&TJ_BOTTOMUP)?"Bottom-Up":"Top-Down ");
+		if(scale_num!=1 || scale_denom!=1)
+			printf("%d/%d ... ", scale_num, scale_denom);
+		else printf("... ");
+	}
 
-	_catch(tjDecompressHeader(hnd, jpegbuf, jpegsize, &_w, &_h));
-	if(_w!=w || _h!=h)
+	_catch(tjDecompressHeader2(hnd, jpegbuf, jpegsize, &_hdrw, &_hdrh,
+		&_hdrsubsamp));
+	if(_hdrw!=w || _hdrh!=h || _hdrsubsamp!=subsamp)
 	{
 		printf("Incorrect JPEG header\n");  bailout();
 	}
 
 	if(yuv==YUVDECODE) size=TJBUFSIZEYUV(w, h, subsamp);
-	else size=w*h*ps+1;
+	else size=scaledw*scaledh*ps+1;
 	if((bmpbuf=(unsigned char *)malloc(size))==NULL)
 	{
 		printf("ERROR: Could not allocate buffer\n");  bailout();
@@ -443,12 +418,13 @@
 	t=rrtime();
 	if(yuv==YUVDECODE)
 	{
-		_catch(tjDecompressToYUV(hnd, jpegbuf, jpegsize, bmpbuf, flags));
+		_catch(tjDecompressToYUV(hnd, jpegbuf, jpegsize, bmpbuf,
+			flags|_flags[pf]));
 	}
 	else
 	{
-		_catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, w, w*ps, h, ps,
-			flags));
+		_catch(tjDecompress(hnd, jpegbuf, jpegsize, bmpbuf, scaledw, 0, scaledh,
+			ps, flags|_flags[pf]));
 	}
 	t=rrtime()-t;
 
@@ -459,23 +435,46 @@
 	}
 	else
 	{
-		if(checkbuf(bmpbuf, w, h, ps, subsamp, flags)) printf("Passed.");
-		else
-		{
-			printf("FAILED!");  exitstatus=-1;
-			dumpbuf(bmpbuf, w, h, ps, flags);
-		}
+		if(checkbuf(bmpbuf, scaledw, scaledh, pf, subsamp, scale_num, scale_denom,
+			flags)) printf("Passed.");
+		else {printf("FAILED!");  exitstatus=-1;}
 	}
-	printf("  %f ms\n\n", t*1000.);
+	printf("  %f ms\n", t*1000.);
 
-	finally:
+	bailout:
 	if(bmpbuf) free(bmpbuf);
 }
 
-void dotest(int w, int h, int ps, int subsamp, char *basefilename)
+void gentestbmp(tjhandle hnd, unsigned char *jpegbuf, unsigned long jpegsize,
+	int w, int h, int pf, char *basefilename, int subsamp, int flags)
+{
+	int i, n=0;
+	tjscalingfactor *sf=tjGetScalingFactors(&n);
+	if(!sf || !n) 
+	{
+		printf("Error in tjGetScalingFactors():\n%s\n", tjGetErrorStr());
+		bailout();
+	}
+
+	if((subsamp==TJ_444 || subsamp==TJ_GRAYSCALE) && !yuv)
+	{
+		for(i=0; i<n; i++)
+			_gentestbmp(hnd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
+				flags, sf[i].num, sf[i].denom);
+	}
+	else
+		_gentestbmp(hnd, jpegbuf, jpegsize, w, h, pf, basefilename, subsamp,
+			flags, 1, 1);
+
+	bailout:
+	printf("\n");
+}
+
+void dotest(int w, int h, const int *formats, int nformats, int subsamp,
+	char *basefilename)
 {
 	tjhandle hnd=NULL, dhnd=NULL;  unsigned char *jpegbuf=NULL;
-	unsigned long size;
+	unsigned long size;  int pfi, pf, i;
 
 	size=(yuv==YUVENCODE? TJBUFSIZEYUV(w, h, subsamp):TJBUFSIZE(w, h));
 	if((jpegbuf=(unsigned char *)malloc(size)) == NULL)
@@ -488,36 +487,24 @@
 	if((dhnd=tjInitDecompress())==NULL)
 		{printf("Error in tjInitDecompress():\n%s\n", tjGetErrorStr());  bailout();}
 
-	gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, 0);
-	gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, 0);
-
-	if(ps==1 || yuv==YUVDECODE) goto finally;
-
-	gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BGR);
-	gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BGR);
-
-	gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BOTTOMUP);
-	gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BOTTOMUP);
-
-	gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_BGR|TJ_BOTTOMUP);
-	gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_BGR|TJ_BOTTOMUP);
-
-	if(ps==4)
+	for(pfi=0; pfi<nformats; pfi++)
 	{
-		gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST);
-		gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST);
-
-		gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR);
-		gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BGR);
-
-		gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BOTTOMUP);
-		gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BOTTOMUP);
-
-		gentestjpeg(hnd, jpegbuf, &size, w, h, ps, basefilename, subsamp, 100, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
-		gentestbmp(dhnd, jpegbuf, size, w, h, ps, basefilename, subsamp, TJ_ALPHAFIRST|TJ_BGR|TJ_BOTTOMUP);
+		for(i=0; i<2; i++)
+		{
+			int flags=0;
+			if(i==1)
+			{
+				if(yuv==YUVDECODE) goto bailout;
+				else flags|=TJ_BOTTOMUP;
+			}
+			pf=formats[pfi];
+			gentestjpeg(hnd, jpegbuf, &size, w, h, pf, basefilename, subsamp, 100,
+				flags);
+			gentestbmp(dhnd, jpegbuf, size, w, h, pf, basefilename, subsamp, flags);
+		}
 	}
 
-	finally:
+	bailout:
 	if(hnd) tjDestroy(hnd);
 	if(dhnd) tjDestroy(dhnd);
 
@@ -571,7 +558,7 @@
 	}
 	printf("Done.      \n");
 
-	finally:
+	bailout:
 	if(bmpbuf) free(bmpbuf);  if(jpgbuf) free(jpgbuf);
 	if(hnd) tjDestroy(hnd);
 }
@@ -581,32 +568,36 @@
 	int doyuv=0;
 	if(argc>1 && !stricmp(argv[1], "-yuv")) doyuv=1;
 	if(doyuv) yuv=YUVENCODE;
-	dotest(35, 39, 3, TJ_444, "test");
-	dotest(39, 41, 4, TJ_444, "test");
+	dotest(35, 39, _3byteformats, 2, TJ_444, "test");
+	dotest(39, 41, _4byteformats, 4, TJ_444, "test");
 	if(doyuv)
 	{
-		dotest(41, 35, 3, TJ_422, "test");
-		dotest(35, 39, 4, TJ_422, "test");
-		dotest(39, 41, 3, TJ_420, "test");
-		dotest(41, 35, 4, TJ_420, "test");
+		dotest(41, 35, _3byteformats, 2, TJ_422, "test");
+		dotest(35, 39, _4byteformats, 4, TJ_422, "test");
+		dotest(39, 41, _3byteformats, 2, TJ_420, "test");
+		dotest(41, 35, _4byteformats, 4, TJ_420, "test");
+		dotest(35, 39, _3byteformats, 2, TJ_440, "test");
+		dotest(39, 41, _4byteformats, 4, TJ_440, "test");
 	}
-	dotest(35, 39, 1, TJ_GRAYSCALE, "test");
-	dotest(39, 41, 3, TJ_GRAYSCALE, "test");
-	dotest(41, 35, 4, TJ_GRAYSCALE, "test");
+	dotest(35, 39, _onlygray, 1, TJ_GRAYSCALE, "test");
+	dotest(39, 41, _3byteformats, 2, TJ_GRAYSCALE, "test");
+	dotest(41, 35, _4byteformats, 4, TJ_GRAYSCALE, "test");
 	if(!doyuv) dotest1();
 	if(doyuv)
 	{
 		yuv=YUVDECODE;
-		dotest(48, 48, 3, TJ_444, "test");
-		dotest(35, 39, 3, TJ_444, "test");
-		dotest(48, 48, 3, TJ_422, "test");
-		dotest(39, 41, 3, TJ_422, "test");
-		dotest(48, 48, 3, TJ_420, "test");
-		dotest(41, 35, 3, TJ_420, "test");
-		dotest(48, 48, 3, TJ_GRAYSCALE, "test");
-		dotest(35, 39, 3, TJ_GRAYSCALE, "test");
-		dotest(48, 48, 1, TJ_GRAYSCALE, "test");
-		dotest(39, 41, 1, TJ_GRAYSCALE, "test");
+		dotest(48, 48, _onlyrgb, 1, TJ_444, "test_yuv0");
+		dotest(35, 39, _onlyrgb, 1, TJ_444, "test_yuv1");
+		dotest(48, 48, _onlyrgb, 1, TJ_422, "test_yuv0");
+		dotest(39, 41, _onlyrgb, 1, TJ_422, "test_yuv1");
+		dotest(48, 48, _onlyrgb, 1, TJ_420, "test_yuv0");
+		dotest(41, 35, _onlyrgb, 1, TJ_420, "test_yuv1");
+		dotest(48, 48, _onlyrgb, 1, TJ_440, "test_yuv0");
+		dotest(35, 39, _onlyrgb, 1, TJ_440, "test_yuv1");
+		dotest(48, 48, _onlyrgb, 1, TJ_GRAYSCALE, "test_yuv0");
+		dotest(35, 39, _onlyrgb, 1, TJ_GRAYSCALE, "test_yuv1");
+		dotest(48, 48, _onlygray, 1, TJ_GRAYSCALE, "test_yuv0");
+		dotest(39, 41, _onlygray, 1, TJ_GRAYSCALE, "test_yuv1");
 	}
 
 	return exitstatus;
diff --git a/jpgtest.c b/jpgtest.c
index cac5ce3..ab4d9f8 100644
--- a/jpgtest.c
+++ b/jpgtest.c
@@ -24,16 +24,16 @@
 #include "./turbojpeg.h"
 
 #define _throw(op, err) {  \
-	printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err);  goto bailout;}
+	printf("ERROR in line %d while %s:\n%s\n", __LINE__, op, err);  \
+  retval=-1;  goto bailout;}
 #define _throwunix(m) _throw(m, strerror(errno))
 #define _throwtj(m) _throw(m, tjGetErrorStr())
 #define _throwbmp(m) _throw(m, bmpgeterr())
 
-#define PAD(v, p) ((v+(p)-1)&(~((p)-1)))
-
 enum {YUVENCODE=1, YUVDECODE};
 int forcemmx=0, forcesse=0, forcesse2=0, forcesse3=0, fastupsample=0,
-	decomponly=0, yuv=0;
+	decomponly=0, yuv=0, quiet=0, dotile=0, pf=BMP_BGR, bu=0, useppm=0,
+	scale_num=1, scale_denom=1;
 const int _ps[BMPPIXELFORMATS]={3, 4, 3, 4, 4, 4};
 const int _flags[BMPPIXELFORMATS]={0, 0, TJ_BGR, TJ_BGR,
 	TJ_BGR|TJ_ALPHAFIRST, TJ_ALPHAFIRST};
@@ -41,8 +41,11 @@
 const int _gindex[BMPPIXELFORMATS]={1, 1, 1, 1, 2, 2};
 const int _bindex[BMPPIXELFORMATS]={2, 2, 0, 0, 1, 3};
 const char *_pfname[]={"RGB", "RGBX", "BGR", "BGRX", "XBGR", "XRGB"};
-const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY"};
-const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY"};
+const char *_subnamel[NUMSUBOPT]={"4:4:4", "4:2:2", "4:2:0", "GRAY", "4:4:0"};
+const char *_subnames[NUMSUBOPT]={"444", "422", "420", "GRAY", "440"};
+tjscalingfactor *sf=NULL;  int nsf=0;
+int xformop=TJXFORM_NONE, xformopt=0;
+double benchtime=5.0;
 
 void printsigfig(double val, int figs)
 {
@@ -51,26 +54,175 @@
 	if(_l<0.)
 	{
 		l=(int)fabs(_l);
-		sprintf(format, "%%%d.%df", figs+l+2, figs+l);
+		snprintf(format, 80, "%%%d.%df", figs+l+2, figs+l);
 	}
 	else
 	{
 		l=(int)_l+1;
-		if(figs<=l) sprintf(format, "%%.0f");
-		else sprintf(format, "%%%d.%df", figs+1, figs-l);
+		if(figs<=l) snprintf(format, 80, "%%.0f");
+		else snprintf(format, 80, "%%%d.%df", figs+1, figs-l);
 	}	
 	printf(format, val);
 }
 
-void dotest(unsigned char *srcbuf, int w, int h, int pf, int bu,
-	int jpegsub, int qual, char *filename, int dotile, int useppm, int quiet)
+// Decompression test
+int decomptest(unsigned char *srcbuf, unsigned char **jpegbuf,
+	unsigned long *comptilesize, unsigned char *rgbbuf, int w, int h,
+	int jpegsub, int qual, char *filename, int tilesizex, int tilesizey)
+{
+	char tempstr[1024], sizestr[20]="\0", qualstr[6]="\0", *ptr;
+	FILE *outfile=NULL;  tjhandle hnd=NULL;
+	int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0)
+		|(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0)
+		|(fastupsample?TJ_FASTUPSAMPLE:0);
+	int i, j, ITER, rgbbufalloc=0, retval=0;
+	double start, elapsed;
+	int ps=_ps[pf];
+	int yuvsize=TJBUFSIZEYUV(w, h, jpegsub), bufsize;
+	int scaledw=(yuv==YUVDECODE)? w : (w*scale_num+scale_denom-1)/scale_denom;
+	int scaledh=(yuv==YUVDECODE)? h : (h*scale_num+scale_denom-1)/scale_denom;
+	int pitch=scaledw*ps;
+
+	if(qual>0)
+	{
+		snprintf(qualstr, 6, "_Q%d", qual);
+		qualstr[4]=0;
+	}
+
+	flags |= _flags[pf];
+	if(bu) flags |= TJ_BOTTOMUP;
+	if((hnd=tjInitDecompress())==NULL)
+		_throwtj("executing tjInitDecompress()");
+
+	bufsize=(yuv==YUVDECODE? yuvsize:pitch*h);
+	if(rgbbuf==NULL)
+	{
+		if((rgbbuf=(unsigned char *)malloc(bufsize)) == NULL)
+			_throwunix("allocating image buffer");
+		rgbbufalloc=1;
+	}
+	// Grey image means decompressor did nothing
+	memset(rgbbuf, 127, bufsize);
+
+	if(yuv==YUVDECODE)
+	{
+		if(tjDecompressToYUV(hnd, jpegbuf[0], comptilesize[0], rgbbuf, flags)==-1)
+			_throwtj("executing tjDecompressToYUV()");
+	}
+	else if(tjDecompress(hnd, jpegbuf[0], comptilesize[0], rgbbuf, scaledw,
+		pitch, scaledh, ps, flags)==-1)
+		_throwtj("executing tjDecompress()");
+	ITER=0;
+	start=rrtime();
+	do
+	{
+		int tilen=0;
+		for(i=0; i<h; i+=tilesizey)
+		{
+			for(j=0; j<w; j+=tilesizex)
+			{
+				int tempw=dotile? min(tilesizex, w-j):scaledw;
+				int temph=dotile? min(tilesizey, h-i):scaledh;
+				if(yuv==YUVDECODE)
+				{
+					if(tjDecompressToYUV(hnd, jpegbuf[tilen], comptilesize[tilen],
+						&rgbbuf[pitch*i+ps*j], flags)==-1)
+						_throwtj("executing tjDecompressToYUV()");
+				}
+				else if(tjDecompress(hnd, jpegbuf[tilen], comptilesize[tilen],
+					&rgbbuf[pitch*i+ps*j], tempw, pitch, temph, ps, flags)==-1)
+					_throwtj("executing tjDecompress()");
+				tilen++;
+			}
+		}
+		ITER++;
+	}	while((elapsed=rrtime()-start)<benchtime);
+	if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
+	hnd=NULL;
+	if(quiet)
+	{
+		printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4);
+		printf("\n");
+	}
+	else
+	{
+		printf("D--> Frame rate:           %f fps\n", (double)ITER/elapsed);
+		printf("     Dest. throughput:     %f Megapixels/sec\n",
+			(double)(w*h)/1000000.*(double)ITER/elapsed);
+	}
+	if(yuv==YUVDECODE)
+	{
+		snprintf(tempstr, 1024, "%s_%s%s.yuv", filename, _subnames[jpegsub],
+			qualstr);
+		if((outfile=fopen(tempstr, "wb"))==NULL)
+			_throwunix("opening YUV image for output");
+		if(fwrite(rgbbuf, yuvsize, 1, outfile)!=1)
+			_throwunix("writing YUV image");
+		fclose(outfile);  outfile=NULL;
+	}
+	else
+	{
+		if(scale_num!=1 || scale_denom!=1)
+			snprintf(sizestr, 20, "%d_%d", scale_num, scale_denom);
+		else if(tilesizex!=w || tilesizey!=h)
+			snprintf(sizestr, 20, "%dx%d", tilesizex, tilesizey);
+		else snprintf(sizestr, 20, "full");
+		if(decomponly)
+			snprintf(tempstr, 1024, "%s_%s.%s", filename, sizestr,
+				useppm?"ppm":"bmp");
+		else
+			snprintf(tempstr, 1024, "%s_%s%s_%s.%s", filename,
+				_subnames[jpegsub], qualstr, sizestr, useppm?"ppm":"bmp");
+		if(savebmp(tempstr, rgbbuf, scaledw, scaledh, pf, pitch, bu)==-1)
+			_throwbmp("saving bitmap");
+		ptr=strrchr(tempstr, '.');
+		snprintf(ptr, 1024-(ptr-tempstr), "-err.%s", useppm?"ppm":"bmp");
+		if(srcbuf && scale_num==1 && scale_denom==1)
+		{
+			if(!quiet)
+				printf("Computing compression error and saving to %s.\n", tempstr);
+			if(jpegsub==TJ_GRAYSCALE)
+			{
+				for(j=0; j<h; j++)
+				{
+					for(i=0; i<w*ps; i+=ps)
+					{
+						int y=(int)((double)srcbuf[w*ps*j+i+_rindex[pf]]*0.299
+							+ (double)srcbuf[w*ps*j+i+_gindex[pf]]*0.587
+							+ (double)srcbuf[w*ps*j+i+_bindex[pf]]*0.114 + 0.5);
+						if(y>255) y=255;  if(y<0) y=0;
+						rgbbuf[pitch*j+i+_rindex[pf]]=abs(rgbbuf[pitch*j+i+_rindex[pf]]-y);
+						rgbbuf[pitch*j+i+_gindex[pf]]=abs(rgbbuf[pitch*j+i+_gindex[pf]]-y);
+						rgbbuf[pitch*j+i+_bindex[pf]]=abs(rgbbuf[pitch*j+i+_bindex[pf]]-y);
+					}
+				}
+			}		
+			else
+			{
+				for(j=0; j<h; j++) for(i=0; i<w*ps; i++)
+					rgbbuf[pitch*j+i]=abs(rgbbuf[pitch*j+i]-srcbuf[w*ps*j+i]);
+			}
+			if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
+				_throwbmp("saving bitmap");
+		}
+	}
+
+	bailout:
+	if(outfile) {fclose(outfile);  outfile=NULL;}
+	if(hnd) {tjDestroy(hnd);  hnd=NULL;}
+	if(rgbbuf && rgbbufalloc) {free(rgbbuf);  rgbbuf=NULL;}
+	return retval;
+}
+
+void dotest(unsigned char *srcbuf, int w, int h, int jpegsub, int qual,
+	char *filename)
 {
 	char tempstr[1024];
 	FILE *outfile=NULL;  tjhandle hnd=NULL;
 	unsigned char **jpegbuf=NULL, *rgbbuf=NULL;
 	double start, elapsed;
 	int jpgbufsize=0, i, j, tilesizex=w, tilesizey=h, numtilesx=1, numtilesy=1,
-		ITER;
+		ITER, retval=0;
 	unsigned long *comptilesize=NULL;
 	int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0)
 		|(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0)
@@ -103,10 +255,15 @@
 		tilesizey*=2;  if(tilesizey>h) tilesizey=h;
 		numtilesx=(w+tilesizex-1)/tilesizex;
 		numtilesy=(h+tilesizey-1)/tilesizey;
-		if((comptilesize=(unsigned long *)malloc(sizeof(unsigned long)*numtilesx*numtilesy)) == NULL
-		|| (jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)*numtilesx*numtilesy)) == NULL)
-			_throwunix("allocating image buffers");
+
+		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
+			*numtilesx*numtilesy))==NULL)
+			_throwunix("allocating image buffer array");
+		if((comptilesize=(unsigned long *)malloc(sizeof(unsigned long)
+			*numtilesx*numtilesy))==NULL)
+			_throwunix("allocating image size array");
 		memset(jpegbuf, 0, sizeof(unsigned char *)*numtilesx*numtilesy);
+
 		for(i=0; i<numtilesx*numtilesy; i++)
 		{
 			if((jpegbuf[i]=(unsigned char *)malloc(
@@ -131,6 +288,7 @@
 		else if(tjCompress(hnd, rgbbuf, tilesizex, pitch, tilesizey, ps,
 			jpegbuf[0], &comptilesize[0], jpegsub, qual, flags)==-1)
 			_throwtj("executing tjCompress()");
+
 		ITER=0;
 		start=rrtime();
 		do
@@ -157,14 +315,10 @@
 				}
 			}
 			ITER++;
-		} while((elapsed=rrtime()-start)<5.);
+		} while((elapsed=rrtime()-start)<benchtime);
 		if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
 		hnd=NULL;
-		if(quiet==1)
-		{
-			if(tilesizex==w && tilesizey==h) printf("Full     \t");
-			else printf("%-4d %-4d\t", tilesizex, tilesizey);
-		}
+		if(quiet==1) printf("%-4d  %-4d\t", tilesizex, tilesizey);
 		if(quiet)
 		{
 			printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4);
@@ -174,8 +328,8 @@
 		}
 		else
 		{
-			if(tilesizex==w && tilesizey==h) printf("\nFull image\n");
-			else printf("\nTile size: %d x %d\n", tilesizex, tilesizey);
+			printf("\n%s size: %d x %d\n", dotile? "Tile":"Image", tilesizex,
+				tilesizey);
 			printf("C--> Frame rate:           %f fps\n", (double)ITER/elapsed);
 			printf("     Output image size:    %d bytes\n", jpgbufsize);
 			printf("     Compression ratio:    %f:1\n",
@@ -188,9 +342,10 @@
 		if(tilesizex==w && tilesizey==h)
 		{
 			if(yuv==YUVENCODE)
-				sprintf(tempstr, "%s_%s.yuv", filename, _subnames[jpegsub]);
+				snprintf(tempstr, 1024, "%s_%s.yuv", filename, _subnames[jpegsub]);
 			else
-				sprintf(tempstr, "%s_%sQ%d.jpg", filename, _subnames[jpegsub], qual);
+				snprintf(tempstr, 1024, "%s_%s_Q%d.jpg", filename, _subnames[jpegsub],
+					qual);
 			if((outfile=fopen(tempstr, "wb"))==NULL)
 				_throwunix("opening reference image");
 			if(fwrite(jpegbuf[0], jpgbufsize, 1, outfile)!=1)
@@ -204,114 +359,17 @@
 		}
 
 		// Decompression test
-		memset(rgbbuf, 127, max(yuvsize, pitch*h));  // Grey image means decompressor did nothing
-		if((hnd=tjInitDecompress())==NULL)
-			_throwtj("executing tjInitDecompress()");
-		if(yuv==YUVDECODE)
-		{
-			if(tjDecompressToYUV(hnd, jpegbuf[0], jpgbufsize, rgbbuf, flags)==-1)
-				_throwtj("executing tjDecompressToYUV()");
-		}
-		else if(tjDecompress(hnd, jpegbuf[0], jpgbufsize, rgbbuf, tilesizex, pitch,
-			tilesizey, ps, flags)==-1)
-			_throwtj("executing tjDecompress()");
-		ITER=0;
-		start=rrtime();
-		do
-		{
-			int tilen=0;
-			for(i=0; i<h; i+=tilesizey)
-			{
-				for(j=0; j<w; j+=tilesizex)
-				{
-					int tempw=min(tilesizex, w-j), temph=min(tilesizey, h-i);
-					if(yuv==YUVDECODE)
-					{
-						if(tjDecompressToYUV(hnd, jpegbuf[tilen], comptilesize[tilen],
-							&rgbbuf[pitch*i+ps*j], flags)==-1)
-							_throwtj("executing tjDecompressToYUV()");
-					}
-					else if(tjDecompress(hnd, jpegbuf[tilen], comptilesize[tilen],
-						&rgbbuf[pitch*i+ps*j], tempw, pitch, temph, ps, flags)==-1)
-						_throwtj("executing tjDecompress()");
-					tilen++;
-				}
-			}
-			ITER++;
-		}	while((elapsed=rrtime()-start)<5.);
-		if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
-		hnd=NULL;
-		if(quiet)
-		{
-			printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4);
-			printf("\n");
-		}
-		else
-		{
-			printf("D--> Frame rate:           %f fps\n", (double)ITER/elapsed);
-			printf("     Dest. throughput:     %f Megapixels/sec\n",
-				(double)(w*h)/1000000.*(double)ITER/elapsed);
-		}
-		if(yuv==YUVDECODE)
-		{
-			sprintf(tempstr, "%s_%sQ%d.yuv", filename, _subnames[jpegsub], qual);
-			if((outfile=fopen(tempstr, "wb"))==NULL)
-				_throwunix("opening YUV image for output");
-			if(fwrite(rgbbuf, yuvsize, 1, outfile)!=1)
-				_throwunix("writing YUV image");
-			fclose(outfile);  outfile=NULL;
-		}
-		else
-		{
-			if(tilesizex==w && tilesizey==h)
-				sprintf(tempstr, "%s_%sQ%d_full.%s", filename, _subnames[jpegsub], qual,
-					useppm?"ppm":"bmp");
-			else sprintf(tempstr, "%s_%sQ%d_%dx%d.%s", filename, _subnames[jpegsub],
-				qual, tilesizex, tilesizey, useppm?"ppm":"bmp");
-			if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
-				_throwbmp("saving bitmap");
-			sprintf(strrchr(tempstr, '.'), "-err.%s", useppm?"ppm":"bmp");
-			if(!quiet)
-				printf("Computing compression error and saving to %s.\n", tempstr);
-			if(jpegsub==TJ_GRAYSCALE)
-			{
-				for(j=0; j<h; j++)
-				{
-					for(i=0; i<w*ps; i+=ps)
-					{
-						int y=(int)((double)srcbuf[w*ps*j+i+_rindex[pf]]*0.299
-							+ (double)srcbuf[w*ps*j+i+_gindex[pf]]*0.587
-							+ (double)srcbuf[w*ps*j+i+_bindex[pf]]*0.114 + 0.5);
-						if(y>255) y=255;  if(y<0) y=0;
-						rgbbuf[pitch*j+i+_rindex[pf]]=abs(rgbbuf[pitch*j+i+_rindex[pf]]-y);
-						rgbbuf[pitch*j+i+_gindex[pf]]=abs(rgbbuf[pitch*j+i+_gindex[pf]]-y);
-						rgbbuf[pitch*j+i+_bindex[pf]]=abs(rgbbuf[pitch*j+i+_bindex[pf]]-y);
-					}
-				}
-			}		
-			else
-			{
-				for(j=0; j<h; j++) for(i=0; i<w*ps; i++)
-					rgbbuf[pitch*j+i]=abs(rgbbuf[pitch*j+i]-srcbuf[w*ps*j+i]);
-			}
-			if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
-				_throwbmp("saving bitmap");
-		}
+		if(decomptest(srcbuf, jpegbuf, comptilesize, rgbbuf, w, h, jpegsub, qual,
+			filename, tilesizex, tilesizey)==-1)
+			goto bailout;
 
 		// Cleanup
-		if(outfile) {fclose(outfile);  outfile=NULL;}
-		if(jpegbuf)
-		{
-			for(i=0; i<numtilesx*numtilesy; i++)
-				{if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;}
-			free(jpegbuf);  jpegbuf=NULL;
-		}
-		if(comptilesize) {free(comptilesize);  comptilesize=NULL;}
+		for(i=0; i<numtilesx*numtilesy; i++)
+			{if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;}
+		free(jpegbuf);  jpegbuf=NULL;
+		free(comptilesize);  comptilesize=NULL;
 	} while(tilesizex<w || tilesizey<h);
 
-	if(rgbbuf) {free(rgbbuf);  rgbbuf=NULL;}
-	return;
-
 	bailout:
 	if(outfile) {fclose(outfile);  outfile=NULL;}
 	if(jpegbuf)
@@ -327,126 +385,193 @@
 }
 
 
-void dodecomptest(char *filename, int pf, int bu, int useppm,
-	int quiet)
+void dodecomptest(char *filename)
 {
-	char tempstr[1024];
 	FILE *file=NULL;  tjhandle hnd=NULL;
-	unsigned char *jpegbuf=NULL, *rgbbuf=NULL;
-	double start, elapsed;
-	int w, h, ITER;
-	unsigned long jpgbufsize=0;
-	int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0)
-		|(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0)
-		|(fastupsample?TJ_FASTUPSAMPLE:0);
-	int ps=_ps[pf], pitch, jpegsub=-1;
+	unsigned char **jpegbuf=NULL, *srcbuf=NULL;
+	unsigned long *comptilesize=NULL, srcbufsize, jpgbufsize;
+	tjtransform *t=NULL;
+	int w=0, h=0, jpegsub=-1, _w, _h, _tilesizex, _tilesizey,
+		_numtilesx, _numtilesy, _jpegsub;
 	char *temp=NULL;
-	int yuvsize, bufsize;
+	int i, j, tilesizex, tilesizey, numtilesx, numtilesy, retval=0;
+	double start, elapsed;
+	int flags=(forcemmx?TJ_FORCEMMX:0)|(forcesse?TJ_FORCESSE:0)
+		|(forcesse2?TJ_FORCESSE2:0)|(forcesse3?TJ_FORCESSE3:0);
+	int ps=_ps[pf], tilen;
 
-	flags |= _flags[pf];
-	if(bu) flags |= TJ_BOTTOMUP;
+	useppm=1;
 
 	if((file=fopen(filename, "rb"))==NULL)
 		_throwunix("opening file");
-	if(fseek(file, 0, SEEK_END)<0 || (jpgbufsize=ftell(file))<0)
+	if(fseek(file, 0, SEEK_END)<0 || (srcbufsize=ftell(file))<0)
 		_throwunix("determining file size");
-	if((jpegbuf=(unsigned char *)malloc(jpgbufsize))==NULL)
+	if((srcbuf=(unsigned char *)malloc(srcbufsize))==NULL)
 		_throwunix("allocating memory");
 	if(fseek(file, 0, SEEK_SET)<0)
 		_throwunix("setting file position");
-	if(fread(jpegbuf, jpgbufsize, 1, file)<1)
+	if(fread(srcbuf, srcbufsize, 1, file)<1)
 		_throwunix("reading JPEG data");
 	fclose(file);  file=NULL;
 
 	temp=strrchr(filename, '.');
 	if(temp!=NULL) *temp='\0';
 
-	if((hnd=tjInitDecompress())==NULL) _throwtj("executing tjInitDecompress()");
-	if(tjDecompressHeader2(hnd, jpegbuf, jpgbufsize, &w, &h, &jpegsub)==-1)
+	if((hnd=tjInitTransform())==NULL) _throwtj("executing tjInitTransform()");
+	if(tjDecompressHeader2(hnd, srcbuf, srcbufsize, &w, &h, &jpegsub)==-1)
 		_throwtj("executing tjDecompressHeader2()");
 
-	yuvsize=TJBUFSIZEYUV(w, h, jpegsub);
+	if(yuv) dotile=0;
 
-	pitch=w*ps;
+	if(dotile) {tilesizex=tilesizey=8;}  else {tilesizex=w;  tilesizey=h;}
 
 	if(quiet==1)
 	{
 		printf("All performance values in Mpixels/sec\n\n");
-		printf("Bitmap\tBitmap\tImage Size\tDecomp\n"),
-		printf("Format\tOrder\t X    Y  \tPerf\n\n");
-		printf("%s\t%s\t%-4d %-4d\t", _pfname[pf], bu?"BU":"TD", w, h);
+		printf("Bitmap\tBitmap\tJPEG\t%s %s \tXform\tCompr\tDecomp\n",
+			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
+		printf("Format\tOrder\tFormat\tWidth Height\tPerf \tRatio\tPerf\n\n");
 	}
-
-	bufsize=(yuv==YUVDECODE? yuvsize:pitch*h);
-	if((rgbbuf=(unsigned char *)malloc(bufsize))==NULL)
-		_throwunix("allocating image buffer");
-
-	if(!quiet)
+	else if(!quiet)
 	{
-		if(yuv==YUVDECODE)
-			printf(">>>>>  JPEG --> YUV %s  <<<<<\n", _subnamel[jpegsub]);
-		else
-			printf(">>>>>  JPEG --> %s (%s)  <<<<<\n", _pfname[pf],
-				bu?"Bottom-up":"Top-down");
-		printf("\nImage size: %d x %d\n", w, h);
+		printf(">>>>>  JPEG %s --> %s (%s)  <<<<<\n", _subnamel[jpegsub],
+			_pfname[pf], bu?"Bottom-up":"Top-down");
 	}
 
-	memset(rgbbuf, 127, bufsize);  // Grey image means decompressor did nothing
-	if(yuv==YUVDECODE)
-	{
-		if(tjDecompressToYUV(hnd, jpegbuf, jpgbufsize, rgbbuf, flags)==-1)
-			_throwtj("executing tjDecompressToYUV()");
-	}
-	else if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps,
-		flags)==-1)
-		_throwtj("executing tjDecompress()");
-	ITER=0;
-	start=rrtime();
 	do
 	{
-		if(yuv==YUVDECODE)
+		tilesizex*=2;  if(tilesizex>w) tilesizex=w;
+		tilesizey*=2;  if(tilesizey>h) tilesizey=h;
+		numtilesx=(w+tilesizex-1)/tilesizex;
+		numtilesy=(h+tilesizey-1)/tilesizey;
+
+		if((jpegbuf=(unsigned char **)malloc(sizeof(unsigned char *)
+			*numtilesx*numtilesy))==NULL)
+			_throwunix("allocating image buffer array");
+		if((comptilesize=(unsigned long *)malloc(sizeof(unsigned long)
+			*numtilesx*numtilesy))==NULL)
+			_throwunix("allocating image size array");
+		memset(jpegbuf, 0, sizeof(unsigned char *)*numtilesx*numtilesy);
+
+		for(i=0; i<numtilesx*numtilesy; i++)
 		{
-			if(tjDecompressToYUV(hnd, jpegbuf, jpgbufsize, rgbbuf, flags)==-1)
-				_throwtj("executing tjDecompressToYUV()");
+			if((jpegbuf[i]=(unsigned char *)malloc(
+				TJBUFSIZE(tilesizex, tilesizey))) == NULL)
+				_throwunix("allocating image buffers");
 		}
-		else if(tjDecompress(hnd, jpegbuf, jpgbufsize, rgbbuf, w, pitch, h, ps,
-			flags)==-1)
-			_throwtj("executing tjDecompress()");
-		ITER++;
-	}	while((elapsed=rrtime()-start)<5.);
-	if(tjDestroy(hnd)==-1) _throwtj("executing tjDestroy()");
-	hnd=NULL;
-	if(quiet)
-	{
-		printsigfig((double)(w*h)/1000000.*(double)ITER/elapsed, 4);
-		printf("\n");
-	}
-	else
-	{
-		printf("D--> Frame rate:           %f fps\n", (double)ITER/elapsed);
-		printf("     Dest. throughput:     %f Megapixels/sec\n",
-			(double)(w*h)/1000000.*(double)ITER/elapsed);
-	}
-	sprintf(tempstr, "%s_full.%s", filename, useppm?"ppm":"bmp");
-	if(yuv==YUVDECODE)
-	{
-		sprintf(tempstr, "%s_%s.yuv", filename, _subnames[jpegsub]);
-		if((file=fopen(tempstr, "wb"))==NULL)
-			_throwunix("opening YUV image for output");
-		if(fwrite(rgbbuf, yuvsize, 1, file)!=1)
-			_throwunix("writing YUV image");
-		fclose(file);  file=NULL;
-	}
-	else
-	{
-		if(savebmp(tempstr, rgbbuf, w, h, pf, pitch, bu)==-1)
-			_throwbmp("saving bitmap");
-	}
+
+		_w=w;  _h=h;  _tilesizex=tilesizex;  _tilesizey=tilesizey;
+		if(!quiet)
+		{
+			printf("\n%s size: %d x %d", dotile? "Tile":"Image", _tilesizex,
+				_tilesizey);
+			if(scale_num!=1 || scale_denom!=1)
+				printf(" --> %d x %d", (_w*scale_num+scale_denom-1)/scale_denom,
+					(_h*scale_num+scale_denom-1)/scale_denom);
+			printf("\n");
+		}
+		else if(quiet==1)
+		{
+			printf("%s\t%s\t%s\t",  _pfname[pf], bu?"BU":"TD", _subnamel[jpegsub]);
+			printf("%-4d  %-4d\t", tilesizex, tilesizey);
+		}
+
+		_jpegsub=jpegsub;
+		if(dotile || xformop!=TJXFORM_NONE || xformopt!=0)
+		{
+			if((t=(tjtransform *)malloc(sizeof(tjtransform)*numtilesx*numtilesy))
+				==NULL)
+				_throwunix("allocating image transform array");
+
+			if(xformop==TJXFORM_TRANSPOSE || xformop==TJXFORM_TRANSVERSE
+				|| xformop==TJXFORM_ROT90 || xformop==TJXFORM_ROT270)
+			{
+				_w=h;  _h=w;  _tilesizex=tilesizey;  _tilesizey=tilesizex;
+			}
+
+			if(xformopt&TJXFORM_GRAY) _jpegsub=TJ_GRAYSCALE;
+			if(xformop==TJXFORM_HFLIP || xformop==TJXFORM_ROT180)
+				_w=_w-(_w%tjmcuw[_jpegsub]);
+			if(xformop==TJXFORM_VFLIP || xformop==TJXFORM_ROT180)
+				_h=_h-(_h%tjmcuh[_jpegsub]);
+			if(xformop==TJXFORM_TRANSVERSE || xformop==TJXFORM_ROT90)
+				_w=_w-(_w%tjmcuh[_jpegsub]);
+			if(xformop==TJXFORM_TRANSVERSE || xformop==TJXFORM_ROT270)
+				_h=_h-(_h%tjmcuw[_jpegsub]);
+			_numtilesx=(_w+_tilesizex-1)/_tilesizex;
+			_numtilesy=(_h+_tilesizey-1)/_tilesizey;
+
+			for(i=0, tilen=0; i<_h; i+=_tilesizey)
+			{
+				for(j=0; j<_w; j+=_tilesizex, tilen++)
+				{
+					t[tilen].r.w=min(_tilesizex, _w-j);
+					t[tilen].r.h=min(_tilesizey, _h-i);
+					t[tilen].r.x=j;
+					t[tilen].r.y=i;
+					t[tilen].op=xformop;
+					t[tilen].options=xformopt|TJXFORM_TRIM;
+				}
+			}
+
+			start=rrtime();
+			if(tjTransform(hnd, srcbuf, srcbufsize, _numtilesx*_numtilesy, jpegbuf,
+				comptilesize, t, flags)==-1)
+				_throwtj("executing tjTransform()");
+			elapsed=rrtime()-start;
+
+			for(tilen=0, jpgbufsize=0; tilen<_numtilesx*_numtilesy; tilen++)
+				jpgbufsize+=comptilesize[tilen];
+
+			if(quiet)
+			{
+				printsigfig((double)(w*h)/1000000./elapsed, 4);
+				printf("%c", quiet==2? '\n':'\t');
+				printsigfig((double)(w*h*ps)/(double)jpgbufsize, 4);
+				printf("%c", quiet==2? '\n':'\t');
+			}
+			else if(!quiet)
+			{
+				printf("X--> Frame rate:           %f fps\n", 1.0/elapsed);
+				printf("     Output image size:    %lu bytes\n", jpgbufsize);
+				printf("     Compression ratio:    %f:1\n",
+					(double)(w*h*ps)/(double)jpgbufsize);
+				printf("     Source throughput:    %f Megapixels/sec\n",
+					(double)(w*h)/1000000./elapsed);
+				printf("     Output bit stream:    %f Megabits/sec\n",
+					(double)jpgbufsize*8./1000000./elapsed);
+			}
+		}
+		else
+		{
+			if(quiet==1) printf("N/A\tN/A\t");
+			comptilesize[0]=srcbufsize;
+			memcpy(jpegbuf[0], srcbuf, srcbufsize);
+		}
+
+		if(w==tilesizex) _tilesizex=_w;
+		if(h==tilesizey) _tilesizey=_h;
+		if(decomptest(NULL, jpegbuf, comptilesize, NULL, _w, _h, _jpegsub, 0,
+			filename, _tilesizex, _tilesizey)==-1)
+			goto bailout;
+
+		// Cleanup
+		for(i=0; i<numtilesx*numtilesy; i++)
+			{free(jpegbuf[i]);  jpegbuf[i]=NULL;}
+		free(jpegbuf);  jpegbuf=NULL;
+		if(comptilesize) {free(comptilesize);  comptilesize=NULL;}
+	} while(tilesizex<w || tilesizey<h);
 
 	bailout:
 	if(file) {fclose(file);  file=NULL;}
-	if(jpegbuf) {free(jpegbuf);  jpegbuf=NULL;}
-	if(rgbbuf) {free(rgbbuf);  rgbbuf=NULL;}
+	if(jpegbuf)
+	{
+		for(i=0; i<numtilesx*numtilesy; i++)
+			{if(jpegbuf[i]) free(jpegbuf[i]);  jpegbuf[i]=NULL;}
+		free(jpegbuf);  jpegbuf=NULL;
+	}
+	if(comptilesize) {free(comptilesize);  comptilesize=NULL;}
+	if(srcbuf) {free(srcbuf);  srcbuf=NULL;}
 	if(hnd) {tjDestroy(hnd);  hnd=NULL;}
 	return;
 }
@@ -454,36 +579,56 @@
 
 void usage(char *progname)
 {
-	printf("USAGE: %s <Inputfile (BMP|PPM))> <%% Quality>\n", progname);
-	printf("       %s <Inputfile (JPG))>\n\n", progname);
-	printf("       [-tile]\n");
-	printf("       Test performance of the codec when the image is encoded\n");
-	printf("       as separate tiles of varying sizes.\n\n");
-	printf("       [-forcemmx] [-forcesse] [-forcesse2] [-forcesse3]\n");
-	printf("       Force MMX, SSE, SSE2, or SSE3 code paths in the underlying codec\n\n");
-	printf("       [-rgb | -bgr | -rgbx | -bgrx | -xbgr | -xrgb]\n");
-	printf("       Test the specified color conversion path in the codec (default: BGR)\n\n");
-	printf("       [-fastupsample]\n");
-	printf("       Use fast, inaccurate upsampling code to perform 4:2:2 and 4:2:0\n");
-	printf("       YUV decoding in libjpeg decompressor\n\n");
-	printf("       [-quiet]\n");
-	printf("       Output in tabular rather than verbose format\n\n");
-	printf("       [-yuvencode]\n");
-	printf("       Encode RGB input as planar YUV rather than compressing as JPEG\n\n");
-	printf("       [-yuvdecode]\n");
-	printf("       Decode JPEG image to planar YUV rather than RGB\n\n");
-	printf("       NOTE: If the quality is specified as a range, i.e. 90-100, a separate\n");
-	printf("       test will be performed for all quality values in the range.\n");
+	int i;
+	printf("USAGE: %s\n", progname);
+	printf("       <Inputfile (BMP|PPM)> <%% Quality> [options]\n\n");
+	printf("       %s\n", progname);
+	printf("       <Inputfile (JPG)> [options]\n\n");
+	printf("Options:\n\n");
+	printf("-tile = Test performance of the codec when the image is encoded as separate\n");
+	printf("     tiles of varying sizes.\n");
+	printf("-forcemmx, -forcesse, -forcesse2, -forcesse3 =\n");
+	printf("     Force MMX, SSE, SSE2, or SSE3 code paths in the underlying codec\n");
+	printf("-rgb, -bgr, -rgbx, -bgrx, -xbgr, -xrgb =\n");
+	printf("     Test the specified color conversion path in the codec (default: BGR)\n");
+	printf("-fastupsample = Use fast, inaccurate upsampling code to perform 4:2:2 and 4:2:0\n");
+	printf("     YUV decoding in libjpeg decompressor\n");
+	printf("-quiet = Output results in tabular rather than verbose format\n");
+	printf("-yuvencode = Encode RGB input as planar YUV rather than compressing as JPEG\n");
+	printf("-yuvdecode = Decode JPEG image to planar YUV rather than RGB\n");
+	printf("-scale M/N = scale down the width/height of the decompressed JPEG image by a\n");
+	printf("     factor of M/N (M/N = ");
+	for(i=0; i<nsf; i++)
+	{
+		printf("%d/%d", sf[i].num, sf[i].denom);
+		if(nsf==2 && i!=nsf-1) printf(" or ");
+		else if(nsf>2)
+		{
+			if(i!=nsf-1) printf(", ");
+			if(i==nsf-2) printf("or ");
+		}
+	}
+	printf(")\n");
+	printf("-hflip, -vflip, -transpose, -transverse, -rot90, -rot180, -rot270 =\n");
+	printf("     Perform the corresponding lossless transform prior to\n");
+	printf("     decompression (these options are mutually exclusive)\n");
+	printf("-grayscale = Perform lossless grayscale conversion prior to decompression\n");
+	printf("     test (can be combined with the other transforms above)\n");
+	printf("-benchtime <t> = Run each benchmark for at least <t> seconds (default = 5.0)\n\n");
+	printf("NOTE:  If the quality is specified as a range (e.g. 90-100), a separate\n");
+	printf("test will be performed for all quality values in the range.\n\n");
 	exit(1);
 }
 
 
 int main(int argc, char *argv[])
 {
-	unsigned char *bmpbuf=NULL;  int w, h, i, useppm=0;
-	int qual=-1, dotile=0, quiet=0, hiqual=-1;  char *temp;
-	int pf=BMP_BGR;
-	int bu=0, minarg=2;
+	unsigned char *bmpbuf=NULL;  int w, h, i, j;
+	int qual=-1, hiqual=-1;  char *temp;
+	int minarg=2;  int retval=0;
+
+	if((sf=tjGetScalingFactors(&nsf))==NULL || nsf==0)
+		_throwtj("executing tjGetScalingFactors()");
 
 	if(argc<minarg) usage(argv[0]);
 
@@ -532,7 +677,10 @@
 	{
 		for(i=minarg; i<argc; i++)
 		{
-			if(!stricmp(argv[i], "-tile")) dotile=1;
+			if(!stricmp(argv[i], "-tile"))
+			{
+				dotile=1;  xformopt|=TJXFORM_CROP;
+			}
 			if(!stricmp(argv[i], "-forcesse3"))
 			{
 				printf("Using SSE3 code\n\n");
@@ -567,9 +715,47 @@
 			if(!stricmp(argv[i], "-bottomup")) bu=1;
 			if(!stricmp(argv[i], "-quiet")) quiet=1;
 			if(!stricmp(argv[i], "-qq")) quiet=2;
+			if(!stricmp(argv[i], "-scale") && i<argc-1)
+			{
+				int temp1=0, temp2=0, match=0;
+				if(sscanf(argv[++i], "%d/%d", &temp1, &temp2)==2)
+				{
+					for(j=0; j<nsf; j++)
+					{
+						if(temp1==sf[j].num && temp2==sf[j].denom)
+						{
+							scale_num=temp1;  scale_denom=temp2;
+							match=1;  break;
+						}
+					}
+					if(!match) usage(argv[0]);
+				}
+				else usage(argv[0]);
+			}
+			if(!stricmp(argv[i], "-hflip")) xformop=TJXFORM_HFLIP;
+			if(!stricmp(argv[i], "-vflip")) xformop=TJXFORM_VFLIP;
+			if(!stricmp(argv[i], "-transpose")) xformop=TJXFORM_TRANSPOSE;
+			if(!stricmp(argv[i], "-transverse")) xformop=TJXFORM_TRANSVERSE;
+			if(!stricmp(argv[i], "-rot90")) xformop=TJXFORM_ROT90;
+			if(!stricmp(argv[i], "-rot180")) xformop=TJXFORM_ROT180;
+			if(!stricmp(argv[i], "-rot270")) xformop=TJXFORM_ROT270;
+			if(!stricmp(argv[i], "-grayscale")) xformopt|=TJXFORM_GRAY;
+			if(!stricmp(argv[i], "-benchtime") && i<argc-1)
+			{
+				double temp=atof(argv[++i]);
+				if(temp>0.0) benchtime=temp;
+				else usage(argv[0]);
+			}
 		}
 	}
 
+	if((scale_num!=1 || scale_denom!=1) && dotile)
+	{
+		printf("Disabling tiled compression/decompression tests, because these tests do not\n");
+		printf("work when scaled decompression is enabled.\n");
+		dotile=0;
+	}
+
 	if(!decomponly)
 	{
 		if(loadbmp(argv[1], &bmpbuf, &w, &h, pf, 1, bu)==-1)
@@ -581,30 +767,31 @@
 	if(quiet==1 && !decomponly)
 	{
 		printf("All performance values in Mpixels/sec\n\n");
-		printf("Bitmap\tBitmap\tJPEG\tJPEG\tTile Size\tCompr\tCompr\tDecomp\n");
-		printf("Format\tOrder\tFormat\tQual\t X    Y  \tPerf \tRatio\tPerf\n\n");
+		printf("Bitmap\tBitmap\tJPEG\tJPEG\t%s %s \tCompr\tCompr\tDecomp\n",
+			dotile? "Tile ":"Image", dotile? "Tile ":"Image");
+		printf("Format\tOrder\tFormat\tQual\tWidth Height\tPerf \tRatio\tPerf\n\n");
 	}
 
 	if(decomponly)
 	{
-		dodecomptest(argv[1], pf, bu, 1, quiet);
+		dodecomptest(argv[1]);
 		printf("\n");
 		goto bailout;
 	}
 	for(i=hiqual; i>=qual; i--)
-		dotest(bmpbuf, w, h, pf, bu, TJ_GRAYSCALE, i, argv[1], dotile, useppm, quiet);
+		dotest(bmpbuf, w, h, TJ_GRAYSCALE, i, argv[1]);
 	printf("\n");
 	for(i=hiqual; i>=qual; i--)
-		dotest(bmpbuf, w, h, pf, bu, TJ_420, i, argv[1], dotile, useppm, quiet);
+		dotest(bmpbuf, w, h, TJ_420, i, argv[1]);
 	printf("\n");
 	for(i=hiqual; i>=qual; i--)
-		dotest(bmpbuf, w, h, pf, bu, TJ_422, i, argv[1], dotile, useppm, quiet);
+		dotest(bmpbuf, w, h, TJ_422, i, argv[1]);
 	printf("\n");
 	for(i=hiqual; i>=qual; i--)
-		dotest(bmpbuf, w, h, pf, bu, TJ_444, i, argv[1], dotile, useppm, quiet);
+		dotest(bmpbuf, w, h, TJ_444, i, argv[1]);
 	printf("\n");
 
 	bailout:
 	if(bmpbuf) free(bmpbuf);
-	return 0;
+	return retval;
 }
diff --git a/jsimd.h b/jsimd.h
index b663791..3fa2c43 100644
--- a/jsimd.h
+++ b/jsimd.h
@@ -2,6 +2,7 @@
  * jsimd.h
  *
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011 D. R. Commander
  * 
  * Based on the x86 SIMD extension for IJG JPEG library,
  * Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -13,8 +14,10 @@
 
 #ifdef NEED_SHORT_EXTERNAL_NAMES
 #define jsimd_can_rgb_ycc                 jSCanRgbYcc
+#define jsimd_can_rgb_gray                jSCanRgbGry
 #define jsimd_can_ycc_rgb                 jSCanYccRgb
 #define jsimd_rgb_ycc_convert             jSRgbYccConv
+#define jsimd_rgb_gray_convert            jSRgbGryConv
 #define jsimd_ycc_rgb_convert             jSYccRgbConv
 #define jsimd_can_h2v2_downsample         jSCanH2V2Down
 #define jsimd_can_h2v1_downsample         jSCanH2V1Down
@@ -35,12 +38,17 @@
 #endif /* NEED_SHORT_EXTERNAL_NAMES */
 
 EXTERN(int) jsimd_can_rgb_ycc JPP((void));
+EXTERN(int) jsimd_can_rgb_gray JPP((void));
 EXTERN(int) jsimd_can_ycc_rgb JPP((void));
 
 EXTERN(void) jsimd_rgb_ycc_convert
         JPP((j_compress_ptr cinfo,
              JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
              JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_rgb_gray_convert
+        JPP((j_compress_ptr cinfo,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
 EXTERN(void) jsimd_ycc_rgb_convert
         JPP((j_decompress_ptr cinfo,
              JSAMPIMAGE input_buf, JDIMENSION input_row,
diff --git a/jsimd_none.c b/jsimd_none.c
index 7ff3074..9787902 100644
--- a/jsimd_none.c
+++ b/jsimd_none.c
@@ -2,7 +2,7 @@
  * jsimd_none.c
  *
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright 2009 D. R. Commander
+ * Copyright 2009-2011 D. R. Commander
  * 
  * Based on the x86 SIMD extension for IJG JPEG library,
  * Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -25,6 +25,12 @@
 }
 
 GLOBAL(int)
+jsimd_can_rgb_gray (void)
+{
+  return 0;
+}
+
+GLOBAL(int)
 jsimd_can_ycc_rgb (void)
 {
   return 0;
@@ -38,6 +44,13 @@
 }
 
 GLOBAL(void)
+jsimd_rgb_gray_convert (j_compress_ptr cinfo,
+                        JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+                        JDIMENSION output_row, int num_rows)
+{
+}
+
+GLOBAL(void)
 jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
                        JSAMPIMAGE input_buf, JDIMENSION input_row,
                        JSAMPARRAY output_buf, int num_rows)
diff --git a/release/libjpeg-turbo.nsi.in b/release/libjpeg-turbo.nsi.in
index 6eb4bae..576e668 100755
--- a/release/libjpeg-turbo.nsi.in
+++ b/release/libjpeg-turbo.nsi.in
@@ -63,6 +63,10 @@
 	File "@CMAKE_BINARY_DIR@\sharedlib\${BUILDDIR}jpeg.lib"
 	File "@CMAKE_BINARY_DIR@\${BUILDDIR}jpeg-static.lib"
 !endif
+!ifdef JAVA
+	SetOutPath $INSTDIR\classes
+	File "@CMAKE_BINARY_DIR@\java\${BUILDDIR}turbojpeg.jar"
+!endif
 	SetOutPath $INSTDIR\include
 	File "@CMAKE_BINARY_DIR@\jconfig.h"
 	File "@CMAKE_SOURCE_DIR@\jerror.h"
@@ -113,6 +117,9 @@
 	Delete $INSTDIR\lib\turbojpeg.lib
 	Delete $INSTDIR\lib\turbojpeg-static.lib
 !endif
+!ifdef JAVA
+	Delete $INSTDIR\classes\turbojpeg.jar
+!endif
 	Delete $INSTDIR\bin\cjpeg.exe
 	Delete $INSTDIR\bin\djpeg.exe
 	Delete $INSTDIR\bin\jpegtran.exe
@@ -135,6 +142,9 @@
 	RMDir "$INSTDIR\include"
 	RMDir "$INSTDIR\lib"
 	RMDir "$INSTDIR\doc"
+!ifdef JAVA
+	RMDir "$INSTDIR\classes"
+!endif
 	RMDir "$INSTDIR\bin"
 	RMDir "$INSTDIR"
 
diff --git a/release/libjpeg-turbo.spec.in b/release/libjpeg-turbo.spec.in
index 48e161d..73afb64 100644
--- a/release/libjpeg-turbo.spec.in
+++ b/release/libjpeg-turbo.spec.in
@@ -43,7 +43,7 @@
 #-->%setup -q
 
 #-->%build
-#-->configure libdir=/opt/%{name}/%{__lib} mandir=/opt/%{name}/man JPEG_LIB_VERSION=@JPEG_LIB_VERSION@ SO_MAJOR_VERSION=@SO_MAJOR_VERSION@ SO_MINOR_VERSION=@SO_MINOR_VERSION@ --with-pic
+#-->configure libdir=/opt/%{name}/%{__lib} mandir=/opt/%{name}/man JPEG_LIB_VERSION=@JPEG_LIB_VERSION@ SO_MAJOR_VERSION=@SO_MAJOR_VERSION@ SO_MINOR_VERSION=@SO_MINOR_VERSION@ --with-pic @RPM_CONFIG_ARGS@
 #-->make DESTDIR=$RPM_BUILD_ROOT libdir=/opt/%{name}/%{__lib} mandir=/opt/%{name}/man
 
 %install
@@ -104,5 +104,7 @@
 /opt/%{name}/man/man1/jpegtran.1*
 /opt/%{name}/man/man1/rdjpgcom.1*
 /opt/%{name}/man/man1/wrjpgcom.1*
+@JAVA_RPM_CONTENTS_1@
+@JAVA_RPM_CONTENTS_2@
 
 %changelog
diff --git a/release/makemacpkg.in b/release/makemacpkg.in
index 4fee6c1..6cd13c3 100644
--- a/release/makemacpkg.in
+++ b/release/makemacpkg.in
@@ -28,6 +28,7 @@
 BUILD=@BUILD@
 SRCDIR=@abs_top_srcdir@
 BUILDDIR32=@abs_top_srcdir@/osxx86
+WITH_JAVA=@WITH_JAVA@
 if [ $# -gt 0 ]; then
 	if [ "$1" = "universal" ]; then
 		UNIVERSAL=1
@@ -122,6 +123,9 @@
 
 ln -fs /usr/include/turbojpeg.h $PKGROOT/opt/$PACKAGE_NAME/include/
 ln -fs /usr/lib/libturbojpeg.a $PKGROOT/opt/$PACKAGE_NAME/lib/
+if [ $WITH_JAVA = 1 ]; then
+	ln -fs libturbojpeg.dylib $PKGROOT/usr/lib/libturbojpeg.jnilib
+fi
 if [ ! -h $PKGROOT/opt/$PACKAGE_NAME/lib32 ]; then
 	ln -fs lib $PKGROOT/opt/$PACKAGE_NAME/lib32
 fi
diff --git a/release/makesunpkg.in b/release/makesunpkg.in
index aa2e735..2745d15 100644
--- a/release/makesunpkg.in
+++ b/release/makesunpkg.in
@@ -29,6 +29,7 @@
 PKGARCH=@DEBARCH@
 SRCDIR=@abs_top_srcdir@
 BUILDDIR32=@abs_top_srcdir@/solx86
+WITH_JAVA=@WITH_JAVA@
 if [ $# -gt 0 ]; then
 	if [ "$1" = "combined" ]; then
 		COMBINED=1
@@ -128,6 +129,10 @@
 f none $PACKAGE_NAME/doc/README-turbo.txt 0644 root bin
 f none $PACKAGE_NAME/doc/usage.txt 0644 root bin
 EOF
+if [ $WITH_JAVA = 1 ]; then
+echo d none $PACKAGE_NAME/classes 0755 root bin >>$TMPDIR/proto
+echo f none $PACKAGE_NAME/classes/turbojpeg.jar 0644 root bin >>$TMPDIR/proto
+fi
 
 pkgmk -o -r $TMPDIR/opt -d $TMPDIR -a i386 -f $TMPDIR/proto
 pkgtrans -s $TMPDIR $TMPDIR/$PACKAGE_NAME-$VERSION.pkg $PACKAGE_NAME
diff --git a/release/uninstall.in b/release/uninstall.in
index 94fc4f1..67b2a3e 100644
--- a/release/uninstall.in
+++ b/release/uninstall.in
@@ -63,6 +63,9 @@
 if [ -d /opt/$PKGNAME/man ]; then
 	rmdir /opt/$PKGNAME/man 2>&1 || RETCODE=-1
 fi
+if [ -d /opt/$PKGNAME/classes ]; then
+	rmdir /opt/$PKGNAME/classes 2>&1 || RETCODE=-1
+fi
 rmdir /opt/$PKGNAME 2>&1 || RETCODE=-1
 rmdir /Library/Documentation/$PKGNAME 2>&1 || RETCODE=-1
 
diff --git a/rrutil.h b/rrutil.h
index 4b61dbf..1df569b 100644
--- a/rrutil.h
+++ b/rrutil.h
@@ -16,10 +16,10 @@
 #ifndef __RRUTIL_H__
 #define __RRUTIL_H__
 
-#ifdef _WIN32
-	#include <windows.h>
-	#define sleep(t) Sleep((t)*1000)
-	#define usleep(t) Sleep((t)/1000)
+#if defined(_WIN32) && !defined(__MINGW32__)
+	#include <stdio.h>
+	#define snprintf(str, n, format, ...)  \
+		_snprintf_s(str, n, _TRUNCATE, format, __VA_ARGS__)
 #else
 	#include <unistd.h>
 	#define stricmp strcasecmp
@@ -37,30 +37,10 @@
 #define pow2(i) (1<<(i))
 #define isPow2(x) (((x)&(x-1))==0)
 
-#ifdef sgi
-#define _SC_NPROCESSORS_CONF _SC_NPROC_CONF
-#endif
-
 #ifdef sun
 #define __inline inline
 #endif
 
-static __inline int numprocs(void)
-{
-	#ifdef _WIN32
-	DWORD_PTR ProcAff, SysAff, i;  int count=0;
-	if(!GetProcessAffinityMask(GetCurrentProcess(), &ProcAff, &SysAff)) return(1);
-	for(i=0; i<sizeof(long*)*8; i++) if(ProcAff&(1LL<<i)) count++;
-	return(count);
-	#elif defined (__APPLE__)
-	return(1);
-	#else
-	long count=1;
-	if((count=sysconf(_SC_NPROCESSORS_CONF))!=-1) return((int)count);
-	else return(1);
-	#endif
-}
-
 #define byteswap(i) ( \
 	(((i) & 0xff000000) >> 24) | \
 	(((i) & 0x00ff0000) >>  8) | \
diff --git a/simd/CMakeLists.txt b/simd/CMakeLists.txt
index 353bb15..d67591e 100755
--- a/simd/CMakeLists.txt
+++ b/simd/CMakeLists.txt
@@ -22,16 +22,16 @@
 endif()
 
 if(SIMD_X86_64)
-  set(SIMD_BASENAMES jfsseflt-64 jccolss2-64 jdcolss2-64 jcsamss2-64
-    jdsamss2-64 jdmerss2-64 jcqnts2i-64 jfss2fst-64 jfss2int-64 jiss2red-64
-    jiss2int-64 jiss2fst-64 jcqnts2f-64 jiss2flt-64)
+  set(SIMD_BASENAMES jfsseflt-64 jccolss2-64 jdcolss2-64 jcgrass2-64
+    jcsamss2-64 jdsamss2-64 jdmerss2-64 jcqnts2i-64 jfss2fst-64 jfss2int-64
+    jiss2red-64 jiss2int-64 jiss2fst-64 jcqnts2f-64 jiss2flt-64)
   message(STATUS "Building x86_64 SIMD extensions")
 else()
-  set(SIMD_BASENAMES jsimdcpu jccolmmx jdcolmmx jcsammmx jdsammmx jdmermmx
-    jcqntmmx jfmmxfst jfmmxint jimmxred jimmxint jimmxfst jcqnt3dn jf3dnflt
-    ji3dnflt jcqntsse jfsseflt jisseflt jccolss2 jdcolss2 jcsamss2 jdsamss2
-    jdmerss2 jcqnts2i jfss2fst jfss2int jiss2red jiss2int jiss2fst jcqnts2f
-    jiss2flt)
+  set(SIMD_BASENAMES jsimdcpu jccolmmx jcgrammx jdcolmmx jcsammmx jdsammmx
+    jdmermmx jcqntmmx jfmmxfst jfmmxint jimmxred jimmxint jimmxfst jcqnt3dn
+    jf3dnflt ji3dnflt jcqntsse jfsseflt jisseflt jccolss2 jcgrass2 jdcolss2
+    jcsamss2 jdsamss2 jdmerss2 jcqnts2i jfss2fst jfss2int jiss2red jiss2int
+    jiss2fst jcqnts2f jiss2flt)
   message(STATUS "Building i386 SIMD extensions")
 endif()
 
@@ -52,6 +52,10 @@
     set(DEPFILE ${SIMD_SRC})
     string(REGEX REPLACE "mer" "mrg" DEPFILE ${DEPFILE})
   endif()
+  if(${file} MATCHES gra)
+    set(DEPFILE ${SIMD_SRC})
+    string(REGEX REPLACE "gra" "gry" DEPFILE ${DEPFILE})
+  endif()
   set(SIMD_OBJ ${OBJDIR}/${file}.obj)
   add_custom_command(OUTPUT ${SIMD_OBJ} DEPENDS ${SIMD_SRC} ${DEPFILE} *.inc
     COMMAND ${NASM} ${NAFLAGS} ${SIMD_SRC} -o${SIMD_OBJ})
diff --git a/simd/Makefile.am b/simd/Makefile.am
index 81c23af..959e82b 100644
--- a/simd/Makefile.am
+++ b/simd/Makefile.am
@@ -4,14 +4,14 @@
 
 EXTRA_DIST = nasm_lt.sh jcclrmmx.asm jcclrss2.asm jdclrmmx.asm jdclrss2.asm \
 	jdmrgmmx.asm jdmrgss2.asm jcclrss2-64.asm jdclrss2-64.asm \
-	jdmrgss2-64.asm CMakeLists.txt
+	jdmrgss2-64.asm jcgryss2-64.asm jcgrymmx.asm jcgryss2.asm CMakeLists.txt
 
 if SIMD_X86_64
 
 libsimd_la_SOURCES = jsimd_x86_64.c \
 	jsimd.h jsimdcfg.inc.h \
 	jsimdext.inc jcolsamp.inc jdct.inc \
-	jfsseflt-64.asm \
+	jfsseflt-64.asm jcgrass2-64.asm \
 	jccolss2-64.asm jdcolss2-64.asm \
 	jcsamss2-64.asm jdsamss2-64.asm jdmerss2-64.asm \
 	jcqnts2i-64.asm jfss2fst-64.asm jfss2int-64.asm \
@@ -20,6 +20,7 @@
 
 jccolss2-64.lo: jcclrss2-64.asm
 jdcolss2-64.lo: jdclrss2-64.asm
+jcgrass2-64.lo: jcgryss2-64.asm
 jdmerss2-64.lo: jdmrgss2-64.asm
 endif
 
@@ -29,20 +30,22 @@
 	jsimd.h jsimdcfg.inc.h \
 	jsimdext.inc jcolsamp.inc jdct.inc \
 	jsimdcpu.asm \
-	jccolmmx.asm jdcolmmx.asm \
+	jccolmmx.asm jdcolmmx.asm jcgrammx.asm \
 	jcsammmx.asm jdsammmx.asm jdmermmx.asm \
 	jcqntmmx.asm jfmmxfst.asm jfmmxint.asm \
 	jimmxred.asm jimmxint.asm jimmxfst.asm \
 	jcqnt3dn.asm jf3dnflt.asm ji3dnflt.asm \
 	jcqntsse.asm jfsseflt.asm jisseflt.asm \
-	jccolss2.asm jdcolss2.asm \
+	jccolss2.asm jdcolss2.asm jcgrass2.asm \
 	jcsamss2.asm jdsamss2.asm jdmerss2.asm \
 	jcqnts2i.asm jfss2fst.asm jfss2int.asm \
 	jiss2red.asm jiss2int.asm jiss2fst.asm \
 	jcqnts2f.asm jiss2flt.asm
 
 jccolmmx.lo: jcclrmmx.asm
+jcgrammx.lo: jcgrymmx.asm
 jccolss2.lo: jcclrss2.asm
+jcgrass2.lo: jcgryss2.asm
 jdcolmmx.lo: jdclrmmx.asm
 jdcolss2.lo: jdclrss2.asm
 jdmermmx.lo: jdmrgmmx.asm
diff --git a/simd/jcgrammx.asm b/simd/jcgrammx.asm
new file mode 100644
index 0000000..dd46cc5
--- /dev/null
+++ b/simd/jcgrammx.asm
@@ -0,0 +1,113 @@
+;
+; jcgrammx.asm - grayscale colorspace conversion (MMX)
+;
+; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
+; Copyright 2011 D. R. Commander
+;
+; Based on
+; x86 SIMD extension for IJG JPEG library
+; Copyright (C) 1999-2006, MIYASAKA Masaru.
+; For conditions of distribution and use, see copyright notice in jsimdext.inc
+;
+; This file should be assembled with NASM (Netwide Assembler),
+; can *not* be assembled with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler).
+; NASM is available from http://nasm.sourceforge.net/ or
+; http://sourceforge.net/project/showfiles.php?group_id=6208
+;
+; [TAB8]
+
+%include "jsimdext.inc"
+
+; --------------------------------------------------------------------------
+
+%define SCALEBITS	16
+
+F_0_114	equ	 7471			; FIX(0.11400)
+F_0_250	equ	16384			; FIX(0.25000)
+F_0_299	equ	19595			; FIX(0.29900)
+F_0_587	equ	38470			; FIX(0.58700)
+F_0_337	equ	(F_0_587 - F_0_250)	; FIX(0.58700) - FIX(0.25000)
+
+; --------------------------------------------------------------------------
+	SECTION	SEG_CONST
+
+	alignz	16
+	global	EXTN(jconst_rgb_gray_convert_mmx)
+
+EXTN(jconst_rgb_gray_convert_mmx):
+
+PW_F0299_F0337	times 2 dw  F_0_299, F_0_337
+PW_F0114_F0250	times 2 dw  F_0_114, F_0_250
+PD_ONEHALF	times 2 dd  (1 << (SCALEBITS-1))
+
+	alignz	16
+
+; --------------------------------------------------------------------------
+%include "jcgrymmx.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 0
+%define RGB_GREEN 1
+%define RGB_BLUE 2
+%define RGB_PIXELSIZE 3
+%define jsimd_rgb_gray_convert_mmx jsimd_extrgb_gray_convert_mmx
+%include "jcgrymmx.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 0
+%define RGB_GREEN 1
+%define RGB_BLUE 2
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_mmx jsimd_extrgbx_gray_convert_mmx
+%include "jcgrymmx.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 2
+%define RGB_GREEN 1
+%define RGB_BLUE 0
+%define RGB_PIXELSIZE 3
+%define jsimd_rgb_gray_convert_mmx jsimd_extbgr_gray_convert_mmx
+%include "jcgrymmx.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 2
+%define RGB_GREEN 1
+%define RGB_BLUE 0
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_mmx jsimd_extbgrx_gray_convert_mmx
+%include "jcgrymmx.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 3
+%define RGB_GREEN 2
+%define RGB_BLUE 1
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_mmx jsimd_extxbgr_gray_convert_mmx
+%include "jcgrymmx.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 1
+%define RGB_GREEN 2
+%define RGB_BLUE 3
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_mmx jsimd_extxrgb_gray_convert_mmx
+%include "jcgrymmx.asm"
diff --git a/simd/jcgrass2-64.asm b/simd/jcgrass2-64.asm
new file mode 100644
index 0000000..9f8a01a
--- /dev/null
+++ b/simd/jcgrass2-64.asm
@@ -0,0 +1,110 @@
+;
+; jcgrass2-64.asm - grayscale colorspace conversion (64-bit SSE2)
+;
+; x86 SIMD extension for IJG JPEG library
+; Copyright (C) 1999-2006, MIYASAKA Masaru.
+; Copyright (C) 2011, D. R. Commander.
+; For conditions of distribution and use, see copyright notice in jsimdext.inc
+;
+; This file should be assembled with NASM (Netwide Assembler),
+; can *not* be assembled with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler).
+; NASM is available from http://nasm.sourceforge.net/ or
+; http://sourceforge.net/project/showfiles.php?group_id=6208
+;
+; [TAB8]
+
+%include "jsimdext.inc"
+
+; --------------------------------------------------------------------------
+
+%define SCALEBITS	16
+
+F_0_114	equ	 7471			; FIX(0.11400)
+F_0_250	equ	16384			; FIX(0.25000)
+F_0_299	equ	19595			; FIX(0.29900)
+F_0_587	equ	38470			; FIX(0.58700)
+F_0_337	equ	(F_0_587 - F_0_250)	; FIX(0.58700) - FIX(0.25000)
+
+; --------------------------------------------------------------------------
+	SECTION	SEG_CONST
+
+	alignz	16
+	global	EXTN(jconst_rgb_gray_convert_sse2)
+
+EXTN(jconst_rgb_gray_convert_sse2):
+
+PW_F0299_F0337	times 4 dw  F_0_299, F_0_337
+PW_F0114_F0250	times 4 dw  F_0_114, F_0_250
+PD_ONEHALF	times 4 dd  (1 << (SCALEBITS-1))
+
+	alignz	16
+
+; --------------------------------------------------------------------------
+%include "jcgryss2-64.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 0
+%define RGB_GREEN 1
+%define RGB_BLUE 2
+%define RGB_PIXELSIZE 3
+%define jsimd_rgb_gray_convert_sse2 jsimd_extrgb_gray_convert_sse2
+%include "jcgryss2-64.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 0
+%define RGB_GREEN 1
+%define RGB_BLUE 2
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extrgbx_gray_convert_sse2
+%include "jcgryss2-64.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 2
+%define RGB_GREEN 1
+%define RGB_BLUE 0
+%define RGB_PIXELSIZE 3
+%define jsimd_rgb_gray_convert_sse2 jsimd_extbgr_gray_convert_sse2
+%include "jcgryss2-64.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 2
+%define RGB_GREEN 1
+%define RGB_BLUE 0
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extbgrx_gray_convert_sse2
+%include "jcgryss2-64.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 3
+%define RGB_GREEN 2
+%define RGB_BLUE 1
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extxbgr_gray_convert_sse2
+%include "jcgryss2-64.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 1
+%define RGB_GREEN 2
+%define RGB_BLUE 3
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extxrgb_gray_convert_sse2
+%include "jcgryss2-64.asm"
diff --git a/simd/jcgrass2.asm b/simd/jcgrass2.asm
new file mode 100644
index 0000000..f284e0f
--- /dev/null
+++ b/simd/jcgrass2.asm
@@ -0,0 +1,110 @@
+;
+; jcgrass2.asm - grayscale colorspace conversion (SSE2)
+;
+; x86 SIMD extension for IJG JPEG library
+; Copyright (C) 1999-2006, MIYASAKA Masaru.
+; Copyright (C) 2011, D. R. Commander.
+; For conditions of distribution and use, see copyright notice in jsimdext.inc
+;
+; This file should be assembled with NASM (Netwide Assembler),
+; can *not* be assembled with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler).
+; NASM is available from http://nasm.sourceforge.net/ or
+; http://sourceforge.net/project/showfiles.php?group_id=6208
+;
+; [TAB8]
+
+%include "jsimdext.inc"
+
+; --------------------------------------------------------------------------
+
+%define SCALEBITS	16
+
+F_0_114	equ	 7471			; FIX(0.11400)
+F_0_250	equ	16384			; FIX(0.25000)
+F_0_299	equ	19595			; FIX(0.29900)
+F_0_587	equ	38470			; FIX(0.58700)
+F_0_337	equ	(F_0_587 - F_0_250)	; FIX(0.58700) - FIX(0.25000)
+
+; --------------------------------------------------------------------------
+	SECTION	SEG_CONST
+
+	alignz	16
+	global	EXTN(jconst_rgb_gray_convert_sse2)
+
+EXTN(jconst_rgb_gray_convert_sse2):
+
+PW_F0299_F0337	times 4 dw  F_0_299, F_0_337
+PW_F0114_F0250	times 4 dw  F_0_114, F_0_250
+PD_ONEHALF	times 4 dd  (1 << (SCALEBITS-1))
+
+	alignz	16
+
+; --------------------------------------------------------------------------
+%include "jcgryss2.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 0
+%define RGB_GREEN 1
+%define RGB_BLUE 2
+%define RGB_PIXELSIZE 3
+%define jsimd_rgb_gray_convert_sse2 jsimd_extrgb_gray_convert_sse2
+%include "jcgryss2.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 0
+%define RGB_GREEN 1
+%define RGB_BLUE 2
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extrgbx_gray_convert_sse2
+%include "jcgryss2.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 2
+%define RGB_GREEN 1
+%define RGB_BLUE 0
+%define RGB_PIXELSIZE 3
+%define jsimd_rgb_gray_convert_sse2 jsimd_extbgr_gray_convert_sse2
+%include "jcgryss2.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 2
+%define RGB_GREEN 1
+%define RGB_BLUE 0
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extbgrx_gray_convert_sse2
+%include "jcgryss2.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 3
+%define RGB_GREEN 2
+%define RGB_BLUE 1
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extxbgr_gray_convert_sse2
+%include "jcgryss2.asm"
+
+%undef RGB_RED
+%undef RGB_GREEN
+%undef RGB_BLUE
+%undef RGB_PIXELSIZE
+%define RGB_RED 1
+%define RGB_GREEN 2
+%define RGB_BLUE 3
+%define RGB_PIXELSIZE 4
+%define jsimd_rgb_gray_convert_sse2 jsimd_extxrgb_gray_convert_sse2
+%include "jcgryss2.asm"
diff --git a/simd/jcgrymmx.asm b/simd/jcgrymmx.asm
new file mode 100644
index 0000000..481a619
--- /dev/null
+++ b/simd/jcgrymmx.asm
@@ -0,0 +1,359 @@
+;
+; jcgrymmx.asm - grayscale colorspace conversion (MMX)
+;
+; Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
+; Copyright 2011 D. R. Commander
+;
+; Based on
+; x86 SIMD extension for IJG JPEG library
+; Copyright (C) 1999-2006, MIYASAKA Masaru.
+; For conditions of distribution and use, see copyright notice in jsimdext.inc
+;
+; This file should be assembled with NASM (Netwide Assembler),
+; can *not* be assembled with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler).
+; NASM is available from http://nasm.sourceforge.net/ or
+; http://sourceforge.net/project/showfiles.php?group_id=6208
+;
+; [TAB8]
+
+%include "jcolsamp.inc"
+
+; --------------------------------------------------------------------------
+	SECTION	SEG_TEXT
+	BITS	32
+;
+; Convert some rows of samples to the output colorspace.
+;
+; GLOBAL(void)
+; jsimd_rgb_gray_convert_mmx (JDIMENSION img_width,
+;                             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+;                             JDIMENSION output_row, int num_rows);
+;
+
+%define img_width(b)	(b)+8			; JDIMENSION img_width
+%define input_buf(b)	(b)+12		; JSAMPARRAY input_buf
+%define output_buf(b)	(b)+16		; JSAMPIMAGE output_buf
+%define output_row(b)	(b)+20		; JDIMENSION output_row
+%define num_rows(b)	(b)+24		; int num_rows
+
+%define original_ebp	ebp+0
+%define wk(i)		ebp-(WK_NUM-(i))*SIZEOF_MMWORD	; mmword wk[WK_NUM]
+%define WK_NUM		2
+%define gotptr		wk(0)-SIZEOF_POINTER	; void * gotptr
+
+	align	16
+	global	EXTN(jsimd_rgb_gray_convert_mmx)
+
+EXTN(jsimd_rgb_gray_convert_mmx):
+	push	ebp
+	mov	eax,esp				; eax = original ebp
+	sub	esp, byte 4
+	and	esp, byte (-SIZEOF_MMWORD)	; align to 64 bits
+	mov	[esp],eax
+	mov	ebp,esp				; ebp = aligned ebp
+	lea	esp, [wk(0)]
+	pushpic	eax		; make a room for GOT address
+	push	ebx
+;	push	ecx		; need not be preserved
+;	push	edx		; need not be preserved
+	push	esi
+	push	edi
+
+	get_GOT	ebx			; get GOT address
+	movpic	POINTER [gotptr], ebx	; save GOT address
+
+	mov	ecx, JDIMENSION [img_width(eax)]	; num_cols
+	test	ecx,ecx
+	jz	near .return
+
+	push	ecx
+
+	mov	esi, JSAMPIMAGE [output_buf(eax)]
+	mov	ecx, JDIMENSION [output_row(eax)]
+	mov	edi, JSAMPARRAY [esi+0*SIZEOF_JSAMPARRAY]
+	lea	edi, [edi+ecx*SIZEOF_JSAMPROW]
+
+	pop	ecx
+
+	mov	esi, JSAMPARRAY [input_buf(eax)]
+	mov	eax, INT [num_rows(eax)]
+	test	eax,eax
+	jle	near .return
+	alignx	16,7
+.rowloop:
+	pushpic	eax
+	push	edi
+	push	esi
+	push	ecx			; col
+
+	mov	esi, JSAMPROW [esi]	; inptr
+	mov	edi, JSAMPROW [edi]	; outptr0
+	movpic	eax, POINTER [gotptr]	; load GOT address (eax)
+
+	cmp	ecx, byte SIZEOF_MMWORD
+	jae	short .columnloop
+	alignx	16,7
+
+%if RGB_PIXELSIZE == 3 ; ---------------
+
+.column_ld1:
+	push	eax
+	push	edx
+	lea	ecx,[ecx+ecx*2]		; imul ecx,RGB_PIXELSIZE
+	test	cl, SIZEOF_BYTE
+	jz	short .column_ld2
+	sub	ecx, byte SIZEOF_BYTE
+	xor	eax,eax
+	mov	al, BYTE [esi+ecx]
+.column_ld2:
+	test	cl, SIZEOF_WORD
+	jz	short .column_ld4
+	sub	ecx, byte SIZEOF_WORD
+	xor	edx,edx
+	mov	dx, WORD [esi+ecx]
+	shl	eax, WORD_BIT
+	or	eax,edx
+.column_ld4:
+	movd	mmA,eax
+	pop	edx
+	pop	eax
+	test	cl, SIZEOF_DWORD
+	jz	short .column_ld8
+	sub	ecx, byte SIZEOF_DWORD
+	movd	mmG, DWORD [esi+ecx]
+	psllq	mmA, DWORD_BIT
+	por	mmA,mmG
+.column_ld8:
+	test	cl, SIZEOF_MMWORD
+	jz	short .column_ld16
+	movq	mmG,mmA
+	movq	mmA, MMWORD [esi+0*SIZEOF_MMWORD]
+	mov	ecx, SIZEOF_MMWORD
+	jmp	short .rgb_gray_cnv
+.column_ld16:
+	test	cl, 2*SIZEOF_MMWORD
+	mov	ecx, SIZEOF_MMWORD
+	jz	short .rgb_gray_cnv
+	movq	mmF,mmA
+	movq	mmA, MMWORD [esi+0*SIZEOF_MMWORD]
+	movq	mmG, MMWORD [esi+1*SIZEOF_MMWORD]
+	jmp	short .rgb_gray_cnv
+	alignx	16,7
+
+.columnloop:
+	movq	mmA, MMWORD [esi+0*SIZEOF_MMWORD]
+	movq	mmG, MMWORD [esi+1*SIZEOF_MMWORD]
+	movq	mmF, MMWORD [esi+2*SIZEOF_MMWORD]
+
+.rgb_gray_cnv:
+	; mmA=(00 10 20 01 11 21 02 12)
+	; mmG=(22 03 13 23 04 14 24 05)
+	; mmF=(15 25 06 16 26 07 17 27)
+
+	movq      mmD,mmA
+	psllq     mmA,4*BYTE_BIT	; mmA=(-- -- -- -- 00 10 20 01)
+	psrlq     mmD,4*BYTE_BIT	; mmD=(11 21 02 12 -- -- -- --)
+
+	punpckhbw mmA,mmG		; mmA=(00 04 10 14 20 24 01 05)
+	psllq     mmG,4*BYTE_BIT	; mmG=(-- -- -- -- 22 03 13 23)
+
+	punpcklbw mmD,mmF		; mmD=(11 15 21 25 02 06 12 16)
+	punpckhbw mmG,mmF		; mmG=(22 26 03 07 13 17 23 27)
+
+	movq      mmE,mmA
+	psllq     mmA,4*BYTE_BIT	; mmA=(-- -- -- -- 00 04 10 14)
+	psrlq     mmE,4*BYTE_BIT	; mmE=(20 24 01 05 -- -- -- --)
+
+	punpckhbw mmA,mmD		; mmA=(00 02 04 06 10 12 14 16)
+	psllq     mmD,4*BYTE_BIT	; mmD=(-- -- -- -- 11 15 21 25)
+
+	punpcklbw mmE,mmG		; mmE=(20 22 24 26 01 03 05 07)
+	punpckhbw mmD,mmG		; mmD=(11 13 15 17 21 23 25 27)
+
+	pxor      mmH,mmH
+
+	movq      mmC,mmA
+	punpcklbw mmA,mmH		; mmA=(00 02 04 06)
+	punpckhbw mmC,mmH		; mmC=(10 12 14 16)
+
+	movq      mmB,mmE
+	punpcklbw mmE,mmH		; mmE=(20 22 24 26)
+	punpckhbw mmB,mmH		; mmB=(01 03 05 07)
+
+	movq      mmF,mmD
+	punpcklbw mmD,mmH		; mmD=(11 13 15 17)
+	punpckhbw mmF,mmH		; mmF=(21 23 25 27)
+
+%else ; RGB_PIXELSIZE == 4 ; -----------
+
+.column_ld1:
+	test	cl, SIZEOF_MMWORD/8
+	jz	short .column_ld2
+	sub	ecx, byte SIZEOF_MMWORD/8
+	movd	mmA, DWORD [esi+ecx*RGB_PIXELSIZE]
+.column_ld2:
+	test	cl, SIZEOF_MMWORD/4
+	jz	short .column_ld4
+	sub	ecx, byte SIZEOF_MMWORD/4
+	movq	mmF,mmA
+	movq	mmA, MMWORD [esi+ecx*RGB_PIXELSIZE]
+.column_ld4:
+	test	cl, SIZEOF_MMWORD/2
+	mov	ecx, SIZEOF_MMWORD
+	jz	short .rgb_gray_cnv
+	movq	mmD,mmA
+	movq	mmC,mmF
+	movq	mmA, MMWORD [esi+0*SIZEOF_MMWORD]
+	movq	mmF, MMWORD [esi+1*SIZEOF_MMWORD]
+	jmp	short .rgb_gray_cnv
+	alignx	16,7
+
+.columnloop:
+	movq	mmA, MMWORD [esi+0*SIZEOF_MMWORD]
+	movq	mmF, MMWORD [esi+1*SIZEOF_MMWORD]
+	movq	mmD, MMWORD [esi+2*SIZEOF_MMWORD]
+	movq	mmC, MMWORD [esi+3*SIZEOF_MMWORD]
+
+.rgb_gray_cnv:
+	; mmA=(00 10 20 30 01 11 21 31)
+	; mmF=(02 12 22 32 03 13 23 33)
+	; mmD=(04 14 24 34 05 15 25 35)
+	; mmC=(06 16 26 36 07 17 27 37)
+
+	movq      mmB,mmA
+	punpcklbw mmA,mmF		; mmA=(00 02 10 12 20 22 30 32)
+	punpckhbw mmB,mmF		; mmB=(01 03 11 13 21 23 31 33)
+
+	movq      mmG,mmD
+	punpcklbw mmD,mmC		; mmD=(04 06 14 16 24 26 34 36)
+	punpckhbw mmG,mmC		; mmG=(05 07 15 17 25 27 35 37)
+
+	movq      mmE,mmA
+	punpcklwd mmA,mmD		; mmA=(00 02 04 06 10 12 14 16)
+	punpckhwd mmE,mmD		; mmE=(20 22 24 26 30 32 34 36)
+
+	movq      mmH,mmB
+	punpcklwd mmB,mmG		; mmB=(01 03 05 07 11 13 15 17)
+	punpckhwd mmH,mmG		; mmH=(21 23 25 27 31 33 35 37)
+
+	pxor      mmF,mmF
+
+	movq      mmC,mmA
+	punpcklbw mmA,mmF		; mmA=(00 02 04 06)
+	punpckhbw mmC,mmF		; mmC=(10 12 14 16)
+
+	movq      mmD,mmB
+	punpcklbw mmB,mmF		; mmB=(01 03 05 07)
+	punpckhbw mmD,mmF		; mmD=(11 13 15 17)
+
+	movq      mmG,mmE
+	punpcklbw mmE,mmF		; mmE=(20 22 24 26)
+	punpckhbw mmG,mmF		; mmG=(30 32 34 36)
+
+	punpcklbw mmF,mmH
+	punpckhbw mmH,mmH
+	psrlw     mmF,BYTE_BIT		; mmF=(21 23 25 27)
+	psrlw     mmH,BYTE_BIT		; mmH=(31 33 35 37)
+
+%endif ; RGB_PIXELSIZE ; ---------------
+
+	; mm0=(R0 R2 R4 R6)=RE, mm2=(G0 G2 G4 G6)=GE, mm4=(B0 B2 B4 B6)=BE
+	; mm1=(R1 R3 R5 R7)=RO, mm3=(G1 G3 G5 G7)=GO, mm5=(B1 B3 B5 B7)=BO
+
+	; (Original)
+	; Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
+	;
+	; (This implementation)
+	; Y  =  0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G
+
+	movq      mm6,mm1
+	punpcklwd mm1,mm3
+	punpckhwd mm6,mm3
+	pmaddwd   mm1,[GOTOFF(eax,PW_F0299_F0337)] ; mm1=ROL*FIX(0.299)+GOL*FIX(0.337)
+	pmaddwd   mm6,[GOTOFF(eax,PW_F0299_F0337)] ; mm6=ROH*FIX(0.299)+GOH*FIX(0.337)
+
+	movq      mm7, mm6	; mm7=ROH*FIX(0.299)+GOH*FIX(0.337)
+
+	movq      mm6,mm0
+	punpcklwd mm0,mm2
+	punpckhwd mm6,mm2
+	pmaddwd   mm0,[GOTOFF(eax,PW_F0299_F0337)] ; mm0=REL*FIX(0.299)+GEL*FIX(0.337)
+	pmaddwd   mm6,[GOTOFF(eax,PW_F0299_F0337)] ; mm6=REH*FIX(0.299)+GEH*FIX(0.337)
+
+	movq      MMWORD [wk(0)], mm0	; wk(0)=REL*FIX(0.299)+GEL*FIX(0.337)
+	movq      MMWORD [wk(1)], mm6	; wk(1)=REH*FIX(0.299)+GEH*FIX(0.337)
+
+	movq      mm0, mm5	; mm0=BO
+	movq      mm6, mm4	; mm6=BE
+
+	movq      mm4,mm0
+	punpcklwd mm0,mm3
+	punpckhwd mm4,mm3
+	pmaddwd   mm0,[GOTOFF(eax,PW_F0114_F0250)] ; mm0=BOL*FIX(0.114)+GOL*FIX(0.250)
+	pmaddwd   mm4,[GOTOFF(eax,PW_F0114_F0250)] ; mm4=BOH*FIX(0.114)+GOH*FIX(0.250)
+
+	movq      mm3,[GOTOFF(eax,PD_ONEHALF)]	; mm3=[PD_ONEHALF]
+
+	paddd     mm0, mm1
+	paddd     mm4, mm7
+	paddd     mm0,mm3
+	paddd     mm4,mm3
+	psrld     mm0,SCALEBITS		; mm0=YOL
+	psrld     mm4,SCALEBITS		; mm4=YOH
+	packssdw  mm0,mm4		; mm0=YO
+
+	movq      mm4,mm6
+	punpcklwd mm6,mm2
+	punpckhwd mm4,mm2
+	pmaddwd   mm6,[GOTOFF(eax,PW_F0114_F0250)] ; mm6=BEL*FIX(0.114)+GEL*FIX(0.250)
+	pmaddwd   mm4,[GOTOFF(eax,PW_F0114_F0250)] ; mm4=BEH*FIX(0.114)+GEH*FIX(0.250)
+
+	movq      mm2,[GOTOFF(eax,PD_ONEHALF)]	; mm2=[PD_ONEHALF]
+
+	paddd     mm6, MMWORD [wk(0)]
+	paddd     mm4, MMWORD [wk(1)]
+	paddd     mm6,mm2
+	paddd     mm4,mm2
+	psrld     mm6,SCALEBITS		; mm6=YEL
+	psrld     mm4,SCALEBITS		; mm4=YEH
+	packssdw  mm6,mm4		; mm6=YE
+
+	psllw     mm0,BYTE_BIT
+	por       mm6,mm0		; mm6=Y
+	movq      MMWORD [edi], mm6	; Save Y
+
+	sub	ecx, byte SIZEOF_MMWORD
+	add	esi, byte RGB_PIXELSIZE*SIZEOF_MMWORD	; inptr
+	add	edi, byte SIZEOF_MMWORD			; outptr0
+	cmp	ecx, byte SIZEOF_MMWORD
+	jae	near .columnloop
+	test	ecx,ecx
+	jnz	near .column_ld1
+
+	pop	ecx			; col
+	pop	esi
+	pop	edi
+	poppic	eax
+
+	add	esi, byte SIZEOF_JSAMPROW	; input_buf
+	add	edi, byte SIZEOF_JSAMPROW
+	dec	eax				; num_rows
+	jg	near .rowloop
+
+	emms		; empty MMX state
+
+.return:
+	pop	edi
+	pop	esi
+;	pop	edx		; need not be preserved
+;	pop	ecx		; need not be preserved
+	pop	ebx
+	mov	esp,ebp		; esp <- aligned ebp
+	pop	esp		; esp <- original ebp
+	pop	ebp
+	ret
+
+; For some reason, the OS X linker does not honor the request to align the
+; segment unless we do this.
+	align	16
diff --git a/simd/jcgryss2-64.asm b/simd/jcgryss2-64.asm
new file mode 100644
index 0000000..3a52ec2
--- /dev/null
+++ b/simd/jcgryss2-64.asm
@@ -0,0 +1,366 @@
+;
+; jcgryss2-64.asm - grayscale colorspace conversion (64-bit SSE2)
+;
+; x86 SIMD extension for IJG JPEG library
+; Copyright (C) 1999-2006, MIYASAKA Masaru.
+; Copyright (C) 2011, D. R. Commander.
+; For conditions of distribution and use, see copyright notice in jsimdext.inc
+;
+; This file should be assembled with NASM (Netwide Assembler),
+; can *not* be assembled with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler).
+; NASM is available from http://nasm.sourceforge.net/ or
+; http://sourceforge.net/project/showfiles.php?group_id=6208
+;
+; [TAB8]
+
+%include "jcolsamp.inc"
+
+; --------------------------------------------------------------------------
+	SECTION	SEG_TEXT
+	BITS	64
+;
+; Convert some rows of samples to the output colorspace.
+;
+; GLOBAL(void)
+; jsimd_rgb_gray_convert_sse2 (JDIMENSION img_width,
+;                              JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+;                              JDIMENSION output_row, int num_rows);
+;
+
+; r10 = JDIMENSION img_width
+; r11 = JSAMPARRAY input_buf
+; r12 = JSAMPIMAGE output_buf
+; r13 = JDIMENSION output_row
+; r14 = int num_rows
+
+%define wk(i)		rbp-(WK_NUM-(i))*SIZEOF_XMMWORD	; xmmword wk[WK_NUM]
+%define WK_NUM		2
+
+	align	16
+
+	global	EXTN(jsimd_rgb_gray_convert_sse2)
+
+EXTN(jsimd_rgb_gray_convert_sse2):
+	push	rbp
+	mov	rax,rsp				; rax = original rbp
+	sub	rsp, byte 4
+	and	rsp, byte (-SIZEOF_XMMWORD)	; align to 128 bits
+	mov	[rsp],rax
+	mov	rbp,rsp				; rbp = aligned rbp
+	lea	rsp, [wk(0)]
+	collect_args
+	push	rbx
+
+	mov	rcx, r10
+	test	rcx,rcx
+	jz	near .return
+
+	push	rcx
+
+	mov rsi, r12
+	mov rcx, r13
+	mov	rdi, JSAMPARRAY [rsi+0*SIZEOF_JSAMPARRAY]
+	lea	rdi, [rdi+rcx*SIZEOF_JSAMPROW]
+
+	pop	rcx
+
+	mov rsi, r11
+	mov	eax, r14d
+	test	rax,rax
+	jle	near .return
+.rowloop:
+	push	rdi
+	push	rsi
+	push	rcx			; col
+
+	mov	rsi, JSAMPROW [rsi]	; inptr
+	mov	rdi, JSAMPROW [rdi]	; outptr0
+
+	cmp	rcx, byte SIZEOF_XMMWORD
+	jae	near .columnloop
+
+%if RGB_PIXELSIZE == 3 ; ---------------
+
+.column_ld1:
+	push	rax
+	push	rdx
+	lea	rcx,[rcx+rcx*2]		; imul ecx,RGB_PIXELSIZE
+	test	cl, SIZEOF_BYTE
+	jz	short .column_ld2
+	sub	rcx, byte SIZEOF_BYTE
+	movzx	rax, BYTE [rsi+rcx]
+.column_ld2:
+	test	cl, SIZEOF_WORD
+	jz	short .column_ld4
+	sub	rcx, byte SIZEOF_WORD
+	movzx	rdx, WORD [rsi+rcx]
+	shl	rax, WORD_BIT
+	or	rax,rdx
+.column_ld4:
+	movd	xmmA,eax
+	pop	rdx
+	pop	rax
+	test	cl, SIZEOF_DWORD
+	jz	short .column_ld8
+	sub	rcx, byte SIZEOF_DWORD
+	movd	xmmF, XMM_DWORD [rsi+rcx]
+	pslldq	xmmA, SIZEOF_DWORD
+	por	xmmA,xmmF
+.column_ld8:
+	test	cl, SIZEOF_MMWORD
+	jz	short .column_ld16
+	sub	rcx, byte SIZEOF_MMWORD
+	movq	xmmB, XMM_MMWORD [rsi+rcx]
+	pslldq	xmmA, SIZEOF_MMWORD
+	por	xmmA,xmmB
+.column_ld16:
+	test	cl, SIZEOF_XMMWORD
+	jz	short .column_ld32
+	movdqa	xmmF,xmmA
+	movdqu	xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD]
+	mov	rcx, SIZEOF_XMMWORD
+	jmp	short .rgb_gray_cnv
+.column_ld32:
+	test	cl, 2*SIZEOF_XMMWORD
+	mov	rcx, SIZEOF_XMMWORD
+	jz	short .rgb_gray_cnv
+	movdqa	xmmB,xmmA
+	movdqu	xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD]
+	movdqu	xmmF, XMMWORD [rsi+1*SIZEOF_XMMWORD]
+	jmp	short .rgb_gray_cnv
+
+.columnloop:
+	movdqu	xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD]
+	movdqu	xmmF, XMMWORD [rsi+1*SIZEOF_XMMWORD]
+	movdqu	xmmB, XMMWORD [rsi+2*SIZEOF_XMMWORD]
+
+.rgb_gray_cnv:
+	; xmmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05)
+	; xmmF=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A)
+	; xmmB=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F)
+
+	movdqa    xmmG,xmmA
+	pslldq    xmmA,8	; xmmA=(-- -- -- -- -- -- -- -- 00 10 20 01 11 21 02 12)
+	psrldq    xmmG,8	; xmmG=(22 03 13 23 04 14 24 05 -- -- -- -- -- -- -- --)
+
+	punpckhbw xmmA,xmmF	; xmmA=(00 08 10 18 20 28 01 09 11 19 21 29 02 0A 12 1A)
+	pslldq    xmmF,8	; xmmF=(-- -- -- -- -- -- -- -- 15 25 06 16 26 07 17 27)
+
+	punpcklbw xmmG,xmmB	; xmmG=(22 2A 03 0B 13 1B 23 2B 04 0C 14 1C 24 2C 05 0D)
+	punpckhbw xmmF,xmmB	; xmmF=(15 1D 25 2D 06 0E 16 1E 26 2E 07 0F 17 1F 27 2F)
+
+	movdqa    xmmD,xmmA
+	pslldq    xmmA,8	; xmmA=(-- -- -- -- -- -- -- -- 00 08 10 18 20 28 01 09)
+	psrldq    xmmD,8	; xmmD=(11 19 21 29 02 0A 12 1A -- -- -- -- -- -- -- --)
+
+	punpckhbw xmmA,xmmG	; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 01 05 09 0D)
+	pslldq    xmmG,8	; xmmG=(-- -- -- -- -- -- -- -- 22 2A 03 0B 13 1B 23 2B)
+
+	punpcklbw xmmD,xmmF	; xmmD=(11 15 19 1D 21 25 29 2D 02 06 0A 0E 12 16 1A 1E)
+	punpckhbw xmmG,xmmF	; xmmG=(22 26 2A 2E 03 07 0B 0F 13 17 1B 1F 23 27 2B 2F)
+
+	movdqa    xmmE,xmmA
+	pslldq    xmmA,8	; xmmA=(-- -- -- -- -- -- -- -- 00 04 08 0C 10 14 18 1C)
+	psrldq    xmmE,8	; xmmE=(20 24 28 2C 01 05 09 0D -- -- -- -- -- -- -- --)
+
+	punpckhbw xmmA,xmmD	; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E)
+	pslldq    xmmD,8	; xmmD=(-- -- -- -- -- -- -- -- 11 15 19 1D 21 25 29 2D)
+
+	punpcklbw xmmE,xmmG	; xmmE=(20 22 24 26 28 2A 2C 2E 01 03 05 07 09 0B 0D 0F)
+	punpckhbw xmmD,xmmG	; xmmD=(11 13 15 17 19 1B 1D 1F 21 23 25 27 29 2B 2D 2F)
+
+	pxor      xmmH,xmmH
+
+	movdqa    xmmC,xmmA
+	punpcklbw xmmA,xmmH	; xmmA=(00 02 04 06 08 0A 0C 0E)
+	punpckhbw xmmC,xmmH	; xmmC=(10 12 14 16 18 1A 1C 1E)
+
+	movdqa    xmmB,xmmE
+	punpcklbw xmmE,xmmH	; xmmE=(20 22 24 26 28 2A 2C 2E)
+	punpckhbw xmmB,xmmH	; xmmB=(01 03 05 07 09 0B 0D 0F)
+
+	movdqa    xmmF,xmmD
+	punpcklbw xmmD,xmmH	; xmmD=(11 13 15 17 19 1B 1D 1F)
+	punpckhbw xmmF,xmmH	; xmmF=(21 23 25 27 29 2B 2D 2F)
+
+%else ; RGB_PIXELSIZE == 4 ; -----------
+
+.column_ld1:
+	test	cl, SIZEOF_XMMWORD/16
+	jz	short .column_ld2
+	sub	rcx, byte SIZEOF_XMMWORD/16
+	movd	xmmA, XMM_DWORD [rsi+rcx*RGB_PIXELSIZE]
+.column_ld2:
+	test	cl, SIZEOF_XMMWORD/8
+	jz	short .column_ld4
+	sub	rcx, byte SIZEOF_XMMWORD/8
+	movq	xmmE, XMM_MMWORD [rsi+rcx*RGB_PIXELSIZE]
+	pslldq	xmmA, SIZEOF_MMWORD
+	por	xmmA,xmmE
+.column_ld4:
+	test	cl, SIZEOF_XMMWORD/4
+	jz	short .column_ld8
+	sub	rcx, byte SIZEOF_XMMWORD/4
+	movdqa	xmmE,xmmA
+	movdqu	xmmA, XMMWORD [rsi+rcx*RGB_PIXELSIZE]
+.column_ld8:
+	test	cl, SIZEOF_XMMWORD/2
+	mov	rcx, SIZEOF_XMMWORD
+	jz	short .rgb_gray_cnv
+	movdqa	xmmF,xmmA
+	movdqa	xmmH,xmmE
+	movdqu	xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD]
+	movdqu	xmmE, XMMWORD [rsi+1*SIZEOF_XMMWORD]
+	jmp	short .rgb_gray_cnv
+
+.columnloop:
+	movdqu	xmmA, XMMWORD [rsi+0*SIZEOF_XMMWORD]
+	movdqu	xmmE, XMMWORD [rsi+1*SIZEOF_XMMWORD]
+	movdqu	xmmF, XMMWORD [rsi+2*SIZEOF_XMMWORD]
+	movdqu	xmmH, XMMWORD [rsi+3*SIZEOF_XMMWORD]
+
+.rgb_gray_cnv:
+	; xmmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33)
+	; xmmE=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37)
+	; xmmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B)
+	; xmmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F)
+
+	movdqa    xmmD,xmmA
+	punpcklbw xmmA,xmmE	; xmmA=(00 04 10 14 20 24 30 34 01 05 11 15 21 25 31 35)
+	punpckhbw xmmD,xmmE	; xmmD=(02 06 12 16 22 26 32 36 03 07 13 17 23 27 33 37)
+
+	movdqa    xmmC,xmmF
+	punpcklbw xmmF,xmmH	; xmmF=(08 0C 18 1C 28 2C 38 3C 09 0D 19 1D 29 2D 39 3D)
+	punpckhbw xmmC,xmmH	; xmmC=(0A 0E 1A 1E 2A 2E 3A 3E 0B 0F 1B 1F 2B 2F 3B 3F)
+
+	movdqa    xmmB,xmmA
+	punpcklwd xmmA,xmmF	; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 30 34 38 3C)
+	punpckhwd xmmB,xmmF	; xmmB=(01 05 09 0D 11 15 19 1D 21 25 29 2D 31 35 39 3D)
+
+	movdqa    xmmG,xmmD
+	punpcklwd xmmD,xmmC	; xmmD=(02 06 0A 0E 12 16 1A 1E 22 26 2A 2E 32 36 3A 3E)
+	punpckhwd xmmG,xmmC	; xmmG=(03 07 0B 0F 13 17 1B 1F 23 27 2B 2F 33 37 3B 3F)
+
+	movdqa    xmmE,xmmA
+	punpcklbw xmmA,xmmD	; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E)
+	punpckhbw xmmE,xmmD	; xmmE=(20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E)
+
+	movdqa    xmmH,xmmB
+	punpcklbw xmmB,xmmG	; xmmB=(01 03 05 07 09 0B 0D 0F 11 13 15 17 19 1B 1D 1F)
+	punpckhbw xmmH,xmmG	; xmmH=(21 23 25 27 29 2B 2D 2F 31 33 35 37 39 3B 3D 3F)
+
+	pxor      xmmF,xmmF
+
+	movdqa    xmmC,xmmA
+	punpcklbw xmmA,xmmF	; xmmA=(00 02 04 06 08 0A 0C 0E)
+	punpckhbw xmmC,xmmF	; xmmC=(10 12 14 16 18 1A 1C 1E)
+
+	movdqa    xmmD,xmmB
+	punpcklbw xmmB,xmmF	; xmmB=(01 03 05 07 09 0B 0D 0F)
+	punpckhbw xmmD,xmmF	; xmmD=(11 13 15 17 19 1B 1D 1F)
+
+	movdqa    xmmG,xmmE
+	punpcklbw xmmE,xmmF	; xmmE=(20 22 24 26 28 2A 2C 2E)
+	punpckhbw xmmG,xmmF	; xmmG=(30 32 34 36 38 3A 3C 3E)
+
+	punpcklbw xmmF,xmmH
+	punpckhbw xmmH,xmmH
+	psrlw     xmmF,BYTE_BIT	; xmmF=(21 23 25 27 29 2B 2D 2F)
+	psrlw     xmmH,BYTE_BIT	; xmmH=(31 33 35 37 39 3B 3D 3F)
+
+%endif ; RGB_PIXELSIZE ; ---------------
+
+	; xmm0=R(02468ACE)=RE, xmm2=G(02468ACE)=GE, xmm4=B(02468ACE)=BE
+	; xmm1=R(13579BDF)=RO, xmm3=G(13579BDF)=GO, xmm5=B(13579BDF)=BO
+
+	; (Original)
+	; Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
+	;
+	; (This implementation)
+	; Y  =  0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G
+
+	movdqa    xmm6,xmm1
+	punpcklwd xmm1,xmm3
+	punpckhwd xmm6,xmm3
+	pmaddwd   xmm1,[rel PW_F0299_F0337] ; xmm1=ROL*FIX(0.299)+GOL*FIX(0.337)
+	pmaddwd   xmm6,[rel PW_F0299_F0337] ; xmm6=ROH*FIX(0.299)+GOH*FIX(0.337)
+
+	movdqa    xmm7, xmm6	; xmm7=ROH*FIX(0.299)+GOH*FIX(0.337)
+
+	movdqa    xmm6,xmm0
+	punpcklwd xmm0,xmm2
+	punpckhwd xmm6,xmm2
+	pmaddwd   xmm0,[rel PW_F0299_F0337] ; xmm0=REL*FIX(0.299)+GEL*FIX(0.337)
+	pmaddwd   xmm6,[rel PW_F0299_F0337] ; xmm6=REH*FIX(0.299)+GEH*FIX(0.337)
+
+	movdqa    XMMWORD [wk(0)], xmm0	; wk(0)=REL*FIX(0.299)+GEL*FIX(0.337)
+	movdqa    XMMWORD [wk(1)], xmm6	; wk(1)=REH*FIX(0.299)+GEH*FIX(0.337)
+
+	movdqa    xmm0, xmm5	; xmm0=BO
+	movdqa    xmm6, xmm4	; xmm6=BE
+
+	movdqa    xmm4,xmm0
+	punpcklwd xmm0,xmm3
+	punpckhwd xmm4,xmm3
+	pmaddwd   xmm0,[rel PW_F0114_F0250] ; xmm0=BOL*FIX(0.114)+GOL*FIX(0.250)
+	pmaddwd   xmm4,[rel PW_F0114_F0250] ; xmm4=BOH*FIX(0.114)+GOH*FIX(0.250)
+
+	movdqa    xmm3,[rel PD_ONEHALF]	; xmm3=[PD_ONEHALF]
+
+	paddd     xmm0, xmm1
+	paddd     xmm4, xmm7
+	paddd     xmm0,xmm3
+	paddd     xmm4,xmm3
+	psrld     xmm0,SCALEBITS	; xmm0=YOL
+	psrld     xmm4,SCALEBITS	; xmm4=YOH
+	packssdw  xmm0,xmm4		; xmm0=YO
+
+	movdqa    xmm4,xmm6
+	punpcklwd xmm6,xmm2
+	punpckhwd xmm4,xmm2
+	pmaddwd   xmm6,[rel PW_F0114_F0250] ; xmm6=BEL*FIX(0.114)+GEL*FIX(0.250)
+	pmaddwd   xmm4,[rel PW_F0114_F0250] ; xmm4=BEH*FIX(0.114)+GEH*FIX(0.250)
+
+	movdqa    xmm2,[rel PD_ONEHALF]	; xmm2=[PD_ONEHALF]
+
+	paddd     xmm6, XMMWORD [wk(0)]
+	paddd     xmm4, XMMWORD [wk(1)]
+	paddd     xmm6,xmm2
+	paddd     xmm4,xmm2
+	psrld     xmm6,SCALEBITS	; xmm6=YEL
+	psrld     xmm4,SCALEBITS	; xmm4=YEH
+	packssdw  xmm6,xmm4		; xmm6=YE
+
+	psllw     xmm0,BYTE_BIT
+	por       xmm6,xmm0		; xmm6=Y
+	movdqa    XMMWORD [rdi], xmm6	; Save Y
+
+	sub	rcx, byte SIZEOF_XMMWORD
+	add	rsi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD	; inptr
+	add	rdi, byte SIZEOF_XMMWORD		; outptr0
+	cmp	rcx, byte SIZEOF_XMMWORD
+	jae	near .columnloop
+	test	rcx,rcx
+	jnz	near .column_ld1
+
+	pop	rcx			; col
+	pop	rsi
+	pop	rdi
+
+	add	rsi, byte SIZEOF_JSAMPROW	; input_buf
+	add	rdi, byte SIZEOF_JSAMPROW
+	dec	rax				; num_rows
+	jg	near .rowloop
+
+.return:
+	pop	rbx
+	uncollect_args
+	mov	rsp,rbp		; rsp <- aligned rbp
+	pop	rsp		; rsp <- original rbp
+	pop	rbp
+	ret
+
+; For some reason, the OS X linker does not honor the request to align the
+; segment unless we do this.
+	align	16
diff --git a/simd/jcgryss2.asm b/simd/jcgryss2.asm
new file mode 100644
index 0000000..6eac030
--- /dev/null
+++ b/simd/jcgryss2.asm
@@ -0,0 +1,385 @@
+;
+; jcgryss2.asm - grayscale colorspace conversion (SSE2)
+;
+; x86 SIMD extension for IJG JPEG library
+; Copyright (C) 1999-2006, MIYASAKA Masaru.
+; Copyright (C) 2011, D. R. Commander.
+; For conditions of distribution and use, see copyright notice in jsimdext.inc
+;
+; This file should be assembled with NASM (Netwide Assembler),
+; can *not* be assembled with Microsoft's MASM or any compatible
+; assembler (including Borland's Turbo Assembler).
+; NASM is available from http://nasm.sourceforge.net/ or
+; http://sourceforge.net/project/showfiles.php?group_id=6208
+;
+; [TAB8]
+
+%include "jcolsamp.inc"
+
+; --------------------------------------------------------------------------
+	SECTION	SEG_TEXT
+	BITS	32
+;
+; Convert some rows of samples to the output colorspace.
+;
+; GLOBAL(void)
+; jsimd_rgb_gray_convert_sse2 (JDIMENSION img_width,
+;                              JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+;                              JDIMENSION output_row, int num_rows);
+;
+
+%define img_width(b)	(b)+8			; JDIMENSION img_width
+%define input_buf(b)	(b)+12		; JSAMPARRAY input_buf
+%define output_buf(b)	(b)+16		; JSAMPIMAGE output_buf
+%define output_row(b)	(b)+20		; JDIMENSION output_row
+%define num_rows(b)	(b)+24		; int num_rows
+
+%define original_ebp	ebp+0
+%define wk(i)		ebp-(WK_NUM-(i))*SIZEOF_XMMWORD	; xmmword wk[WK_NUM]
+%define WK_NUM		2
+%define gotptr		wk(0)-SIZEOF_POINTER	; void * gotptr
+
+	align	16
+
+	global	EXTN(jsimd_rgb_gray_convert_sse2)
+
+EXTN(jsimd_rgb_gray_convert_sse2):
+	push	ebp
+	mov	eax,esp				; eax = original ebp
+	sub	esp, byte 4
+	and	esp, byte (-SIZEOF_XMMWORD)	; align to 128 bits
+	mov	[esp],eax
+	mov	ebp,esp				; ebp = aligned ebp
+	lea	esp, [wk(0)]
+	pushpic	eax		; make a room for GOT address
+	push	ebx
+;	push	ecx		; need not be preserved
+;	push	edx		; need not be preserved
+	push	esi
+	push	edi
+
+	get_GOT	ebx			; get GOT address
+	movpic	POINTER [gotptr], ebx	; save GOT address
+
+	mov	ecx, JDIMENSION [img_width(eax)]
+	test	ecx,ecx
+	jz	near .return
+
+	push	ecx
+
+	mov	esi, JSAMPIMAGE [output_buf(eax)]
+	mov	ecx, JDIMENSION [output_row(eax)]
+	mov	edi, JSAMPARRAY [esi+0*SIZEOF_JSAMPARRAY]
+	lea	edi, [edi+ecx*SIZEOF_JSAMPROW]
+
+	pop	ecx
+
+	mov	esi, JSAMPARRAY [input_buf(eax)]
+	mov	eax, INT [num_rows(eax)]
+	test	eax,eax
+	jle	near .return
+	alignx	16,7
+.rowloop:
+	pushpic	eax
+	push	edi
+	push	esi
+	push	ecx			; col
+
+	mov	esi, JSAMPROW [esi]	; inptr
+	mov	edi, JSAMPROW [edi]	; outptr0
+	movpic	eax, POINTER [gotptr]	; load GOT address (eax)
+
+	cmp	ecx, byte SIZEOF_XMMWORD
+	jae	near .columnloop
+	alignx	16,7
+
+%if RGB_PIXELSIZE == 3 ; ---------------
+
+.column_ld1:
+	push	eax
+	push	edx
+	lea	ecx,[ecx+ecx*2]		; imul ecx,RGB_PIXELSIZE
+	test	cl, SIZEOF_BYTE
+	jz	short .column_ld2
+	sub	ecx, byte SIZEOF_BYTE
+	movzx	eax, BYTE [esi+ecx]
+.column_ld2:
+	test	cl, SIZEOF_WORD
+	jz	short .column_ld4
+	sub	ecx, byte SIZEOF_WORD
+	movzx	edx, WORD [esi+ecx]
+	shl	eax, WORD_BIT
+	or	eax,edx
+.column_ld4:
+	movd	xmmA,eax
+	pop	edx
+	pop	eax
+	test	cl, SIZEOF_DWORD
+	jz	short .column_ld8
+	sub	ecx, byte SIZEOF_DWORD
+	movd	xmmF, XMM_DWORD [esi+ecx]
+	pslldq	xmmA, SIZEOF_DWORD
+	por	xmmA,xmmF
+.column_ld8:
+	test	cl, SIZEOF_MMWORD
+	jz	short .column_ld16
+	sub	ecx, byte SIZEOF_MMWORD
+	movq	xmmB, XMM_MMWORD [esi+ecx]
+	pslldq	xmmA, SIZEOF_MMWORD
+	por	xmmA,xmmB
+.column_ld16:
+	test	cl, SIZEOF_XMMWORD
+	jz	short .column_ld32
+	movdqa	xmmF,xmmA
+	movdqu	xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
+	mov	ecx, SIZEOF_XMMWORD
+	jmp	short .rgb_gray_cnv
+.column_ld32:
+	test	cl, 2*SIZEOF_XMMWORD
+	mov	ecx, SIZEOF_XMMWORD
+	jz	short .rgb_gray_cnv
+	movdqa	xmmB,xmmA
+	movdqu	xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
+	movdqu	xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD]
+	jmp	short .rgb_gray_cnv
+	alignx	16,7
+
+.columnloop:
+	movdqu	xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
+	movdqu	xmmF, XMMWORD [esi+1*SIZEOF_XMMWORD]
+	movdqu	xmmB, XMMWORD [esi+2*SIZEOF_XMMWORD]
+
+.rgb_gray_cnv:
+	; xmmA=(00 10 20 01 11 21 02 12 22 03 13 23 04 14 24 05)
+	; xmmF=(15 25 06 16 26 07 17 27 08 18 28 09 19 29 0A 1A)
+	; xmmB=(2A 0B 1B 2B 0C 1C 2C 0D 1D 2D 0E 1E 2E 0F 1F 2F)
+
+	movdqa    xmmG,xmmA
+	pslldq    xmmA,8	; xmmA=(-- -- -- -- -- -- -- -- 00 10 20 01 11 21 02 12)
+	psrldq    xmmG,8	; xmmG=(22 03 13 23 04 14 24 05 -- -- -- -- -- -- -- --)
+
+	punpckhbw xmmA,xmmF	; xmmA=(00 08 10 18 20 28 01 09 11 19 21 29 02 0A 12 1A)
+	pslldq    xmmF,8	; xmmF=(-- -- -- -- -- -- -- -- 15 25 06 16 26 07 17 27)
+
+	punpcklbw xmmG,xmmB	; xmmG=(22 2A 03 0B 13 1B 23 2B 04 0C 14 1C 24 2C 05 0D)
+	punpckhbw xmmF,xmmB	; xmmF=(15 1D 25 2D 06 0E 16 1E 26 2E 07 0F 17 1F 27 2F)
+
+	movdqa    xmmD,xmmA
+	pslldq    xmmA,8	; xmmA=(-- -- -- -- -- -- -- -- 00 08 10 18 20 28 01 09)
+	psrldq    xmmD,8	; xmmD=(11 19 21 29 02 0A 12 1A -- -- -- -- -- -- -- --)
+
+	punpckhbw xmmA,xmmG	; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 01 05 09 0D)
+	pslldq    xmmG,8	; xmmG=(-- -- -- -- -- -- -- -- 22 2A 03 0B 13 1B 23 2B)
+
+	punpcklbw xmmD,xmmF	; xmmD=(11 15 19 1D 21 25 29 2D 02 06 0A 0E 12 16 1A 1E)
+	punpckhbw xmmG,xmmF	; xmmG=(22 26 2A 2E 03 07 0B 0F 13 17 1B 1F 23 27 2B 2F)
+
+	movdqa    xmmE,xmmA
+	pslldq    xmmA,8	; xmmA=(-- -- -- -- -- -- -- -- 00 04 08 0C 10 14 18 1C)
+	psrldq    xmmE,8	; xmmE=(20 24 28 2C 01 05 09 0D -- -- -- -- -- -- -- --)
+
+	punpckhbw xmmA,xmmD	; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E)
+	pslldq    xmmD,8	; xmmD=(-- -- -- -- -- -- -- -- 11 15 19 1D 21 25 29 2D)
+
+	punpcklbw xmmE,xmmG	; xmmE=(20 22 24 26 28 2A 2C 2E 01 03 05 07 09 0B 0D 0F)
+	punpckhbw xmmD,xmmG	; xmmD=(11 13 15 17 19 1B 1D 1F 21 23 25 27 29 2B 2D 2F)
+
+	pxor      xmmH,xmmH
+
+	movdqa    xmmC,xmmA
+	punpcklbw xmmA,xmmH	; xmmA=(00 02 04 06 08 0A 0C 0E)
+	punpckhbw xmmC,xmmH	; xmmC=(10 12 14 16 18 1A 1C 1E)
+
+	movdqa    xmmB,xmmE
+	punpcklbw xmmE,xmmH	; xmmE=(20 22 24 26 28 2A 2C 2E)
+	punpckhbw xmmB,xmmH	; xmmB=(01 03 05 07 09 0B 0D 0F)
+
+	movdqa    xmmF,xmmD
+	punpcklbw xmmD,xmmH	; xmmD=(11 13 15 17 19 1B 1D 1F)
+	punpckhbw xmmF,xmmH	; xmmF=(21 23 25 27 29 2B 2D 2F)
+
+%else ; RGB_PIXELSIZE == 4 ; -----------
+
+.column_ld1:
+	test	cl, SIZEOF_XMMWORD/16
+	jz	short .column_ld2
+	sub	ecx, byte SIZEOF_XMMWORD/16
+	movd	xmmA, XMM_DWORD [esi+ecx*RGB_PIXELSIZE]
+.column_ld2:
+	test	cl, SIZEOF_XMMWORD/8
+	jz	short .column_ld4
+	sub	ecx, byte SIZEOF_XMMWORD/8
+	movq	xmmE, XMM_MMWORD [esi+ecx*RGB_PIXELSIZE]
+	pslldq	xmmA, SIZEOF_MMWORD
+	por	xmmA,xmmE
+.column_ld4:
+	test	cl, SIZEOF_XMMWORD/4
+	jz	short .column_ld8
+	sub	ecx, byte SIZEOF_XMMWORD/4
+	movdqa	xmmE,xmmA
+	movdqu	xmmA, XMMWORD [esi+ecx*RGB_PIXELSIZE]
+.column_ld8:
+	test	cl, SIZEOF_XMMWORD/2
+	mov	ecx, SIZEOF_XMMWORD
+	jz	short .rgb_gray_cnv
+	movdqa	xmmF,xmmA
+	movdqa	xmmH,xmmE
+	movdqu	xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
+	movdqu	xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD]
+	jmp	short .rgb_gray_cnv
+	alignx	16,7
+
+.columnloop:
+	movdqu	xmmA, XMMWORD [esi+0*SIZEOF_XMMWORD]
+	movdqu	xmmE, XMMWORD [esi+1*SIZEOF_XMMWORD]
+	movdqu	xmmF, XMMWORD [esi+2*SIZEOF_XMMWORD]
+	movdqu	xmmH, XMMWORD [esi+3*SIZEOF_XMMWORD]
+
+.rgb_gray_cnv:
+	; xmmA=(00 10 20 30 01 11 21 31 02 12 22 32 03 13 23 33)
+	; xmmE=(04 14 24 34 05 15 25 35 06 16 26 36 07 17 27 37)
+	; xmmF=(08 18 28 38 09 19 29 39 0A 1A 2A 3A 0B 1B 2B 3B)
+	; xmmH=(0C 1C 2C 3C 0D 1D 2D 3D 0E 1E 2E 3E 0F 1F 2F 3F)
+
+	movdqa    xmmD,xmmA
+	punpcklbw xmmA,xmmE	; xmmA=(00 04 10 14 20 24 30 34 01 05 11 15 21 25 31 35)
+	punpckhbw xmmD,xmmE	; xmmD=(02 06 12 16 22 26 32 36 03 07 13 17 23 27 33 37)
+
+	movdqa    xmmC,xmmF
+	punpcklbw xmmF,xmmH	; xmmF=(08 0C 18 1C 28 2C 38 3C 09 0D 19 1D 29 2D 39 3D)
+	punpckhbw xmmC,xmmH	; xmmC=(0A 0E 1A 1E 2A 2E 3A 3E 0B 0F 1B 1F 2B 2F 3B 3F)
+
+	movdqa    xmmB,xmmA
+	punpcklwd xmmA,xmmF	; xmmA=(00 04 08 0C 10 14 18 1C 20 24 28 2C 30 34 38 3C)
+	punpckhwd xmmB,xmmF	; xmmB=(01 05 09 0D 11 15 19 1D 21 25 29 2D 31 35 39 3D)
+
+	movdqa    xmmG,xmmD
+	punpcklwd xmmD,xmmC	; xmmD=(02 06 0A 0E 12 16 1A 1E 22 26 2A 2E 32 36 3A 3E)
+	punpckhwd xmmG,xmmC	; xmmG=(03 07 0B 0F 13 17 1B 1F 23 27 2B 2F 33 37 3B 3F)
+
+	movdqa    xmmE,xmmA
+	punpcklbw xmmA,xmmD	; xmmA=(00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A 1C 1E)
+	punpckhbw xmmE,xmmD	; xmmE=(20 22 24 26 28 2A 2C 2E 30 32 34 36 38 3A 3C 3E)
+
+	movdqa    xmmH,xmmB
+	punpcklbw xmmB,xmmG	; xmmB=(01 03 05 07 09 0B 0D 0F 11 13 15 17 19 1B 1D 1F)
+	punpckhbw xmmH,xmmG	; xmmH=(21 23 25 27 29 2B 2D 2F 31 33 35 37 39 3B 3D 3F)
+
+	pxor      xmmF,xmmF
+
+	movdqa    xmmC,xmmA
+	punpcklbw xmmA,xmmF	; xmmA=(00 02 04 06 08 0A 0C 0E)
+	punpckhbw xmmC,xmmF	; xmmC=(10 12 14 16 18 1A 1C 1E)
+
+	movdqa    xmmD,xmmB
+	punpcklbw xmmB,xmmF	; xmmB=(01 03 05 07 09 0B 0D 0F)
+	punpckhbw xmmD,xmmF	; xmmD=(11 13 15 17 19 1B 1D 1F)
+
+	movdqa    xmmG,xmmE
+	punpcklbw xmmE,xmmF	; xmmE=(20 22 24 26 28 2A 2C 2E)
+	punpckhbw xmmG,xmmF	; xmmG=(30 32 34 36 38 3A 3C 3E)
+
+	punpcklbw xmmF,xmmH
+	punpckhbw xmmH,xmmH
+	psrlw     xmmF,BYTE_BIT	; xmmF=(21 23 25 27 29 2B 2D 2F)
+	psrlw     xmmH,BYTE_BIT	; xmmH=(31 33 35 37 39 3B 3D 3F)
+
+%endif ; RGB_PIXELSIZE ; ---------------
+
+	; xmm0=R(02468ACE)=RE, xmm2=G(02468ACE)=GE, xmm4=B(02468ACE)=BE
+	; xmm1=R(13579BDF)=RO, xmm3=G(13579BDF)=GO, xmm5=B(13579BDF)=BO
+
+	; (Original)
+	; Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
+	;
+	; (This implementation)
+	; Y  =  0.29900 * R + 0.33700 * G + 0.11400 * B + 0.25000 * G
+
+	movdqa    xmm6,xmm1
+	punpcklwd xmm1,xmm3
+	punpckhwd xmm6,xmm3
+	pmaddwd   xmm1,[GOTOFF(eax,PW_F0299_F0337)] ; xmm1=ROL*FIX(0.299)+GOL*FIX(0.337)
+	pmaddwd   xmm6,[GOTOFF(eax,PW_F0299_F0337)] ; xmm6=ROH*FIX(0.299)+GOH*FIX(0.337)
+
+	movdqa    xmm7, xmm6	; xmm7=ROH*FIX(0.299)+GOH*FIX(0.337)
+
+	movdqa    xmm6,xmm0
+	punpcklwd xmm0,xmm2
+	punpckhwd xmm6,xmm2
+	pmaddwd   xmm0,[GOTOFF(eax,PW_F0299_F0337)] ; xmm0=REL*FIX(0.299)+GEL*FIX(0.337)
+	pmaddwd   xmm6,[GOTOFF(eax,PW_F0299_F0337)] ; xmm6=REH*FIX(0.299)+GEH*FIX(0.337)
+
+	movdqa    XMMWORD [wk(0)], xmm0	; wk(0)=REL*FIX(0.299)+GEL*FIX(0.337)
+	movdqa    XMMWORD [wk(1)], xmm6	; wk(1)=REH*FIX(0.299)+GEH*FIX(0.337)
+
+	movdqa    xmm0, xmm5	; xmm0=BO
+	movdqa    xmm6, xmm4	; xmm6=BE
+
+	movdqa    xmm4,xmm0
+	punpcklwd xmm0,xmm3
+	punpckhwd xmm4,xmm3
+	pmaddwd   xmm0,[GOTOFF(eax,PW_F0114_F0250)] ; xmm0=BOL*FIX(0.114)+GOL*FIX(0.250)
+	pmaddwd   xmm4,[GOTOFF(eax,PW_F0114_F0250)] ; xmm4=BOH*FIX(0.114)+GOH*FIX(0.250)
+
+	movdqa    xmm3,[GOTOFF(eax,PD_ONEHALF)]	; xmm3=[PD_ONEHALF]
+
+	paddd     xmm0, xmm1
+	paddd     xmm4, xmm7
+	paddd     xmm0,xmm3
+	paddd     xmm4,xmm3
+	psrld     xmm0,SCALEBITS	; xmm0=YOL
+	psrld     xmm4,SCALEBITS	; xmm4=YOH
+	packssdw  xmm0,xmm4		; xmm0=YO
+
+	movdqa    xmm4,xmm6
+	punpcklwd xmm6,xmm2
+	punpckhwd xmm4,xmm2
+	pmaddwd   xmm6,[GOTOFF(eax,PW_F0114_F0250)] ; xmm6=BEL*FIX(0.114)+GEL*FIX(0.250)
+	pmaddwd   xmm4,[GOTOFF(eax,PW_F0114_F0250)] ; xmm4=BEH*FIX(0.114)+GEH*FIX(0.250)
+
+	movdqa    xmm2,[GOTOFF(eax,PD_ONEHALF)]	; xmm2=[PD_ONEHALF]
+
+	paddd     xmm6, XMMWORD [wk(0)]
+	paddd     xmm4, XMMWORD [wk(1)]
+	paddd     xmm6,xmm2
+	paddd     xmm4,xmm2
+	psrld     xmm6,SCALEBITS	; xmm6=YEL
+	psrld     xmm4,SCALEBITS	; xmm4=YEH
+	packssdw  xmm6,xmm4		; xmm6=YE
+
+	psllw     xmm0,BYTE_BIT
+	por       xmm6,xmm0		; xmm6=Y
+	movdqa    XMMWORD [edi], xmm6	; Save Y
+
+	sub	ecx, byte SIZEOF_XMMWORD
+	add	esi, byte RGB_PIXELSIZE*SIZEOF_XMMWORD	; inptr
+	add	edi, byte SIZEOF_XMMWORD		; outptr0
+	cmp	ecx, byte SIZEOF_XMMWORD
+	jae	near .columnloop
+	test	ecx,ecx
+	jnz	near .column_ld1
+
+	pop	ecx			; col
+	pop	esi
+	pop	edi
+	poppic	eax
+
+	add	esi, byte SIZEOF_JSAMPROW	; input_buf
+	add	edi, byte SIZEOF_JSAMPROW
+	dec	eax				; num_rows
+	jg	near .rowloop
+
+.return:
+	pop	edi
+	pop	esi
+;	pop	edx		; need not be preserved
+;	pop	ecx		; need not be preserved
+	pop	ebx
+	mov	esp,ebp		; esp <- aligned ebp
+	pop	esp		; esp <- original ebp
+	pop	ebp
+	ret
+
+; For some reason, the OS X linker does not honor the request to align the
+; segment unless we do this.
+	align	16
diff --git a/simd/jsimd.h b/simd/jsimd.h
index 89ac1b7..60ae0e0 100644
--- a/simd/jsimd.h
+++ b/simd/jsimd.h
@@ -2,6 +2,7 @@
  * simd/jsimd.h
  *
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
+ * Copyright 2011 D. R. Commander
  * 
  * Based on the x86 SIMD extension for IJG JPEG library,
  * Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -28,6 +29,13 @@
 #define jsimd_extbgrx_ycc_convert_mmx         jSEXTBGRXYCCM
 #define jsimd_extxbgr_ycc_convert_mmx         jSEXTXBGRYCCM
 #define jsimd_extxrgb_ycc_convert_mmx         jSEXTXRGBYCCM
+#define jsimd_rgb_gray_convert_mmx            jSRGBGRYM
+#define jsimd_extrgb_gray_convert_mmx         jSEXTRGBGRYM
+#define jsimd_extrgbx_gray_convert_mmx        jSEXTRGBXGRYM
+#define jsimd_extbgr_gray_convert_mmx         jSEXTBGRGRYM
+#define jsimd_extbgrx_gray_convert_mmx        jSEXTBGRXGRYM
+#define jsimd_extxbgr_gray_convert_mmx        jSEXTXBGRGRYM
+#define jsimd_extxrgb_gray_convert_mmx        jSEXTXRGBGRYM
 #define jsimd_ycc_rgb_convert_mmx             jSYCCRGBM
 #define jsimd_ycc_extrgb_convert_mmx          jSYCCEXTRGBM
 #define jsimd_ycc_extrgbx_convert_mmx         jSYCCEXTRGBXM
@@ -43,6 +51,14 @@
 #define jsimd_extbgrx_ycc_convert_sse2        jSEXTBGRXYCCS2
 #define jsimd_extxbgr_ycc_convert_sse2        jSEXTXBGRYCCS2
 #define jsimd_extxrgb_ycc_convert_sse2        jSEXTXRGBYCCS2
+#define jconst_rgb_gray_convert_sse2          jSCRGBGRYS2
+#define jsimd_rgb_gray_convert_sse2           jSRGBGRYS2
+#define jsimd_extrgb_gray_convert_sse2        jSEXTRGBGRYS2
+#define jsimd_extrgbx_gray_convert_sse2       jSEXTRGBXGRYS2
+#define jsimd_extbgr_gray_convert_sse2        jSEXTBGRGRYS2
+#define jsimd_extbgrx_gray_convert_sse2       jSEXTBGRXGRYS2
+#define jsimd_extxbgr_gray_convert_sse2       jSEXTXBGRGRYS2
+#define jsimd_extxrgb_gray_convert_sse2       jSEXTXRGBGRYS2
 #define jconst_ycc_rgb_convert_sse2           jSCYCCRGBS2
 #define jsimd_ycc_rgb_convert_sse2            jSYCCRGBS2
 #define jsimd_ycc_extrgb_convert_sse2         jSYCCEXTRGBS2
@@ -163,6 +179,35 @@
              JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
              JDIMENSION output_row, int num_rows));
 
+EXTERN(void) jsimd_rgb_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extrgb_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extrgbx_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extbgr_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extbgrx_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extxbgr_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extxrgb_gray_convert_mmx
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+
 EXTERN(void) jsimd_ycc_rgb_convert_mmx
         JPP((JDIMENSION out_width,
              JSAMPIMAGE input_buf, JDIMENSION input_row,
@@ -222,6 +267,36 @@
              JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
              JDIMENSION output_row, int num_rows));
 
+extern const int jconst_rgb_gray_convert_sse2[];
+EXTERN(void) jsimd_rgb_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extrgb_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extrgbx_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extbgr_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extbgrx_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extxbgr_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+EXTERN(void) jsimd_extxrgb_gray_convert_sse2
+        JPP((JDIMENSION img_width,
+             JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+             JDIMENSION output_row, int num_rows));
+
 extern const int jconst_ycc_rgb_convert_sse2[];
 EXTERN(void) jsimd_ycc_rgb_convert_sse2
         JPP((JDIMENSION out_width,
diff --git a/simd/jsimd_i386.c b/simd/jsimd_i386.c
index d9bb774..f77c5ef 100644
--- a/simd/jsimd_i386.c
+++ b/simd/jsimd_i386.c
@@ -2,7 +2,7 @@
  * jsimd_i386.c
  *
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright 2009 D. R. Commander
+ * Copyright 2009-2011 D. R. Commander
  * 
  * Based on the x86 SIMD extension for IJG JPEG library,
  * Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -84,6 +84,28 @@
 }
 
 GLOBAL(int)
+jsimd_can_rgb_gray (void)
+{
+  init_simd();
+
+  /* The code is optimised for these values only */
+  if (BITS_IN_JSAMPLE != 8)
+    return 0;
+  if (sizeof(JDIMENSION) != 4)
+    return 0;
+  if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
+    return 0;
+
+  if ((simd_support & JSIMD_SSE2) &&
+      IS_ALIGNED_SSE(jconst_rgb_gray_convert_sse2))
+    return 1;
+  if (simd_support & JSIMD_MMX)
+    return 1;
+
+  return 0;
+}
+
+GLOBAL(int)
 jsimd_can_ycc_rgb (void)
 {
   init_simd();
@@ -155,6 +177,55 @@
 }
 
 GLOBAL(void)
+jsimd_rgb_gray_convert (j_compress_ptr cinfo,
+                        JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+                        JDIMENSION output_row, int num_rows)
+{
+  void (*sse2fct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
+  void (*mmxfct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
+
+  switch(cinfo->in_color_space)
+  {
+    case JCS_EXT_RGB:
+      sse2fct=jsimd_extrgb_gray_convert_sse2;
+      mmxfct=jsimd_extrgb_gray_convert_mmx;
+      break;
+    case JCS_EXT_RGBX:
+      sse2fct=jsimd_extrgbx_gray_convert_sse2;
+      mmxfct=jsimd_extrgbx_gray_convert_mmx;
+      break;
+    case JCS_EXT_BGR:
+      sse2fct=jsimd_extbgr_gray_convert_sse2;
+      mmxfct=jsimd_extbgr_gray_convert_mmx;
+      break;
+    case JCS_EXT_BGRX:
+      sse2fct=jsimd_extbgrx_gray_convert_sse2;
+      mmxfct=jsimd_extbgrx_gray_convert_mmx;
+      break;
+    case JCS_EXT_XBGR:
+      sse2fct=jsimd_extxbgr_gray_convert_sse2;
+      mmxfct=jsimd_extxbgr_gray_convert_mmx;
+      break;
+    case JCS_EXT_XRGB:
+      sse2fct=jsimd_extxrgb_gray_convert_sse2;
+      mmxfct=jsimd_extxrgb_gray_convert_mmx;
+      break;
+    default:
+      sse2fct=jsimd_rgb_gray_convert_sse2;
+      mmxfct=jsimd_rgb_gray_convert_mmx;
+      break;
+  }
+
+  if ((simd_support & JSIMD_SSE2) &&
+      IS_ALIGNED_SSE(jconst_rgb_gray_convert_sse2))
+    sse2fct(cinfo->image_width, input_buf,
+        output_buf, output_row, num_rows);
+  else if (simd_support & JSIMD_MMX)
+    mmxfct(cinfo->image_width, input_buf,
+        output_buf, output_row, num_rows);
+}
+
+GLOBAL(void)
 jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
                        JSAMPIMAGE input_buf, JDIMENSION input_row,
                        JSAMPARRAY output_buf, int num_rows)
diff --git a/simd/jsimd_x86_64.c b/simd/jsimd_x86_64.c
index 7659249..2951268 100644
--- a/simd/jsimd_x86_64.c
+++ b/simd/jsimd_x86_64.c
@@ -2,7 +2,7 @@
  * jsimd_x86_64.c
  *
  * Copyright 2009 Pierre Ossman <ossman@cendio.se> for Cendio AB
- * Copyright 2009 D. R. Commander
+ * Copyright 2009-2011 D. R. Commander
  * 
  * Based on the x86 SIMD extension for IJG JPEG library,
  * Copyright (C) 1999-2006, MIYASAKA Masaru.
@@ -47,6 +47,23 @@
 }
 
 GLOBAL(int)
+jsimd_can_rgb_gray (void)
+{
+  /* The code is optimised for these values only */
+  if (BITS_IN_JSAMPLE != 8)
+    return 0;
+  if (sizeof(JDIMENSION) != 4)
+    return 0;
+  if ((RGB_PIXELSIZE != 3) && (RGB_PIXELSIZE != 4))
+    return 0;
+
+  if (!IS_ALIGNED_SSE(jconst_rgb_gray_convert_sse2))
+    return 0;
+
+  return 1;
+}
+
+GLOBAL(int)
 jsimd_can_ycc_rgb (void)
 {
   /* The code is optimised for these values only */
@@ -99,6 +116,41 @@
 }
 
 GLOBAL(void)
+jsimd_rgb_gray_convert (j_compress_ptr cinfo,
+                        JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
+                        JDIMENSION output_row, int num_rows)
+{
+  void (*sse2fct)(JDIMENSION, JSAMPARRAY, JSAMPIMAGE, JDIMENSION, int);
+
+  switch(cinfo->in_color_space)
+  {
+    case JCS_EXT_RGB:
+      sse2fct=jsimd_extrgb_gray_convert_sse2;
+      break;
+    case JCS_EXT_RGBX:
+      sse2fct=jsimd_extrgbx_gray_convert_sse2;
+      break;
+    case JCS_EXT_BGR:
+      sse2fct=jsimd_extbgr_gray_convert_sse2;
+      break;
+    case JCS_EXT_BGRX:
+      sse2fct=jsimd_extbgrx_gray_convert_sse2;
+      break;
+    case JCS_EXT_XBGR:
+      sse2fct=jsimd_extxbgr_gray_convert_sse2;
+      break;
+    case JCS_EXT_XRGB:
+      sse2fct=jsimd_extxrgb_gray_convert_sse2;
+      break;
+    default:
+      sse2fct=jsimd_rgb_gray_convert_sse2;
+      break;
+  }
+
+  sse2fct(cinfo->image_width, input_buf, output_buf, output_row, num_rows);
+}
+
+GLOBAL(void)
 jsimd_ycc_rgb_convert (j_decompress_ptr cinfo,
                        JSAMPIMAGE input_buf, JDIMENSION input_row,
                        JSAMPARRAY output_buf, int num_rows)
diff --git a/testimggray.jpg b/testimggray.jpg
new file mode 100644
index 0000000..95505a2
--- /dev/null
+++ b/testimggray.jpg
Binary files differ
diff --git a/transupp.c b/transupp.c
index 5c31416..2513691 100644
--- a/transupp.c
+++ b/transupp.c
@@ -1022,7 +1022,7 @@
   case JXFORM_FLIP_H:
     if (info->trim)
       trim_right_edge(info, srcinfo->output_width);
-    if (info->y_crop_offset != 0)
+    if (info->y_crop_offset != 0 || info->slow_hflip)
       need_workspace = TRUE;
     /* do_flip_h_no_crop doesn't need a workspace array */
     break;
@@ -1448,7 +1448,7 @@
 	      src_coef_arrays, dst_coef_arrays);
     break;
   case JXFORM_FLIP_H:
-    if (info->y_crop_offset != 0)
+    if (info->y_crop_offset != 0 || info->slow_hflip)
       do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
 		src_coef_arrays, dst_coef_arrays);
     else
diff --git a/transupp.h b/transupp.h
index 7c16c19..122d448 100644
--- a/transupp.h
+++ b/transupp.h
@@ -128,6 +128,13 @@
   boolean trim;			/* if TRUE, trim partial MCUs as needed */
   boolean force_grayscale;	/* if TRUE, convert color image to grayscale */
   boolean crop;			/* if TRUE, crop source image */
+  boolean slow_hflip;  /* For best performance, the JXFORM_FLIP_H transform
+                          normally modifies the source coefficients in place.
+                          Setting this to TRUE will instead use a slower,
+                          double-buffered algorithm, which leaves the source
+                          coefficients in tact (necessary if other transformed
+                          images must be generated from the same set of
+                          coefficients. */
 
   /* Crop parameters: application need not set these unless crop is TRUE.
    * These can be filled in by jtransform_parse_crop_spec().
diff --git a/turbojpeg-jni.c b/turbojpeg-jni.c
new file mode 100644
index 0000000..099d6bf
--- /dev/null
+++ b/turbojpeg-jni.c
@@ -0,0 +1,598 @@
+/*
+ * Copyright (C)2011 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:
+ *
+ * - Redistributions of source code must retain the above copyright notice,
+ *   this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright notice,
+ *   this list of conditions and the following disclaimer in the documentation
+ *   and/or other materials provided with the distribution.
+ * - Neither the name of the libjpeg-turbo Project nor the names of its
+ *   contributors may be used to endorse or promote products derived from this
+ *   software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS",
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "turbojpeg.h"
+#include <jni.h>
+#include "java/org_libjpegturbo_turbojpeg_TJCompressor.h"
+#include "java/org_libjpegturbo_turbojpeg_TJDecompressor.h"
+#include "java/org_libjpegturbo_turbojpeg_TJ.h"
+
+static const int _pixelsize[org_libjpegturbo_turbojpeg_TJ_NUMPF]=
+	{3, 3, 4, 4, 4, 4, 1};
+
+static const int _flags[org_libjpegturbo_turbojpeg_TJ_NUMPF]=
+	{0, TJ_BGR, 0, TJ_BGR, TJ_BGR|TJ_ALPHAFIRST, TJ_ALPHAFIRST, 0};
+
+#define _throw(msg) {  \
+	jclass _exccls=(*env)->FindClass(env, "java/lang/Exception");  \
+	if(!_exccls) goto bailout;  \
+	(*env)->ThrowNew(env, _exccls, msg);  \
+	goto bailout;  \
+}
+
+#define bailif0(f) {if(!(f)) goto bailout;}
+
+#define gethandle()  \
+	jclass _cls=(*env)->GetObjectClass(env, obj);  \
+	jfieldID _fid;  \
+	if(!_cls) goto bailout;  \
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "handle", "J"));  \
+	handle=(tjhandle)(jlong)(*env)->GetLongField(env, obj, _fid);  \
+
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSize
+	(JNIEnv *env, jclass cls, jint width, jint height)
+{
+	jint retval=(jint)TJBUFSIZE(width, height);
+	if(retval==-1) _throw(tjGetErrorStr());
+
+	bailout:
+	return retval;
+}
+
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV
+	(JNIEnv *env, jclass cls, jint width, jint height, jint subsamp)
+{
+	jint retval=(jint)TJBUFSIZEYUV(width, height, subsamp);
+	if(retval==-1) _throw(tjGetErrorStr());
+
+	bailout:
+	return retval;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_init
+	(JNIEnv *env, jobject obj)
+{
+	jclass cls;
+	jfieldID fid;
+	tjhandle handle;
+
+	if((handle=tjInitCompress())==NULL)
+		_throw(tjGetErrorStr());
+
+	bailif0(cls=(*env)->GetObjectClass(env, obj));
+	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
+	(*env)->SetLongField(env, obj, fid, (jlong)handle);
+
+	bailout:
+	return;
+}
+
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII
+	(JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
+		jint height, jint pf, jbyteArray dst, jint jpegsubsamp, jint jpegqual,
+		jint flags)
+{
+	tjhandle handle=0;  int pixelsize;
+	unsigned long size=0;  jsize arraysize=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+
+	gethandle();
+
+	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
+		|| pitch<0)
+		_throw("Invalid argument in compress()");
+	flags|=_flags[pf];
+	pixelsize=_pixelsize[pf];
+
+	arraysize=(pitch==0)? width*pixelsize*height:pitch*height;
+	if((*env)->GetArrayLength(env, src)<arraysize)
+		_throw("Source buffer is not large enough");
+	if((*env)->GetArrayLength(env, dst)<(jsize)TJBUFSIZE(width, height))
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjCompress(handle, srcbuf, width, pitch, height, pixelsize, dstbuf,
+		&size, jpegsubsamp, jpegqual, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return (jint)size;
+}
+
+JNIEXPORT jint JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII
+	(JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch,
+		jint height, jint pf, jbyteArray dst, jint jpegsubsamp, jint jpegqual,
+		jint flags)
+{
+	tjhandle handle=0;
+	unsigned long size=0;  jsize arraysize=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+
+	gethandle();
+
+	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
+		|| pitch<0)
+		_throw("Invalid argument in compress()");
+	if(_pixelsize[pf]!=sizeof(jint))
+		_throw("Pixel format must be 32-bit when compressing from an integer buffer.");
+	flags|=_flags[pf];
+
+	arraysize=(pitch==0)? width*height:pitch*height;
+	if((*env)->GetArrayLength(env, src)<arraysize)
+		_throw("Source buffer is not large enough");
+	if((*env)->GetArrayLength(env, dst)<(jsize)TJBUFSIZE(width, height))
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjCompress(handle, srcbuf, width, pitch*sizeof(jint), height,
+		sizeof(jint),	dstbuf, &size, jpegsubsamp, jpegqual, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return (jint)size;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII
+	(JNIEnv *env, jobject obj, jbyteArray src, jint width, jint pitch,
+		jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
+{
+	tjhandle handle=0;  int pixelsize;
+	jsize arraysize=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+
+	gethandle();
+
+	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
+		|| pitch<0)
+		_throw("Invalid argument in encodeYUV()");
+	flags|=_flags[pf];
+	pixelsize=_pixelsize[pf];
+
+	arraysize=(pitch==0)? width*pixelsize*height:pitch*height;
+	if((*env)->GetArrayLength(env, src)<arraysize)
+		_throw("Source buffer is not large enough");
+	if((*env)->GetArrayLength(env, dst)
+		<(jsize)TJBUFSIZEYUV(width, height, subsamp))
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjEncodeYUV(handle, srcbuf, width, pitch, height, pixelsize, dstbuf,
+		subsamp, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII
+	(JNIEnv *env, jobject obj, jintArray src, jint width, jint pitch,
+		jint height, jint pf, jbyteArray dst, jint subsamp, jint flags)
+{
+	tjhandle handle=0;
+	jsize arraysize=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+
+	gethandle();
+
+	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF || width<1 || height<1
+		|| pitch<0)
+		_throw("Invalid argument in compress()");
+	if(_pixelsize[pf]!=sizeof(jint))
+		_throw("Pixel format must be 32-bit when encoding from an integer buffer.");
+	flags|=_flags[pf];
+
+	arraysize=(pitch==0)? width*height:pitch*height;
+	if((*env)->GetArrayLength(env, src)<arraysize)
+		_throw("Source buffer is not large enough");
+	if((*env)->GetArrayLength(env, dst)
+		<(jsize)TJBUFSIZEYUV(width, height, subsamp))
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjEncodeYUV(handle, srcbuf, width, pitch*sizeof(jint), height,
+		sizeof(jint),	dstbuf, subsamp, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy
+	(JNIEnv *env, jobject obj)
+{
+	tjhandle handle=0;
+
+	gethandle();
+
+	if(tjDestroy(handle)==-1) _throw(tjGetErrorStr());
+	(*env)->SetLongField(env, obj, _fid, 0);
+
+	bailout:
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_init
+	(JNIEnv *env, jobject obj)
+{
+	jclass cls;
+	jfieldID fid;
+	tjhandle handle;
+
+	if((handle=tjInitDecompress())==NULL) _throw(tjGetErrorStr());
+
+	bailif0(cls=(*env)->GetObjectClass(env, obj));
+	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
+	(*env)->SetLongField(env, obj, fid, (jlong)handle);
+
+	bailout:
+	return;
+}
+
+JNIEXPORT jobjectArray JNICALL Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors
+	(JNIEnv *env, jclass cls)
+{
+  jclass sfcls=NULL;  jfieldID fid=0;
+	tjscalingfactor *sf=NULL;  int n=0, i;
+	jobject sfobj=NULL;
+	jobjectArray sfjava=NULL;
+
+	if((sf=tjGetScalingFactors(&n))==NULL || n==0)
+		_throw(tjGetErrorStr());
+
+	bailif0(sfcls=(*env)->FindClass(env, "org/libjpegturbo/turbojpeg/TJScalingFactor"));
+	bailif0(sfjava=(jobjectArray)(*env)->NewObjectArray(env, n, sfcls, 0));
+
+	for(i=0; i<n; i++)
+	{
+		bailif0(sfobj=(*env)->AllocObject(env, sfcls));
+		bailif0(fid=(*env)->GetFieldID(env, sfcls, "num", "I"));
+		(*env)->SetIntField(env, sfobj, fid, sf[i].num);
+		bailif0(fid=(*env)->GetFieldID(env, sfcls, "denom", "I"));
+		(*env)->SetIntField(env, sfobj, fid, sf[i].denom);
+		(*env)->SetObjectArrayElement(env, sfjava, i, sfobj);
+	}
+
+	bailout:
+	return sfjava;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader
+	(JNIEnv *env, jobject obj, jbyteArray src, jint size)
+{
+	tjhandle handle=0;
+	unsigned char *srcbuf=NULL;
+	int width=0, height=0, jpegsubsamp=-1;
+
+	gethandle();
+
+	if((*env)->GetArrayLength(env, src)<size)
+		_throw("Source buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+
+	if(tjDecompressHeader2(handle, srcbuf, (unsigned long)size, 
+		&width, &height, &jpegsubsamp)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		_throw(tjGetErrorStr());
+	}
+	(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);  srcbuf=NULL;
+
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
+	(*env)->SetIntField(env, obj, _fid, jpegsubsamp);
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
+	(*env)->SetIntField(env, obj, _fid, width);
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
+	(*env)->SetIntField(env, obj, _fid, height);
+
+	bailout:
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII
+	(JNIEnv *env, jobject obj, jbyteArray src, jint size, jbyteArray dst,
+		jint width, jint pitch, jint height, jint pf, jint flags)
+{
+	tjhandle handle=0;  int pixelsize;
+	jsize arraysize=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+
+	gethandle();
+
+	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
+		_throw("Invalid argument in decompress()");
+	flags|=_flags[pf];
+	pixelsize=_pixelsize[pf];
+
+	if((*env)->GetArrayLength(env, src)<size)
+		_throw("Source buffer is not large enough");
+	arraysize=(pitch==0)? width*pixelsize*height:pitch*height;
+	if((*env)->GetArrayLength(env, dst)<arraysize)
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjDecompress(handle, srcbuf, (unsigned long)size, dstbuf, width, pitch,
+		height, pixelsize, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII
+	(JNIEnv *env, jobject obj, jbyteArray src, jint size, jintArray dst,
+		jint width, jint pitch, jint height, jint pf, jint flags)
+{
+	tjhandle handle=0;
+	jsize arraysize=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+
+	gethandle();
+
+	if(pf<0 || pf>=org_libjpegturbo_turbojpeg_TJ_NUMPF)
+		_throw("Invalid argument in decompress()");
+	if(_pixelsize[pf]!=sizeof(jint))
+		_throw("Pixel format must be 32-bit when decompressing to an integer buffer.");
+	flags|=_flags[pf];
+
+	if((*env)->GetArrayLength(env, src)<size)
+		_throw("Source buffer is not large enough");
+	arraysize=(pitch==0)? width*height:pitch*height;
+	if((*env)->GetArrayLength(env, dst)<arraysize)
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjDecompress(handle, srcbuf, (unsigned long)size, dstbuf, width,
+		pitch*sizeof(jint), height, sizeof(jint), flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV
+	(JNIEnv *env, jobject obj, jbyteArray src, jint size, jbyteArray dst,
+		jint flags)
+{
+	tjhandle handle=0;
+	unsigned char *srcbuf=NULL, *dstbuf=NULL;
+	int jpegSubsamp=-1, jpegWidth=0, jpegHeight=0;
+
+	gethandle();
+
+	if((*env)->GetArrayLength(env, src)<size)
+		_throw("Source buffer is not large enough");
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegSubsamp", "I"));
+	jpegSubsamp=(int)(*env)->GetIntField(env, obj, _fid);
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
+	jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
+	jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
+	if((*env)->GetArrayLength(env, dst)
+		<(jsize)TJBUFSIZEYUV(jpegWidth, jpegHeight, jpegSubsamp))
+		_throw("Destination buffer is not large enough");
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, src, 0));
+	bailif0(dstbuf=(*env)->GetPrimitiveArrayCritical(env, dst, 0));
+
+	if(tjDecompressToYUV(handle, srcbuf, (unsigned long)size, dstbuf, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+		(*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+		dstbuf=srcbuf=NULL;
+		_throw(tjGetErrorStr());
+	}
+
+	bailout:
+	if(dstbuf) (*env)->ReleasePrimitiveArrayCritical(env, dst, dstbuf, 0);
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, src, srcbuf, 0);
+	return;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_init
+	(JNIEnv *env, jobject obj)
+{
+	jclass cls;
+	jfieldID fid;
+	tjhandle handle;
+
+	if((handle=tjInitTransform())==NULL) _throw(tjGetErrorStr());
+
+	bailif0(cls=(*env)->GetObjectClass(env, obj));
+	bailif0(fid=(*env)->GetFieldID(env, cls, "handle", "J"));
+	(*env)->SetLongField(env, obj, fid, (jlong)handle);
+
+	bailout:
+	return;
+}
+
+JNIEXPORT jintArray JNICALL Java_org_libjpegturbo_turbojpeg_TJTransformer_transform
+	(JNIEnv *env, jobject obj, jbyteArray jsrcbuf, jint srcsize,
+		jobjectArray dstobjs, jobjectArray tobjs, jint flags)
+{
+	tjhandle handle=0;  int i;
+	unsigned char *srcbuf=NULL, **dstbufs=NULL;  jsize n=0;
+	unsigned long *dstsizes=NULL;  tjtransform *t=NULL;
+	jbyteArray *jdstbufs=NULL;
+	int jpegWidth=0, jpegHeight=0;
+	jintArray jdstsizes=0;  jint *dstsizesi=NULL;
+
+	gethandle();
+
+	if((*env)->GetArrayLength(env, jsrcbuf)<srcsize)
+		_throw("Source buffer is not large enough");
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegWidth", "I"));
+	jpegWidth=(int)(*env)->GetIntField(env, obj, _fid);
+	bailif0(_fid=(*env)->GetFieldID(env, _cls, "jpegHeight", "I"));
+	jpegHeight=(int)(*env)->GetIntField(env, obj, _fid);
+
+	n=(*env)->GetArrayLength(env, dstobjs);
+	if(n!=(*env)->GetArrayLength(env, tobjs))
+		_throw("Mismatch between size of transforms array and destination buffers array");
+
+	if((dstbufs=(unsigned char **)malloc(sizeof(unsigned char *)*n))==NULL)
+		_throw("Memory allocation failure");
+	if((jdstbufs=(jbyteArray *)malloc(sizeof(jbyteArray)*n))==NULL)
+		_throw("Memory allocation failure");
+	if((dstsizes=(unsigned long *)malloc(sizeof(unsigned long)*n))==NULL)
+		_throw("Memory allocation failure");
+	if((t=(tjtransform *)malloc(sizeof(tjtransform)*n))==NULL)
+		_throw("Memory allocation failure");
+	for(i=0; i<n; i++)
+	{
+		dstbufs[i]=NULL;  jdstbufs[i]=NULL;  dstsizes[i]=0;
+		memset(&t[i], 0, sizeof(tjtransform));
+	}
+
+	for(i=0; i<n; i++)
+	{
+		jobject tobj;
+
+		bailif0(tobj=(*env)->GetObjectArrayElement(env, tobjs, i));
+		bailif0(_cls=(*env)->GetObjectClass(env, tobj));
+		bailif0(_fid=(*env)->GetFieldID(env, _cls, "op", "I"));
+		t[i].op=(*env)->GetIntField(env, tobj, _fid);
+		bailif0(_fid=(*env)->GetFieldID(env, _cls, "options", "I"));
+		t[i].options=(*env)->GetIntField(env, tobj, _fid);
+		bailif0(_fid=(*env)->GetFieldID(env, _cls, "x", "I"));
+		t[i].r.x=(*env)->GetIntField(env, tobj, _fid);
+		bailif0(_fid=(*env)->GetFieldID(env, _cls, "y", "I"));
+		t[i].r.y=(*env)->GetIntField(env, tobj, _fid);
+		bailif0(_fid=(*env)->GetFieldID(env, _cls, "width", "I"));
+		t[i].r.w=(*env)->GetIntField(env, tobj, _fid);
+		bailif0(_fid=(*env)->GetFieldID(env, _cls, "height", "I"));
+		t[i].r.h=(*env)->GetIntField(env, tobj, _fid);
+	}
+
+	bailif0(srcbuf=(*env)->GetPrimitiveArrayCritical(env, jsrcbuf, 0));
+	for(i=0; i<n; i++)
+	{
+		int w=jpegWidth, h=jpegHeight;
+		if(t[i].r.w!=0) w=t[i].r.w;
+		if(t[i].r.h!=0) h=t[i].r.h;
+		bailif0(jdstbufs[i]=(*env)->GetObjectArrayElement(env, dstobjs, i));
+		if((*env)->GetArrayLength(env, jdstbufs[i])<TJBUFSIZE(w, h))
+			_throw("Destination buffer is not large enough");
+		bailif0(dstbufs[i]=(*env)->GetPrimitiveArrayCritical(env, jdstbufs[i], 0));
+	}
+
+	if(tjTransform(handle, srcbuf, srcsize, n, dstbufs, dstsizes, t, flags)==-1)
+	{
+		(*env)->ReleasePrimitiveArrayCritical(env, jsrcbuf, srcbuf, 0);
+		srcbuf=NULL;
+		for(i=0; i<n; i++)
+		{
+			(*env)->ReleasePrimitiveArrayCritical(env, jdstbufs[i], dstbufs[i], 0);
+			dstbufs[i]=NULL;
+		}
+		_throw(tjGetErrorStr());
+	}
+
+	jdstsizes=(*env)->NewIntArray(env, n);
+	bailif0(dstsizesi=(*env)->GetIntArrayElements(env, jdstsizes, 0));
+	for(i=0; i<n; i++) dstsizesi[i]=(int)dstsizes[i];
+
+	bailout:
+	if(srcbuf) (*env)->ReleasePrimitiveArrayCritical(env, jsrcbuf, srcbuf, 0);
+	if(dstbufs)
+	{
+		for(i=0; i<n; i++)
+		{
+			if(dstbufs[i] && jdstbufs && jdstbufs[i])
+				(*env)->ReleasePrimitiveArrayCritical(env, jdstbufs[i], dstbufs[i], 0);
+		}
+		free(dstbufs);
+	}
+	if(jdstbufs) free(jdstbufs);
+	if(dstsizes) free(dstsizes);
+	if(dstsizesi) (*env)->ReleaseIntArrayElements(env, jdstsizes, dstsizesi, 0);
+	if(t) free(t);
+	return jdstsizes;
+}
+
+JNIEXPORT void JNICALL Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy
+	(JNIEnv *env, jobject obj)
+{
+	Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy(env, obj);
+}
diff --git a/turbojpeg-mapfile b/turbojpeg-mapfile
index aa0b658..293bd42 100755
--- a/turbojpeg-mapfile
+++ b/turbojpeg-mapfile
@@ -21,3 +21,11 @@
 		tjDecompressToYUV;
 		tjEncodeYUV;
 } TURBOJPEG_1.0;
+
+TURBOJPEG_1.2
+{
+	global:
+		tjGetScalingFactors;
+		tjInitTransform;
+		tjTransform;
+} TURBOJPEG_1.1;
diff --git a/turbojpeg-mapfile.jni b/turbojpeg-mapfile.jni
new file mode 100755
index 0000000..2360d94
--- /dev/null
+++ b/turbojpeg-mapfile.jni
@@ -0,0 +1,48 @@
+TURBOJPEG_1.0
+{
+	global:
+		tjInitCompress;
+		tjCompress;
+		TJBUFSIZE;
+		tjInitDecompress;
+		tjDecompressHeader;
+		tjDecompress;
+		tjDestroy;
+		tjGetErrorStr;
+	local:
+		*;
+};
+
+TURBOJPEG_1.1
+{
+	global:
+		TJBUFSIZEYUV;
+		tjDecompressHeader2;
+		tjDecompressToYUV;
+		tjEncodeYUV;
+} TURBOJPEG_1.0;
+
+TURBOJPEG_1.2
+{
+	global:
+		tjGetScalingFactors;
+		tjInitTransform;
+		tjTransform;
+		Java_org_libjpegturbo_turbojpeg_TJ_bufSize;
+		Java_org_libjpegturbo_turbojpeg_TJ_bufSizeYUV;
+		Java_org_libjpegturbo_turbojpeg_TJ_getScalingFactors;
+		Java_org_libjpegturbo_turbojpeg_TJCompressor_init;
+		Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3BIIII_3BIII;
+		Java_org_libjpegturbo_turbojpeg_TJCompressor_compress___3IIIII_3BIII;
+		Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3BIIII_3BII;
+		Java_org_libjpegturbo_turbojpeg_TJCompressor_encodeYUV___3IIIII_3BII;
+		Java_org_libjpegturbo_turbojpeg_TJCompressor_destroy;
+		Java_org_libjpegturbo_turbojpeg_TJDecompressor_init;
+		Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressHeader;
+		Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3BIIIII;
+		Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompress___3BI_3IIIIII;
+		Java_org_libjpegturbo_turbojpeg_TJDecompressor_decompressToYUV;
+		Java_org_libjpegturbo_turbojpeg_TJDecompressor_destroy;		
+		Java_org_libjpegturbo_turbojpeg_TJTransformer_init;
+		Java_org_libjpegturbo_turbojpeg_TJTransformer_transform;
+} TURBOJPEG_1.1;
diff --git a/turbojpeg.h b/turbojpeg.h
index 24816d7..e075277 100644
--- a/turbojpeg.h
+++ b/turbojpeg.h
@@ -22,19 +22,27 @@
 #define DLLCALL
 
 /* Subsampling */
-#define NUMSUBOPT 4
+#define NUMSUBOPT 5
 
-enum {TJ_444=0, TJ_422, TJ_420, TJ_GRAYSCALE};
+enum {TJ_444=0, TJ_422, TJ_420, TJ_GRAYSCALE, TJ_440};
 #define TJ_411 TJ_420  /* for backward compatibility with VirtualGL <= 2.1.x,
                           TurboVNC <= 0.6, and TurboJPEG/IPP */
 
+/* MCU block sizes:
+   8x8 for no subsampling or grayscale
+   16x8 for 4:2:2
+   8x16 for 4:4:0
+   16x16 for 4:2:0 */
+static const int tjmcuw[NUMSUBOPT]={8, 16, 16, 8, 8};
+static const int tjmcuh[NUMSUBOPT]={8, 8, 16, 8, 16};
+
 /* Flags */
 #define TJ_BGR             1
-  /* The components of each pixel in the source/destination bitmap are stored
-     in B,G,R order, not R,G,B */
+  /* The components of each pixel in the uncompressed source/destination image
+     are stored in B,G,R order, not R,G,B */
 #define TJ_BOTTOMUP        2
-  /* The source/destination bitmap is stored in bottom-up (Windows, OpenGL)
-     order, not top-down (X11) order */
+  /* The uncompressed source/destination image is stored in bottom-up (Windows,
+     OpenGL) order, not top-down (X11) order */
 #define TJ_FORCEMMX        8
   /* Turn off CPU auto-detection and force TurboJPEG to use MMX code
      (IPP and 32-bit libjpeg-turbo versions only) */
@@ -45,23 +53,87 @@
   /* Turn off CPU auto-detection and force TurboJPEG to use SSE2 code
      (32-bit IPP and 32-bit libjpeg-turbo versions only) */
 #define TJ_ALPHAFIRST     64
-  /* If the source/destination bitmap is 32 bpp, assume that each pixel is
-     ARGB/XRGB (or ABGR/XBGR if TJ_BGR is also specified) */
+  /* If the uncompressed source/destination image has 32 bits per pixel,
+     assume that each pixel is ARGB/XRGB (or ABGR/XBGR if TJ_BGR is also
+     specified) */
 #define TJ_FORCESSE3     128
   /* Turn off CPU auto-detection and force TurboJPEG to use SSE3 code
      (64-bit IPP version only) */
 #define TJ_FASTUPSAMPLE  256
-  /* Use fast, inaccurate 4:2:2 and 4:2:0 YUV upsampling routines
-     (libjpeg and libjpeg-turbo versions only) */
+  /* Use fast, inaccurate chrominance upsampling routines in the JPEG
+     decompressor (libjpeg and libjpeg-turbo versions only) */
 #define TJ_YUV           512
   /* Nothing to see here.  Pay no attention to the man behind the curtain. */
 
+/* Scaling factor structure */
+typedef struct
+{
+	int num, denom;
+} tjscalingfactor;
+
+/* Transform operations for tjTransform() */
+#define NUMXFORMOPT 8
+
+enum {
+TJXFORM_NONE=0,     /* Do not transform the position of the image pixels */
+TJXFORM_HFLIP,      /* Flip (mirror) image horizontally.  This transform is
+                       imperfect if there are any partial MCU blocks on the
+                       right edge (see below for explanation.) */
+TJXFORM_VFLIP,      /* Flip (mirror) image vertically.  This transform is
+                       imperfect if there are any partial MCU blocks on the
+                       bottom edge. */
+TJXFORM_TRANSPOSE,  /* Transpose image (flip/mirror along upper left to lower
+                       right axis.)  This transform is always perfect. */
+TJXFORM_TRANSVERSE, /* Transverse transpose image (flip/mirror along upper
+                       right to lower left axis.)  This transform is imperfect
+                       if there are any partial MCU blocks in the image. */
+TJXFORM_ROT90,      /* Rotate image clockwise by 90 degrees.  This transform
+                       is imperfect if there are any partial MCU blocks on the
+                       bottom edge. */
+TJXFORM_ROT180,     /* Rotate image 180 degrees.  This transform is imperfect
+                       if there are any partial MCU blocks in the image. */
+TJXFORM_ROT270      /* Rotate image counter-clockwise by 90 degrees.  This
+                       transform is imperfect if there are any partial MCU
+                       blocks on the right edge. */
+};
+
+/* Transform options (these can be OR'ed together) */
+#define TJXFORM_PERFECT  1
+  /* This will cause the tjTransform() function to return an error if the
+     transform is not perfect.  Lossless transforms operate on MCU blocks,
+     whose size depends on the level of chrominance subsampling used (see
+     "MCU block sizes" above).  If the image's width or height is not evenly
+     divisible by the MCU block size, then there will be partial MCU blocks on
+     the right and/or bottom edges.  It is not possible to move these partial
+     MCU blocks to the top or left of the image, so any transform that would
+     require that is "imperfect."  If this option is not specified, then any
+     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.
+     */
+#define TJXFORM_TRIM     2
+  /* This option will cause tjTransform() to discard any partial MCU blocks
+     that cannot be transformed. */
+#define TJXFORM_CROP     4
+  /* This option will enable lossless cropping.  See the description of
+     tjTransform() below for more information. */
+#define TJXFORM_GRAY     8
+  /* This option will discard the color data in the input image and produce
+     a grayscale output image. */
+
+typedef struct
+{
+	int x, y, w, h;
+} tjregion;
+
+typedef struct
+{
+	tjregion r;
+	int op, options;
+} tjtransform;
+
 typedef void* tjhandle;
 
 #define TJPAD(p) (((p)+3)&(~3))
-#ifndef max
- #define max(a,b) ((a)>(b)?(a):(b))
-#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -86,18 +158,18 @@
 
 
 /*
-  int tjCompress(tjhandle j,
+  int tjCompress(tjhandle hnd,
      unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
      unsigned char *dstbuf, unsigned long *size,
      int jpegsubsamp, int jpegqual, int flags)
 
-  [INPUT] j = instance handle previously returned from a call to
-     tjInitCompress()
+  [INPUT] hnd = instance handle previously returned from a call to
+     tjInitCompress() or tjInitTransform()
   [INPUT] srcbuf = pointer to user-allocated image buffer containing RGB or
      grayscale pixels to be compressed
   [INPUT] width = width (in pixels) of the source image
   [INPUT] pitch = bytes per line of the source image (width*pixelsize if the
-     bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap
+     image is unpadded, else TJPAD(width*pixelsize) if each line of the image
      is padded to the nearest 32-bit boundary, such as is the case for Windows
      bitmaps.  You can also be clever and use this parameter to skip lines,
      etc.  Setting this parameter to 0 is the equivalent of setting it to
@@ -107,22 +179,26 @@
      RGBX/BGRX/XRGB/XBGR: 4, RGB/BGR: 3, Grayscale: 1
   [INPUT] dstbuf = pointer to user-allocated image buffer which will receive
      the JPEG image.  Use the TJBUFSIZE(width, height) function to determine
-     the appropriate size for this buffer based on the image width and height.
-  [OUTPUT] size = pointer to unsigned long which receives the size (in bytes)
-     of the compressed image
-  [INPUT] jpegsubsamp = Specifies either 4:2:0, 4:2:2, 4:4:4, or grayscale
-     subsampling.  When the image is converted from the RGB to YCbCr colorspace
-     as part of the JPEG compression process, every other Cb and Cr
-     (chrominance) pixel can be discarded to produce a smaller image with
+     the maximum size for this buffer based on the image width and height.
+  [OUTPUT] size = pointer to unsigned long which receives the actual size (in
+     bytes) of the JPEG image
+  [INPUT] jpegsubsamp = Specifies the level of chrominance subsampling.  When
+     the image is converted from the RGB to YCbCr colorspace as part of the
+     JPEG compression process, some of the Cb and Cr (chrominance) components
+     can be discarded or averaged together to produce a smaller image with
      little perceptible loss of image clarity (the human eye is more sensitive
      to small changes in brightness than small changes in color.)
 
-     TJ_420: 4:2:0 subsampling.  Discards every other Cb, Cr pixel in both
-        horizontal and vertical directions
-     TJ_422: 4:2:2 subsampling.  Discards every other Cb, Cr pixel only in
-        the horizontal direction
-     TJ_444: no subsampling
-     TJ_GRAYSCALE: Generate grayscale JPEG image
+     TJ_420: 4:2:0 subsampling.  The JPEG image will contain one chrominance
+        component for every 2x2 block of pixels in the source image.
+     TJ_422: 4:2:2 subsampling.  The JPEG image will contain one chrominance
+        component for every 2x1 block of pixels in the source image.
+     TJ_440: 4:4:0 subsampling.  The JPEG image will contain one chrominance
+        component for every 1x2 block of pixels in the source image.
+     TJ_444: no subsampling.  The JPEG image will contain one chrominance
+        component for every pixel in the source image.
+     TJ_GRAYSCALE: Generate grayscale JPEG image.  The JPEG image will contain
+        no chrominance components.
 
   [INPUT] jpegqual = JPEG quality (an integer between 0 and 100 inclusive)
   [INPUT] flags = the bitwise OR of one or more of the flags described in the
@@ -130,7 +206,7 @@
 
   RETURNS: 0 on success, -1 on error
 */
-DLLEXPORT int DLLCALL tjCompress(tjhandle j,
+DLLEXPORT int DLLCALL tjCompress(tjhandle hnd,
 	unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
 	unsigned char *dstbuf, unsigned long *size,
 	int jpegsubsamp, int jpegqual, int flags);
@@ -161,7 +237,7 @@
 
 
 /*
-  int tjEncodeYUV(tjhandle j,
+  int tjEncodeYUV(tjhandle hnd,
      unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
      unsigned char *dstbuf, int subsamp, int flags)
 
@@ -176,13 +252,13 @@
   combination with TJ_420, which produces an image compatible with the I420
   (AKA "YUV420P") format.
 
-  [INPUT] j = instance handle previously returned from a call to
-     tjInitCompress()
+  [INPUT] hnd = instance handle previously returned from a call to
+     tjInitCompress() or tjInitTransform()
   [INPUT] srcbuf = pointer to user-allocated image buffer containing RGB or
      grayscale pixels to be encoded
   [INPUT] width = width (in pixels) of the source image
   [INPUT] pitch = bytes per line of the source image (width*pixelsize if the
-     bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the bitmap
+     image is unpadded, else TJPAD(width*pixelsize) if each line of the image
      is padded to the nearest 32-bit boundary, such as is the case for Windows
      bitmaps.  You can also be clever and use this parameter to skip lines,
      etc.  Setting this parameter to 0 is the equivalent of setting it to
@@ -194,14 +270,14 @@
      the YUV image.  Use the TJBUFSIZEYUV(width, height, subsamp) function to
      determine the appropriate size for this buffer based on the image width,
      height, and level of subsampling.
-  [INPUT] subsamp = Specifies either 4:2:0, 4:2:2, 4:4:4, or grayscale
-     subsampling (see description under tjCompress())
+  [INPUT] subsamp = specifies the level of chrominance subsampling for the
+     YUV image.  See description under tjCompress())
   [INPUT] flags = the bitwise OR of one or more of the flags described in the
      "Flags" section above
 
   RETURNS: 0 on success, -1 on error
 */
-DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle j,
+DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle hnd,
 	unsigned char *srcbuf, int width, int pitch, int height, int pixelsize,
 	unsigned char *dstbuf, int subsamp, int flags);
 
@@ -222,12 +298,12 @@
 
 
 /*
-  int tjDecompressHeader2(tjhandle j,
+  int tjDecompressHeader2(tjhandle hnd,
      unsigned char *srcbuf, unsigned long size,
      int *width, int *height, int *jpegsubsamp)
 
-  [INPUT] j = instance handle previously returned from a call to
-     tjInitDecompress()
+  [INPUT] hnd = instance handle previously returned from a call to
+     tjInitDecompress() or tjInitTransform()
   [INPUT] srcbuf = pointer to a user-allocated buffer containing a JPEG image
   [INPUT] size = size of the JPEG image buffer (in bytes)
   [OUTPUT] width = width (in pixels) of the JPEG image
@@ -237,41 +313,67 @@
 
   RETURNS: 0 on success, -1 on error
 */
-DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle j,
+DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	int *width, int *height, int *jpegsubsamp);
 
 /*
   Legacy version of the above function
 */
-DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle j,
+DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	int *width, int *height);
 
 
 /*
-  int tjDecompress(tjhandle j,
+  tjscalingfactor *tjGetScalingFactors(int *numscalingfactors)
+
+  Returns a list of fractional scaling factors that the JPEG decompressor in
+  this implementation of TurboJPEG supports.
+
+  [OUTPUT] numscalingfactors = the size of the list
+
+  RETURNS: NULL on error
+*/
+DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors);
+
+
+/*
+  int tjDecompress(tjhandle hnd,
      unsigned char *srcbuf, unsigned long size,
      unsigned char *dstbuf, int width, int pitch, int height, int pixelsize,
      int flags)
 
-  [INPUT] j = instance handle previously returned from a call to
-     tjInitDecompress()
+  [INPUT] hnd = instance handle previously returned from a call to
+     tjInitDecompress() or tjInitTransform()
   [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
      to decompress
   [INPUT] size = size of the JPEG image buffer (in bytes)
   [INPUT] dstbuf = pointer to user-allocated image buffer which will receive
-     the bitmap image.  This buffer should normally be pitch*height
-     bytes in size, although this pointer may also be used to decompress into
-     a specific region of a larger buffer.
-  [INPUT] width = width (in pixels) of the destination image
-  [INPUT] pitch = bytes per line of the destination image (width*pixelsize if
-     the bitmap is unpadded, else TJPAD(width*pixelsize) if each line of the
-     bitmap is padded to the nearest 32-bit boundary, such as is the case for
-     Windows bitmaps.  You can also be clever and use this parameter to skip
-     lines, etc.  Setting this parameter to 0 is the equivalent of setting it
-     to width*pixelsize.
-  [INPUT] height = height (in pixels) of the destination image
+     the decompressed image.  This buffer should normally be
+     pitch*scaled_height bytes in size, where scaled_height is
+     ceil(jpeg_height*scaling_factor), and the supported scaling factors can be
+     determined by calling tjGetScalingFactors().  The dstbuf pointer may also
+     be used to decompress into a specific region of a larger buffer.
+  [INPUT] width = desired width (in pixels) of the destination image.  If this
+     is smaller than the width of the JPEG image being decompressed, then
+     TurboJPEG will use scaling in the JPEG decompressor to generate the
+     largest possible image that will fit within the desired width.  If width
+     is set to 0, then only the height will be considered when determining the
+     scaled image size.
+  [INPUT] pitch = bytes per line of the destination image.  Normally, this is
+     scaled_width*pixelsize if the decompressed image is unpadded, else
+     TJPAD(scaled_width*pixelsize) if each line of the decompressed image is
+     padded to the nearest 32-bit boundary, such as is the case for Windows
+     bitmaps.  (NOTE: scaled_width = ceil(jpeg_width*scaling_factor).)  You can
+     also be clever and use this parameter to skip lines, etc.  Setting this
+     parameter to 0 is the equivalent of setting it to scaled_width*pixelsize.
+  [INPUT] height = desired height (in pixels) of the destination image.  If
+     this is smaller than the height of the JPEG image being decompressed, then
+     TurboJPEG will use scaling in the JPEG decompressor to generate the
+     largest possible image that will fit within the desired height.  If
+     height is set to 0, then only the width will be considered when
+     determining the scaled image size.
   [INPUT] pixelsize = size (in bytes) of each pixel in the destination image
      RGBX/BGRX/XRGB/XBGR: 4, RGB/BGR: 3, Grayscale: 1
   [INPUT] flags = the bitwise OR of one or more of the flags described in the
@@ -279,26 +381,26 @@
 
   RETURNS: 0 on success, -1 on error
 */
-DLLEXPORT int DLLCALL tjDecompress(tjhandle j,
+DLLEXPORT int DLLCALL tjDecompress(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	unsigned char *dstbuf, int width, int pitch, int height, int pixelsize,
 	int flags);
 
 
 /*
-  int tjDecompressToYUV(tjhandle j,
+  int tjDecompressToYUV(tjhandle hnd,
      unsigned char *srcbuf, unsigned long size,
      unsigned char *dstbuf, int flags)
 
   This function performs JPEG decompression but leaves out the color conversion
   step, so a planar YUV image is generated instead of an RGB image.  The
-  padding of the planes in this image is the same as in tjEncodeYUV().
-  Note that, if the width or height of the output image is not a multiple of 8
-  (or a multiple of 16 along any dimension in which chrominance subsampling is
-  used), then an intermediate buffer copy will be performed within TurboJPEG.
+  padding of the planes in this image is the same as the images generated
+  by tjEncodeYUV().  Note that, if the width or height of the image is not an
+  even multiple of the MCU block size (see "MCU block sizes" above), then an
+  intermediate buffer copy will be performed within TurboJPEG.
 
-  [INPUT] j = instance handle previously returned from a call to
-     tjInitDecompress()
+  [INPUT] hnd = instance handle previously returned from a call to
+     tjInitDecompress() or tjInitTransform()
   [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
      to decompress
   [INPUT] size = size of the JPEG image buffer (in bytes)
@@ -311,18 +413,94 @@
 
   RETURNS: 0 on success, -1 on error
 */
-DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle j,
+DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	unsigned char *dstbuf, int flags);
 
 
 /*
+  tjhandle tjInitTransform(void)
+
+  Creates a new JPEG transformer instance, allocates memory for the structures,
+  and returns a handle to the instance.  Most applications will only need to
+  call this once at the beginning of the program or once for each concurrent
+  thread.  Don't try to create a new instance every time you transform an
+  image, because this may cause performance to suffer in some TurboJPEG
+  implementations.
+
+  RETURNS: NULL on error
+*/
+DLLEXPORT tjhandle DLLCALL tjInitTransform(void);
+
+
+/*
+  int tjTransform(tjhandle hnd,
+     unsigned char *srcbuf, unsigned long srcsize,
+     int n, unsigned char **dstbufs, unsigned long *dstsizes,
+     tjtransform *transforms, int flags);
+
+  This function can losslessly transform a JPEG image into another JPEG image.
+  Lossless transforms work by moving the raw coefficients from one JPEG image
+  structure to another without altering the values of the coefficients.  While
+  this is typically faster than decompressing the image, transforming it, and
+  re-compressing it, lossless transforms are not free.  Each lossless transform
+  requires reading and Huffman decoding all of the coefficients in the source
+  image, regardless of the size of the destination image.  Thus, this function
+  provides a means of generating multiple transformed images from the same
+  source or of applying multiple transformations simultaneously, in order to
+  eliminate the need to read the source coefficients multiple times.
+
+  [INPUT] hnd = instance handle previously returned from a call to
+     tjInitTransform()
+  [INPUT] srcbuf = pointer to a user-allocated buffer containing the JPEG image
+     to transform
+  [INPUT] srcsize = size of the source JPEG image buffer (in bytes)
+  [INPUT] n = the number of transformed JPEG images to generate
+  [INPUT] dstbufs = pointer to an array of n user-allocated image buffers.
+     dstbufs[i] will receive a JPEG image that has been transformed using the
+     parameters in transforms[i].  Use the TJBUFSIZE(width, height) function to
+     determine the maximum size for each buffer based on the cropped width and
+     height.
+  [OUTPUT] dstsizes = pointer to an array of n unsigned longs which will
+     receive the actual sizes (in bytes) of each transformed JPEG image
+  [INPUT] transforms = pointer to an array of n tjtransform structures, each of
+     which specifies the transform parameters and/or cropping region for the
+     corresponding transformed output image.  The structure members are as
+     follows:
+
+     r.x = the left boundary of the cropping region.  This must be evenly
+        divisible by tjmcuw[subsamp] (the MCU block width corresponding to the
+        level of chrominance subsampling used in the source image)
+     r.y = the upper boundary of the cropping region.  This must be evenly
+        divisible by tjmcuh[subsamp] (the MCU block height corresponding to the
+        level of chrominance subsampling used in the source image)
+     r.w = the width of the cropping region.  Setting this to 0 is the
+        equivalent of setting it to the width of the source JPEG image - r.x.
+     r.h = the height of the cropping region.  Setting this to 0 is the
+        equivalent of setting it to the height of the source JPEG image - r.y.
+     op = one of the transform operations described in the
+        "Transform operations" section above
+     options = the bitwise OR of one or more of the transform options described
+        in the "Transform options" section above.
+
+  [INPUT] flags = the bitwise OR of one or more of the flags described in the
+     "Flags" section above.
+
+  RETURNS: 0 on success, -1 on error
+*/
+DLLEXPORT int DLLCALL tjTransform(tjhandle hnd,
+	unsigned char *srcbuf, unsigned long srcsize,
+	int n, unsigned char **dstbufs, unsigned long *dstsizes,
+	tjtransform *transforms, int flags);
+
+
+/*
   int tjDestroy(tjhandle h)
 
   Frees structures associated with a compression or decompression instance
   
   [INPUT] h = instance handle (returned from a previous call to
-     tjInitCompress() or tjInitDecompress()
+     tjInitCompress(), tjInitDecompress(), or tjInitTransform()
 
   RETURNS: 0 on success, -1 on error
 */
diff --git a/turbojpegl.c b/turbojpegl.c
index 5cc5437..266e335 100644
--- a/turbojpegl.c
+++ b/turbojpegl.c
@@ -23,6 +23,8 @@
 #include <jerror.h>
 #include <setjmp.h>
 #include "./turbojpeg.h"
+#include "./rrutil.h"
+#include "transupp.h"
 
 #ifndef min
  #define min(a,b) ((a)<(b)?(a):(b))
@@ -66,13 +68,23 @@
 	int initc, initd;
 } jpgstruct;
 
-static const int hsampfactor[NUMSUBOPT]={1, 2, 2, 1};
-static const int vsampfactor[NUMSUBOPT]={1, 1, 2, 1};
-static const int pixelsize[NUMSUBOPT]={3, 3, 3, 1};
+static const int pixelsize[NUMSUBOPT]={3, 3, 3, 1, 3};
+static const JXFORM_CODE xformtypes[NUMXFORMOPT]={
+	JXFORM_NONE, JXFORM_FLIP_H, JXFORM_FLIP_V, JXFORM_TRANSPOSE,
+	JXFORM_TRANSVERSE, JXFORM_ROT_90, JXFORM_ROT_180, JXFORM_ROT_270
+};
+#define NUMSF 4
+static const tjscalingfactor sf[NUMSF]={
+	{1, 1},
+	{1, 2},
+	{1, 4},
+	{1, 8}
+};
 
-#define _throw(c) {sprintf(lasterror, "%s", c);  retval=-1;  goto bailout;}
-#define checkhandle(h) jpgstruct *j=(jpgstruct *)h; \
-	if(!j) {sprintf(lasterror, "Invalid handle");  return -1;}
+#define _throw(c) {snprintf(lasterror, JMSG_LENGTH_MAX, "%s", c);  \
+	retval=-1;  goto bailout;}
+#define checkhandle(hnd) jpgstruct *j=(jpgstruct *)hnd; \
+	if(!j) {snprintf(lasterror, JMSG_LENGTH_MAX, "Invalid handle");  return -1;}
 
 
 // CO
@@ -87,12 +99,8 @@
 {
 }
 
-DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
+static tjhandle _tjInitCompress(jpgstruct *j)
 {
-	jpgstruct *j=NULL;
-	if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
-		{sprintf(lasterror, "Memory allocation failure");  return NULL;}
-	memset(j, 0, sizeof(jpgstruct));
 	j->cinfo.err=jpeg_std_error(&j->jerr.pub);
 	j->jerr.pub.error_exit=my_error_exit;
 	j->jerr.pub.output_message=my_output_message;
@@ -112,6 +120,18 @@
 	return (tjhandle)j;
 }
 
+DLLEXPORT tjhandle DLLCALL tjInitCompress(void)
+{
+	jpgstruct *j=NULL;
+	if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
+	{
+		snprintf(lasterror, JMSG_LENGTH_MAX, "Memory allocation failure");
+		return NULL;
+	}
+	memset(j, 0, sizeof(jpgstruct));
+	return _tjInitCompress(j);
+}
+
 
 DLLEXPORT unsigned long DLLCALL TJBUFSIZE(int width, int height)
 {
@@ -136,9 +156,9 @@
 	int pw, ph, cw, ch;
 	if(width<1 || height<1 || subsamp<0 || subsamp>=NUMSUBOPT)
 		_throw("Invalid argument in TJBUFSIZEYUV()");
-	pw=PAD(width, hsampfactor[subsamp]);
-	ph=PAD(height, vsampfactor[subsamp]);
-	cw=pw/hsampfactor[subsamp];  ch=ph/vsampfactor[subsamp];
+	pw=PAD(width, tjmcuw[subsamp]/8);
+	ph=PAD(height, tjmcuh[subsamp]/8);
+	cw=pw*8/tjmcuw[subsamp];  ch=ph*8/tjmcuh[subsamp];
 	retval=PAD(pw, 4)*ph + (subsamp==TJ_GRAYSCALE? 0:PAD(cw, 4)*ch*2);
 
 	bailout:
@@ -146,7 +166,7 @@
 }
 
 
-DLLEXPORT int DLLCALL tjCompress(tjhandle h,
+DLLEXPORT int DLLCALL tjCompress(tjhandle hnd,
 	unsigned char *srcbuf, int width, int pitch, int height, int ps,
 	unsigned char *dstbuf, unsigned long *size,
 	int jpegsub, int qual, int flags)
@@ -156,7 +176,7 @@
 	JSAMPROW *tmpbuf[MAX_COMPONENTS], *tmpbuf2[MAX_COMPONENTS];
 	JSAMPROW *outbuf[MAX_COMPONENTS];
 
-	checkhandle(h);
+	checkhandle(hnd);
 
 	for(i=0; i<MAX_COMPONENTS; i++)
 	{
@@ -215,10 +235,10 @@
 	if(qual>=96) j->cinfo.dct_method=JDCT_ISLOW;
 	else j->cinfo.dct_method=JDCT_FASTEST;
 
-	j->cinfo.comp_info[0].h_samp_factor=hsampfactor[jpegsub];
+	j->cinfo.comp_info[0].h_samp_factor=tjmcuw[jpegsub]/8;
 	j->cinfo.comp_info[1].h_samp_factor=1;
 	j->cinfo.comp_info[2].h_samp_factor=1;
-	j->cinfo.comp_info[0].v_samp_factor=vsampfactor[jpegsub];
+	j->cinfo.comp_info[0].v_samp_factor=tjmcuh[jpegsub]/8;
 	j->cinfo.comp_info[1].v_samp_factor=1;
 	j->cinfo.comp_info[2].v_samp_factor=1;
 
@@ -336,12 +356,12 @@
 }
 
 
-DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle h,
+DLLEXPORT int DLLCALL tjEncodeYUV(tjhandle hnd,
 	unsigned char *srcbuf, int width, int pitch, int height, int ps,
 	unsigned char *dstbuf, int subsamp, int flags)
 {
 	unsigned long size;
-	return tjCompress(h, srcbuf, width, pitch, height, ps, dstbuf, &size,
+	return tjCompress(hnd, srcbuf, width, pitch, height, ps, dstbuf, &size,
 		subsamp, 0, flags|TJ_YUV);
 }
 
@@ -364,12 +384,8 @@
 {
 }
 
-DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
+static tjhandle _tjInitDecompress(jpgstruct *j)
 {
-	jpgstruct *j;
-	if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
-		{sprintf(lasterror, "Memory allocation failure");  return NULL;}
-	memset(j, 0, sizeof(jpgstruct));
 	j->dinfo.err=jpeg_std_error(&j->jerr.pub);
 	j->jerr.pub.error_exit=my_error_exit;
 	j->jerr.pub.output_message=my_output_message;
@@ -391,14 +407,26 @@
 	return (tjhandle)j;
 }
 
+DLLEXPORT tjhandle DLLCALL tjInitDecompress(void)
+{
+	jpgstruct *j;
+	if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
+	{
+		snprintf(lasterror, JMSG_LENGTH_MAX, "Memory allocation failure");
+		return NULL;
+	}
+	memset(j, 0, sizeof(jpgstruct));
+	return _tjInitDecompress(j);
+}
 
-DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle h,
+
+DLLEXPORT int DLLCALL tjDecompressHeader2(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	int *width, int *height, int *jpegsub)
 {
 	int i, k, retval=0;
 
-	checkhandle(h);
+	checkhandle(hnd);
 
 	if(srcbuf==NULL || size<=0 || width==NULL || height==NULL || jpegsub==NULL)
 		_throw("Invalid argument in tjDecompressHeader2()");
@@ -420,8 +448,8 @@
 	{
 		if(j->dinfo.num_components==pixelsize[i])
 		{
-			if(j->dinfo.comp_info[0].h_samp_factor==hsampfactor[i]
-				&& j->dinfo.comp_info[0].v_samp_factor==vsampfactor[i])
+			if(j->dinfo.comp_info[0].h_samp_factor==tjmcuw[i]/8
+				&& j->dinfo.comp_info[0].v_samp_factor==tjmcuh[i]/8)
 			{
 				int match=0;
 				for(k=1; k<j->dinfo.num_components; k++)
@@ -448,16 +476,30 @@
 }
 
 
-DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle h,
+DLLEXPORT int DLLCALL tjDecompressHeader(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	int *width, int *height)
 {
 	int jpegsub;
-	return tjDecompressHeader2(h, srcbuf, size, width, height, &jpegsub);
+	return tjDecompressHeader2(hnd, srcbuf, size, width, height, &jpegsub);
 }
 
 
-DLLEXPORT int DLLCALL tjDecompress(tjhandle h,
+DLLEXPORT tjscalingfactor* DLLCALL tjGetScalingFactors(int *numscalingfactors)
+{
+	if(numscalingfactors==NULL)
+	{
+		snprintf(lasterror, JMSG_LENGTH_MAX,
+			"Invalid argument in tjGetScalingFactors()");
+		return NULL;
+	}
+
+	*numscalingfactors=NUMSF;
+	return (tjscalingfactor *)sf;
+}
+
+
+DLLEXPORT int DLLCALL tjDecompress(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	unsigned char *dstbuf, int width, int pitch, int height, int ps,
 	int flags)
@@ -466,8 +508,9 @@
 	int cw[MAX_COMPONENTS], ch[MAX_COMPONENTS], iw[MAX_COMPONENTS],
 		tmpbufsize=0, usetmpbuf=0, th[MAX_COMPONENTS];
 	JSAMPLE *_tmpbuf=NULL;  JSAMPROW *tmpbuf[MAX_COMPONENTS];
+	int jpegwidth, jpegheight, scaledw, scaledh;
 
-	checkhandle(h);
+	checkhandle(hnd);
 
 	for(i=0; i<MAX_COMPONENTS; i++)
 	{
@@ -475,14 +518,12 @@
 	}
 
 	if(srcbuf==NULL || size<=0
-		|| dstbuf==NULL || width<=0 || pitch<0 || height<=0)
+		|| dstbuf==NULL || width<0 || pitch<0 || height<0)
 		_throw("Invalid argument in tjDecompress()");
 	if(ps!=3 && ps!=4 && ps!=1)
 		_throw("This decompressor can only handle 24-bit and 32-bit RGB or 8-bit grayscale output");
 	if(!j->initd) _throw("Instance has not been initialized for decompression");
 
-	if(pitch==0) pitch=width*ps;
-
 	if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
 	else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
 	else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
@@ -541,16 +582,6 @@
 			}
 		}
 	}
-	else
-	{
-		if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)*height))==NULL)
-			_throw("Memory allocation failed in tjDecompress()");
-		for(i=0; i<height; i++)
-		{
-			if(flags&TJ_BOTTOMUP) row_pointer[i]= &dstbuf[(height-i-1)*pitch];
-			else row_pointer[i]= &dstbuf[i*pitch];
-		}
-	}
 
 	if(ps==1) j->dinfo.out_color_space = JCS_GRAYSCALE;
 	#if JCS_EXTENSIONS==1
@@ -571,12 +602,30 @@
 
 	if(flags&TJ_FASTUPSAMPLE) j->dinfo.do_fancy_upsampling=FALSE;
 	if(flags&TJ_YUV) j->dinfo.raw_data_out=TRUE;
+	else
+	{
+		jpegwidth=j->dinfo.image_width;  jpegheight=j->dinfo.image_height;
+		if(width==0) width=jpegwidth;
+		if(height==0) height=jpegheight;
+		for(i=0; i<NUMSF; i++)
+		{
+			scaledw=(jpegwidth*sf[i].num+sf[i].denom-1)/sf[i].denom;
+			scaledh=(jpegheight*sf[i].num+sf[i].denom-1)/sf[i].denom;
+			if(scaledw<=width && scaledh<=height)
+					break;
+		}
+		if(scaledw>width || scaledh>height)
+			_throw("Could not scale down to desired image dimensions");
+		width=scaledw;  height=scaledh;
+		j->dinfo.scale_num=sf[i].num;
+		j->dinfo.scale_denom=sf[i].denom;
+	}
 
 	jpeg_start_decompress(&j->dinfo);
 	if(flags&TJ_YUV)
 	{
 		j_decompress_ptr dinfo=&j->dinfo;
-		for(row=0; row<dinfo->output_height;
+		for(row=0; row<(int)dinfo->output_height;
 			row+=dinfo->max_v_samp_factor*DCTSIZE)
 		{
 			JSAMPARRAY yuvptr[MAX_COMPONENTS];
@@ -604,6 +653,16 @@
 	}
 	else
 	{
+		if(pitch==0) pitch=j->dinfo.output_width*ps;
+		if((row_pointer=(JSAMPROW *)malloc(sizeof(JSAMPROW)
+			*j->dinfo.output_height))==NULL)
+			_throw("Memory allocation failed in tjInitDecompress()");
+		for(i=0; i<(int)j->dinfo.output_height; i++)
+		{
+			if(flags&TJ_BOTTOMUP)
+				row_pointer[i]= &dstbuf[(j->dinfo.output_height-i-1)*pitch];
+			else row_pointer[i]= &dstbuf[i*pitch];
+		}
 		while(j->dinfo.output_scanline<j->dinfo.output_height)
 		{
 			jpeg_read_scanlines(&j->dinfo, &row_pointer[j->dinfo.output_scanline],
@@ -625,11 +684,150 @@
 }
 
 
-DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle h,
+DLLEXPORT int DLLCALL tjDecompressToYUV(tjhandle hnd,
 	unsigned char *srcbuf, unsigned long size,
 	unsigned char *dstbuf, int flags)
 {
-	return tjDecompress(h, srcbuf, size, dstbuf, 1, 0, 1, 3, flags|TJ_YUV);
+	return tjDecompress(hnd, srcbuf, size, dstbuf, 1, 0, 1, 3, flags|TJ_YUV);
+}
+
+
+// Transformation
+
+DLLEXPORT tjhandle DLLCALL tjInitTransform(void)
+{
+	jpgstruct *j=NULL;  tjhandle tj=NULL;
+	if((j=(jpgstruct *)malloc(sizeof(jpgstruct)))==NULL)
+	{
+		snprintf(lasterror, JMSG_LENGTH_MAX, "Memory allocation failure");
+		return NULL;
+	}
+	memset(j, 0, sizeof(jpgstruct));
+	tj=_tjInitCompress(j);
+	if(!tj) return NULL;
+	tj=_tjInitDecompress(j);
+	return tj;
+}
+
+
+DLLEXPORT int DLLCALL tjTransform(tjhandle hnd,
+	unsigned char *srcbuf, unsigned long srcsize,
+	int n, unsigned char **dstbufs, unsigned long *dstsizes,
+	tjtransform *t, int flags)
+{
+	jpeg_transform_info *xinfo=NULL;
+	jvirt_barray_ptr *srccoefs, *dstcoefs;
+	int retval=0, i;
+
+	checkhandle(hnd);
+
+	if(srcbuf==NULL || srcsize<=0 || n<1 || dstbufs==NULL || dstsizes==NULL
+		|| t==NULL || flags<0)
+		_throw("Invalid argument in tjTransform()");
+	if(!j->initc || !j->initd)
+		_throw("Instance has not been initialized for transformation");
+
+	if(flags&TJ_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
+	else if(flags&TJ_FORCESSE) putenv("JSIMD_FORCESSE=1");
+	else if(flags&TJ_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
+
+	if(setjmp(j->jerr.jb))
+	{  // this will execute if LIBJPEG has an error
+		retval=-1;
+		goto bailout;
+	}
+
+	j->jsms.bytes_in_buffer=srcsize;
+	j->jsms.next_input_byte=srcbuf;
+
+	if((xinfo=(jpeg_transform_info *)malloc(sizeof(jpeg_transform_info)*n))
+		==NULL)
+		_throw("Memory allocation failed in tjTransform()");
+	memset(xinfo, 0, sizeof(jpeg_transform_info)*n);
+
+	for(i=0; i<n; i++)
+	{
+		xinfo[i].transform=xformtypes[t[i].op];
+		xinfo[i].perfect=(t[i].options&TJXFORM_PERFECT)? 1:0;
+		xinfo[i].trim=(t[i].options&TJXFORM_TRIM)? 1:0;
+		xinfo[i].force_grayscale=(t[i].options&TJXFORM_GRAY)? 1:0;
+		xinfo[i].crop=(t[i].options&TJXFORM_CROP)? 1:0;
+		if(n!=1 && t[i].op==TJXFORM_HFLIP) xinfo[i].slow_hflip=1;
+		else xinfo[i].slow_hflip=0;
+
+		if(xinfo[i].crop)
+		{
+			xinfo[i].crop_xoffset=t[i].r.x;  xinfo[i].crop_xoffset_set=JCROP_POS;
+			xinfo[i].crop_yoffset=t[i].r.y;  xinfo[i].crop_yoffset_set=JCROP_POS;
+			if(t[i].r.w!=0)
+			{
+				xinfo[i].crop_width=t[i].r.w;  xinfo[i].crop_width_set=JCROP_POS;
+			}
+			else xinfo[i].crop_width=JCROP_UNSET;
+			if(t[i].r.h!=0)
+			{
+				xinfo[i].crop_height=t[i].r.h;  xinfo[i].crop_height_set=JCROP_POS;
+			}
+			else xinfo[i].crop_height=JCROP_UNSET;
+		}
+	}
+
+	jcopy_markers_setup(&j->dinfo, JCOPYOPT_ALL);
+	jpeg_read_header(&j->dinfo, TRUE);
+
+	for(i=0; i<n; i++)
+	{
+		if(!jtransform_request_workspace(&j->dinfo, &xinfo[i]))
+			_throw("Transform is not perfect");
+
+		if(xinfo[i].crop)
+		{
+			if((t[i].r.x%xinfo[i].iMCU_sample_width)!=0
+				|| (t[i].r.y%xinfo[i].iMCU_sample_height)!=0)
+			{
+				snprintf(lasterror, JMSG_LENGTH_MAX,
+					"To crop this JPEG image, x must be a multiple of %d\n"
+					"and y must be a multiple of %d.\n",
+					xinfo[i].iMCU_sample_width, xinfo[i].iMCU_sample_height);
+				retval=-1;  goto bailout;
+			}
+		}
+	}
+
+	srccoefs=jpeg_read_coefficients(&j->dinfo);
+
+	for(i=0; i<n; i++)
+	{
+		int w, h;
+		j->jdms.next_output_byte=dstbufs[i];
+		if(!xinfo[i].crop)
+		{
+			w=j->dinfo.image_width;  h=j->dinfo.image_height;
+		}
+		else
+		{
+			w=xinfo[i].crop_width;  h=xinfo[i].crop_height;
+		}
+		j->jdms.free_in_buffer=TJBUFSIZE(w, h);
+		jpeg_copy_critical_parameters(&j->dinfo, &j->cinfo);
+		dstcoefs=jtransform_adjust_parameters(&j->dinfo, &j->cinfo, srccoefs,
+			&xinfo[i]);
+		jpeg_write_coefficients(&j->cinfo, dstcoefs);
+		jcopy_markers_execute(&j->dinfo, &j->cinfo, JCOPYOPT_ALL);
+		jtransform_execute_transformation(&j->dinfo, &j->cinfo, srccoefs,
+			&xinfo[i]);
+		jpeg_finish_compress(&j->cinfo);
+
+		dstsizes[i]=TJBUFSIZE(w, h)-(unsigned long)(j->jdms.free_in_buffer);
+	}
+
+	jpeg_finish_decompress(&j->dinfo);
+
+	bailout:
+	if(j->cinfo.global_state>CSTATE_START) jpeg_abort_compress(&j->cinfo);
+	if(j->dinfo.global_state>DSTATE_START) jpeg_abort_decompress(&j->dinfo);
+	if(xinfo) free(xinfo);
+	return retval;
 }
 
 
@@ -640,9 +838,9 @@
 	return lasterror;
 }
 
-DLLEXPORT int DLLCALL tjDestroy(tjhandle h)
+DLLEXPORT int DLLCALL tjDestroy(tjhandle hnd)
 {
-	checkhandle(h);
+	checkhandle(hnd);
 	if(setjmp(j->jerr.jb)) return -1;
 	if(j->initc) jpeg_destroy_compress(&j->cinfo);
 	if(j->initd) jpeg_destroy_decompress(&j->dinfo);