---
 codecs/jpegcomp.h |  30 +++++++
 codecs/jpegint.h  |   9 +++
 codecs/transupp.c | 233 ++++++++++++++++++++++++++++++++++++++----------------
 codecs/transupp.h |  41 +++++++---
 4 files changed, 231 insertions(+), 82 deletions(-)
 create mode 100644 codecs/jpegcomp.h

diff --git a/codecs/jpegcomp.h b/codecs/jpegcomp.h
new file mode 100644
index 0000000..ed9eeab
--- /dev/null
+++ b/codecs/jpegcomp.h
@@ -0,0 +1,30 @@
+/*
+ * jpegcomp.h
+ *
+ * Copyright (C) 2010, D. R. Commander
+ * For conditions of distribution and use, see the accompanying README file.
+ *
+ * JPEG compatibility macros
+ * These declarations are considered internal to the JPEG library; most
+ * applications using the library shouldn't need to include this file.
+ */
+
+#if JPEG_LIB_VERSION >= 70
+#define _DCT_scaled_size DCT_h_scaled_size
+#define _DCT_h_scaled_size DCT_h_scaled_size
+#define _DCT_v_scaled_size DCT_v_scaled_size
+#define _min_DCT_scaled_size min_DCT_h_scaled_size
+#define _min_DCT_h_scaled_size min_DCT_h_scaled_size
+#define _min_DCT_v_scaled_size min_DCT_v_scaled_size
+#define _jpeg_width jpeg_width
+#define _jpeg_height jpeg_height
+#else
+#define _DCT_scaled_size DCT_scaled_size
+#define _DCT_h_scaled_size DCT_scaled_size
+#define _DCT_v_scaled_size DCT_scaled_size
+#define _min_DCT_scaled_size min_DCT_scaled_size
+#define _min_DCT_h_scaled_size min_DCT_scaled_size
+#define _min_DCT_v_scaled_size min_DCT_scaled_size
+#define _jpeg_width image_width
+#define _jpeg_height image_height
+#endif
diff --git a/codecs/jpegint.h b/codecs/jpegint.h
index 95b00d4..7871748 100644
--- a/codecs/jpegint.h
+++ b/codecs/jpegint.h
@@ -2,6 +2,7 @@
  * jpegint.h
  *
  * Copyright (C) 1991-1997, Thomas G. Lane.
+ * Modified 1997-2009 by Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -304,6 +305,7 @@ struct jpeg_color_quantizer {
 #define jinit_forward_dct      jIFDCT
 #define jinit_huff_encoder     jIHEncoder
 #define jinit_phuff_encoder    jIPHEncoder
+#define jinit_arith_encoder    jIAEncoder
 #define jinit_marker_writer    jIMWriter
 #define jinit_master_decompress        jIDMaster
 #define jinit_d_main_controller        jIDMainC
@@ -313,6 +315,7 @@ struct jpeg_color_quantizer {
 #define jinit_marker_reader    jIMReader
 #define jinit_huff_decoder     jIHDecoder
 #define jinit_phuff_decoder    jIPHDecoder
+#define jinit_arith_decoder    jIADecoder
 #define jinit_inverse_dct      jIIDCT
 #define jinit_upsampler                jIUpsampler
 #define jinit_color_deconverter        jIDColor
@@ -327,6 +330,7 @@ struct jpeg_color_quantizer {
 #define jzero_far              jZeroFar
 #define jpeg_zigzag_order      jZIGTable
 #define jpeg_natural_order     jZAGTable
+#define jpeg_aritab            jAriTab
 #endif /* NEED_SHORT_EXTERNAL_NAMES */
 
 
@@ -345,6 +349,7 @@ EXTERN(void) jinit_downsampler JPP((j_compress_ptr cinfo));
 EXTERN(void) jinit_forward_dct JPP((j_compress_ptr cinfo));
 EXTERN(void) jinit_huff_encoder JPP((j_compress_ptr cinfo));
 EXTERN(void) jinit_phuff_encoder JPP((j_compress_ptr cinfo));
+EXTERN(void) jinit_arith_encoder JPP((j_compress_ptr cinfo));
 EXTERN(void) jinit_marker_writer JPP((j_compress_ptr cinfo));
 /* Decompression module initialization routines */
 EXTERN(void) jinit_master_decompress JPP((j_decompress_ptr cinfo));
@@ -358,6 +363,7 @@ EXTERN(void) jinit_input_controller JPP((j_decompress_ptr 
cinfo));
 EXTERN(void) jinit_marker_reader JPP((j_decompress_ptr cinfo));
 EXTERN(void) jinit_huff_decoder JPP((j_decompress_ptr cinfo));
 EXTERN(void) jinit_phuff_decoder JPP((j_decompress_ptr cinfo));
+EXTERN(void) jinit_arith_decoder JPP((j_decompress_ptr cinfo));
 EXTERN(void) jinit_inverse_dct JPP((j_decompress_ptr cinfo));
 EXTERN(void) jinit_upsampler JPP((j_decompress_ptr cinfo));
 EXTERN(void) jinit_color_deconverter JPP((j_decompress_ptr cinfo));
@@ -382,6 +388,9 @@ extern const int jpeg_zigzag_order[]; /* natural coef order 
to zigzag order */
 #endif
 extern const int jpeg_natural_order[]; /* zigzag coef order to natural order */
 
+/* Arithmetic coding probability estimation tables in jaricom.c */
+extern const INT32 jpeg_aritab[];
+
 /* Suppress undefined-structure complaints if necessary. */
 
 #ifdef INCOMPLETE_TYPES_BROKEN
diff --git a/codecs/transupp.c b/codecs/transupp.c
index e6bb936..9e80583 100644
--- a/codecs/transupp.c
+++ b/codecs/transupp.c
@@ -1,8 +1,10 @@
 /*
  * transupp.c
  *
- * Copyright (C) 1997-2001, Thomas G. Lane.
- * This file is part of the Independent JPEG Group's software.
+ * This file was part of the Independent JPEG Group's software:
+ * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
+ * Modifications:
+ * Copyright (C) 2010, D. R. Commander.
  * For conditions of distribution and use, see the accompanying README file.
  *
  * This file contains image transformation routines and other utility code
@@ -20,9 +22,19 @@
 #include "jinclude.h"
 #include "jpeglib.h"
 #include "transupp.h"          /* My own external interface */
+#include "jpegcomp.h"
 #include <ctype.h>             /* to declare isdigit() */
 
 
+#if JPEG_LIB_VERSION >= 70
+#define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
+#define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
+#else
+#define dstinfo_min_DCT_h_scaled_size DCTSIZE
+#define dstinfo_min_DCT_v_scaled_size DCTSIZE
+#endif
+
+
 #if TRANSFORMS_SUPPORTED
 
 /*
@@ -133,7 +145,8 @@ do_flip_h_no_crop (j_decompress_ptr srcinfo, j_compress_ptr 
dstinfo,
    * mirroring by changing the signs of odd-numbered columns.
    * Partial iMCUs at the right edge are left untouched.
    */
-  MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+  MCU_cols = srcinfo->output_width /
+    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -198,7 +211,8 @@ do_flip_h (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
    * different rows of a single virtual array simultaneously.  Otherwise,
    * this is essentially the same as the routine above.
    */
-  MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+  MCU_cols = srcinfo->output_width /
+    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -262,7 +276,8 @@ do_flip_v (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
    * of odd-numbered rows.
    * Partial iMCUs at the bottom edge are copied verbatim.
    */
-  MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+  MCU_rows = srcinfo->output_height /
+    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -389,7 +404,8 @@ do_rot_90 (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
    * at the (output) right edge properly.  They just get transposed and
    * not mirrored.
    */
-  MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
+  MCU_cols = srcinfo->output_height /
+    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -469,7 +485,8 @@ do_rot_270 (j_decompress_ptr srcinfo, j_compress_ptr 
dstinfo,
    * at the (output) bottom edge properly.  They just get transposed and
    * not mirrored.
    */
-  MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
+  MCU_rows = srcinfo->output_width /
+    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -536,8 +553,10 @@ do_rot_180 (j_decompress_ptr srcinfo, j_compress_ptr 
dstinfo,
   JCOEFPTR src_ptr, dst_ptr;
   jpeg_component_info *compptr;
 
-  MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
-  MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+  MCU_cols = srcinfo->output_width /
+    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
+  MCU_rows = srcinfo->output_height /
+    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -645,8 +664,10 @@ do_transverse (j_decompress_ptr srcinfo, j_compress_ptr 
dstinfo,
   JCOEFPTR src_ptr, dst_ptr;
   jpeg_component_info *compptr;
 
-  MCU_cols = srcinfo->image_height / (dstinfo->max_h_samp_factor * DCTSIZE);
-  MCU_rows = srcinfo->image_width / (dstinfo->max_v_samp_factor * DCTSIZE);
+  MCU_cols = srcinfo->output_height /
+    (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
+  MCU_rows = srcinfo->output_width /
+    (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
 
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -762,7 +783,7 @@ jt_read_integer (const char ** strptr, JDIMENSION * result)
  * The routine returns TRUE if the spec string is valid, FALSE if not.
  *
  * The crop spec string should have the format
- *     <width>x<height>{+-}<xoffset>{+-}<yoffset>
+ *     <width>[f]x<height>[f]{+-}<xoffset>{+-}<yoffset>
  * where width, height, xoffset, and yoffset are unsigned integers.
  * Each of the elements can be omitted to indicate a default value.
  * (A weakness of this style is that it is not possible to omit xoffset
@@ -784,14 +805,22 @@ jtransform_parse_crop_spec (jpeg_transform_info *info, 
const char *spec)
     /* fetch width */
     if (! jt_read_integer(&spec, &info->crop_width))
       return FALSE;
-    info->crop_width_set = JCROP_POS;
+    if (*spec == 'f' || *spec == 'F') {
+      spec++;
+      info->crop_width_set = JCROP_FORCE;
+    } else
+      info->crop_width_set = JCROP_POS;
   }
-  if (*spec == 'x' || *spec == 'X') {  
+  if (*spec == 'x' || *spec == 'X') {
     /* fetch height */
     spec++;
     if (! jt_read_integer(&spec, &info->crop_height))
       return FALSE;
-    info->crop_height_set = JCROP_POS;
+    if (*spec == 'f' || *spec == 'F') {
+      spec++;
+      info->crop_height_set = JCROP_FORCE;
+    } else
+      info->crop_height_set = JCROP_POS;
   }
   if (*spec == '+' || *spec == '-') {
     /* fetch xoffset */
@@ -822,10 +851,10 @@ trim_right_edge (jpeg_transform_info *info, JDIMENSION 
full_width)
 {
   JDIMENSION MCU_cols;
 
-  MCU_cols = info->output_width / (info->max_h_samp_factor * DCTSIZE);
+  MCU_cols = info->output_width / info->iMCU_sample_width;
   if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
-      full_width / (info->max_h_samp_factor * DCTSIZE))
-    info->output_width = MCU_cols * (info->max_h_samp_factor * DCTSIZE);
+      full_width / info->iMCU_sample_width)
+    info->output_width = MCU_cols * info->iMCU_sample_width;
 }
 
 LOCAL(void)
@@ -833,10 +862,10 @@ trim_bottom_edge (jpeg_transform_info *info, JDIMENSION 
full_height)
 {
   JDIMENSION MCU_rows;
 
-  MCU_rows = info->output_height / (info->max_v_samp_factor * DCTSIZE);
+  MCU_rows = info->output_height / info->iMCU_sample_height;
   if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
-      full_height / (info->max_v_samp_factor * DCTSIZE))
-    info->output_height = MCU_rows * (info->max_v_samp_factor * DCTSIZE);
+      full_height / info->iMCU_sample_height)
+    info->output_height = MCU_rows * info->iMCU_sample_height;
 }
 
 
@@ -852,59 +881,94 @@ trim_bottom_edge (jpeg_transform_info *info, JDIMENSION 
full_height)
  * Hence, this routine must be called after jpeg_read_header (which reads
  * the image dimensions) and before jpeg_read_coefficients (which realizes
  * the source's virtual arrays).
+ *
+ * This function returns FALSE right away if -perfect is given
+ * and transformation is not perfect.  Otherwise returns TRUE.
  */
 
-GLOBAL(void)
+GLOBAL(boolean)
 jtransform_request_workspace (j_decompress_ptr srcinfo,
                              jpeg_transform_info *info)
 {
-  jvirt_barray_ptr *coef_arrays = NULL;
+  jvirt_barray_ptr *coef_arrays;
   boolean need_workspace, transpose_it;
   jpeg_component_info *compptr;
-  JDIMENSION xoffset, yoffset, width_in_iMCUs, height_in_iMCUs;
+  JDIMENSION xoffset, yoffset;
+  JDIMENSION width_in_iMCUs, height_in_iMCUs;
   JDIMENSION width_in_blocks, height_in_blocks;
   int ci, h_samp_factor, v_samp_factor;
 
   /* Determine number of components in output image */
   if (info->force_grayscale &&
       srcinfo->jpeg_color_space == JCS_YCbCr &&
-      srcinfo->num_components == 3) {
+      srcinfo->num_components == 3)
     /* We'll only process the first component */
     info->num_components = 1;
-  } else {
+  else
     /* Process all the components */
     info->num_components = srcinfo->num_components;
+
+  /* Compute output image dimensions and related values. */
+#if JPEG_LIB_VERSION >= 80
+  jpeg_core_output_dimensions(srcinfo);
+#else
+  srcinfo->output_width = srcinfo->image_width;
+  srcinfo->output_height = srcinfo->image_height;
+#endif
+
+  /* Return right away if -perfect is given and transformation is not perfect.
+   */
+  if (info->perfect) {
+    if (info->num_components == 1) {
+      if (!jtransform_perfect_transform(srcinfo->output_width,
+         srcinfo->output_height,
+         srcinfo->_min_DCT_h_scaled_size,
+         srcinfo->_min_DCT_v_scaled_size,
+         info->transform))
+       return FALSE;
+    } else {
+      if (!jtransform_perfect_transform(srcinfo->output_width,
+         srcinfo->output_height,
+         srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
+         srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
+         info->transform))
+       return FALSE;
+    }
   }
+
   /* If there is only one output component, force the iMCU size to be 1;
    * else use the source iMCU size.  (This allows us to do the right thing
    * when reducing color to grayscale, and also provides a handy way of
    * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
    */
-
   switch (info->transform) {
   case JXFORM_TRANSPOSE:
   case JXFORM_TRANSVERSE:
   case JXFORM_ROT_90:
   case JXFORM_ROT_270:
-    info->output_width = srcinfo->image_height;
-    info->output_height = srcinfo->image_width;
+    info->output_width = srcinfo->output_height;
+    info->output_height = srcinfo->output_width;
     if (info->num_components == 1) {
-      info->max_h_samp_factor = 1;
-      info->max_v_samp_factor = 1;
+      info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
+      info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
     } else {
-      info->max_h_samp_factor = srcinfo->max_v_samp_factor;
-      info->max_v_samp_factor = srcinfo->max_h_samp_factor;
+      info->iMCU_sample_width =
+       srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
+      info->iMCU_sample_height =
+       srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
     }
     break;
   default:
-    info->output_width = srcinfo->image_width;
-    info->output_height = srcinfo->image_height;
+    info->output_width = srcinfo->output_width;
+    info->output_height = srcinfo->output_height;
     if (info->num_components == 1) {
-      info->max_h_samp_factor = 1;
-      info->max_v_samp_factor = 1;
+      info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
+      info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
     } else {
-      info->max_h_samp_factor = srcinfo->max_h_samp_factor;
-      info->max_v_samp_factor = srcinfo->max_v_samp_factor;
+      info->iMCU_sample_width =
+       srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
+      info->iMCU_sample_height =
+       srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
     }
     break;
   }
@@ -920,7 +984,7 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
       info->crop_yoffset = 0;  /* default to +0 */
     if (info->crop_xoffset >= info->output_width ||
        info->crop_yoffset >= info->output_height)
-      ERREXIT(srcinfo, "Invalid crop request"); /* was: JERR_BAD_CROP_SPEC */
+      ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
     if (info->crop_width_set == JCROP_UNSET)
       info->crop_width = info->output_width - info->crop_xoffset;
     if (info->crop_height_set == JCROP_UNSET)
@@ -930,7 +994,7 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
        info->crop_height <= 0 || info->crop_height > info->output_height ||
        info->crop_xoffset > info->output_width - info->crop_width ||
        info->crop_yoffset > info->output_height - info->crop_height)
-      ERREXIT(srcinfo, "Invalid crop request"); /* was: JERR_BAD_CROP_SPEC */
+      ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
     /* Convert negative crop offsets into regular offsets */
     if (info->crop_xoffset_set == JCROP_NEG)
       xoffset = info->output_width - info->crop_width - info->crop_xoffset;
@@ -941,13 +1005,19 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
     else
       yoffset = info->crop_yoffset;
     /* Now adjust so that upper left corner falls at an iMCU boundary */
-    info->output_width =
-      info->crop_width + (xoffset % (info->max_h_samp_factor * DCTSIZE));
-    info->output_height =
-      info->crop_height + (yoffset % (info->max_v_samp_factor * DCTSIZE));
+    if (info->crop_width_set == JCROP_FORCE)
+      info->output_width = info->crop_width;
+    else
+      info->output_width =
+        info->crop_width + (xoffset % info->iMCU_sample_width);
+    if (info->crop_height_set == JCROP_FORCE)
+      info->output_height = info->crop_height;
+    else
+      info->output_height =
+        info->crop_height + (yoffset % info->iMCU_sample_height);
     /* Save x/y offsets measured in iMCUs */
-    info->x_crop_offset = xoffset / (info->max_h_samp_factor * DCTSIZE);
-    info->y_crop_offset = yoffset / (info->max_v_samp_factor * DCTSIZE);
+    info->x_crop_offset = xoffset / info->iMCU_sample_width;
+    info->y_crop_offset = yoffset / info->iMCU_sample_height;
   } else {
     info->x_crop_offset = 0;
     info->y_crop_offset = 0;
@@ -966,14 +1036,14 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
     break;
   case JXFORM_FLIP_H:
     if (info->trim)
-      trim_right_edge(info, srcinfo->image_width);
-    if (info->y_crop_offset != 0)
+      trim_right_edge(info, srcinfo->output_width);
+    if (info->y_crop_offset != 0 || info->slow_hflip)
       need_workspace = TRUE;
     /* do_flip_h_no_crop doesn't need a workspace array */
     break;
   case JXFORM_FLIP_V:
     if (info->trim)
-      trim_bottom_edge(info, srcinfo->image_height);
+      trim_bottom_edge(info, srcinfo->output_height);
     /* Need workspace arrays having same dimensions as source image. */
     need_workspace = TRUE;
     break;
@@ -985,8 +1055,8 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
     break;
   case JXFORM_TRANSVERSE:
     if (info->trim) {
-      trim_right_edge(info, srcinfo->image_height);
-      trim_bottom_edge(info, srcinfo->image_width);
+      trim_right_edge(info, srcinfo->output_height);
+      trim_bottom_edge(info, srcinfo->output_width);
     }
     /* Need workspace arrays having transposed dimensions. */
     need_workspace = TRUE;
@@ -994,22 +1064,22 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
     break;
   case JXFORM_ROT_90:
     if (info->trim)
-      trim_right_edge(info, srcinfo->image_height);
+      trim_right_edge(info, srcinfo->output_height);
     /* Need workspace arrays having transposed dimensions. */
     need_workspace = TRUE;
     transpose_it = TRUE;
     break;
   case JXFORM_ROT_180:
     if (info->trim) {
-      trim_right_edge(info, srcinfo->image_width);
-      trim_bottom_edge(info, srcinfo->image_height);
+      trim_right_edge(info, srcinfo->output_width);
+      trim_bottom_edge(info, srcinfo->output_height);
     }
     /* Need workspace arrays having same dimensions as source image. */
     need_workspace = TRUE;
     break;
   case JXFORM_ROT_270:
     if (info->trim)
-      trim_bottom_edge(info, srcinfo->image_width);
+      trim_bottom_edge(info, srcinfo->output_width);
     /* Need workspace arrays having transposed dimensions. */
     need_workspace = TRUE;
     transpose_it = TRUE;
@@ -1026,10 +1096,10 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
                SIZEOF(jvirt_barray_ptr) * info->num_components);
     width_in_iMCUs = (JDIMENSION)
       jdiv_round_up((long) info->output_width,
-                   (long) (info->max_h_samp_factor * DCTSIZE));
+                   (long) info->iMCU_sample_width);
     height_in_iMCUs = (JDIMENSION)
       jdiv_round_up((long) info->output_height,
-                   (long) (info->max_v_samp_factor * DCTSIZE));
+                   (long) info->iMCU_sample_height);
     for (ci = 0; ci < info->num_components; ci++) {
       compptr = srcinfo->comp_info + ci;
       if (info->num_components == 1) {
@@ -1048,9 +1118,11 @@ jtransform_request_workspace (j_decompress_ptr srcinfo,
        ((j_common_ptr) srcinfo, JPOOL_IMAGE, FALSE,
         width_in_blocks, height_in_blocks, (JDIMENSION) v_samp_factor);
     }
-  }
+    info->workspace_coef_arrays = coef_arrays;
+  } else
+    info->workspace_coef_arrays = NULL;
 
-  info->workspace_coef_arrays = coef_arrays;
+  return TRUE;
 }
 
 
@@ -1062,8 +1134,19 @@ transpose_critical_parameters (j_compress_ptr dstinfo)
   int tblno, i, j, ci, itemp;
   jpeg_component_info *compptr;
   JQUANT_TBL *qtblptr;
+  JDIMENSION jtemp;
   UINT16 qtemp;
 
+  /* Transpose image dimensions */
+  jtemp = dstinfo->image_width;
+  dstinfo->image_width = dstinfo->image_height;
+  dstinfo->image_height = jtemp;
+#if JPEG_LIB_VERSION >= 70
+  itemp = dstinfo->min_DCT_h_scaled_size;
+  dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
+  dstinfo->min_DCT_v_scaled_size = itemp;
+#endif
+
   /* Transpose sampling factors */
   for (ci = 0; ci < dstinfo->num_components; ci++) {
     compptr = dstinfo->comp_info + ci;
@@ -1296,10 +1379,12 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo,
   }
 
   /* Correct the destination's image dimensions as necessary
-   * for crop and rotate/flip operations.
+   * for rotate/flip, resize, and crop operations.
    */
-  dstinfo->image_width = info->output_width;
-  dstinfo->image_height = info->output_height;
+#if JPEG_LIB_VERSION >= 70
+  dstinfo->jpeg_width = info->output_width;
+  dstinfo->jpeg_height = info->output_height;
+#endif
 
   /* Transpose destination image parameters */
   switch (info->transform) {
@@ -1307,9 +1392,17 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo,
   case JXFORM_TRANSVERSE:
   case JXFORM_ROT_90:
   case JXFORM_ROT_270:
+#if JPEG_LIB_VERSION < 70
+    dstinfo->image_width = info->output_height;
+    dstinfo->image_height = info->output_width;
+#endif
     transpose_critical_parameters(dstinfo);
     break;
   default:
+#if JPEG_LIB_VERSION < 70
+    dstinfo->image_width = info->output_width;
+    dstinfo->image_height = info->output_height;
+#endif
     break;
   }
 
@@ -1325,13 +1418,15 @@ jtransform_adjust_parameters (j_decompress_ptr srcinfo,
       GETJOCTET(srcinfo->marker_list->data[5]) == 0) {
     /* Suppress output of JFIF marker */
     dstinfo->write_JFIF_header = FALSE;
+#if JPEG_LIB_VERSION >= 70
     /* Adjust Exif image parameters */
-    if (dstinfo->image_width != srcinfo->image_width ||
-       dstinfo->image_height != srcinfo->image_height)
+    if (dstinfo->jpeg_width != srcinfo->image_width ||
+       dstinfo->jpeg_height != srcinfo->image_height)
       /* Align data segment to start of TIFF structure for parsing */
       adjust_exif_parameters(srcinfo->marker_list->data + 6,
        srcinfo->marker_list->data_length - 6,
-       dstinfo->image_width, dstinfo->image_height);
+       dstinfo->jpeg_width, dstinfo->jpeg_height);
+#endif
   }
 
   /* Return the appropriate output data set */
@@ -1368,7 +1463,7 @@ jtransform_execute_transform (j_decompress_ptr srcinfo,
              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
@@ -1415,8 +1510,8 @@ jtransform_execute_transform (j_decompress_ptr srcinfo,
  * (after reading source header):
  *   image_width = cinfo.image_width
  *   image_height = cinfo.image_height
- *   MCU_width = cinfo.max_h_samp_factor * DCTSIZE
- *   MCU_height = cinfo.max_v_samp_factor * DCTSIZE
+ *   MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
+ *   MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
  * Result:
  *   TRUE = perfect transformation possible
  *   FALSE = perfect transformation not possible
diff --git a/codecs/transupp.h b/codecs/transupp.h
index 981b1ce..cfbaca4 100644
--- a/codecs/transupp.h
+++ b/codecs/transupp.h
@@ -1,7 +1,7 @@
 /*
  * transupp.h
  *
- * Copyright (C) 1997-2001, Thomas G. Lane.
+ * Copyright (C) 1997-2011, Thomas G. Lane, Guido Vollbeding.
  * This file is part of the Independent JPEG Group's software.
  * For conditions of distribution and use, see the accompanying README file.
  *
@@ -57,10 +57,16 @@
  * corner up and/or left to make it so, simultaneously increasing the region
  * dimensions to keep the lower right crop corner unchanged.  (Thus, the
  * output image covers at least the requested region, but may cover more.)
+ * The adjustment of the region dimensions may be optionally disabled.
  *
- * If both crop and a rotate/flip transform are requested, the crop is applied
- * last --- that is, the crop region is specified in terms of the destination
- * image.
+ * We also provide a lossless-resize option, which is kind of a lossless-crop
+ * operation in the DCT coefficient block domain - it discards higher-order
+ * coefficients and losslessly preserves lower-order coefficients of a
+ * sub-block.
+ *
+ * Rotate/flip transform, resize, and crop can be requested together in a
+ * single invocation.  The crop is applied last --- that is, the crop region
+ * is specified in terms of the destination image after transform/resize.
  *
  * We also offer a "force to grayscale" option, which simply discards the
  * chrominance channels of a YCbCr image.  This is lossless in the sense that
@@ -101,13 +107,15 @@ typedef enum {
 
 /*
  * Codes for crop parameters, which can individually be unspecified,
- * positive, or negative.  (Negative width or height makes no sense, though.)
+ * positive or negative for xoffset or yoffset,
+ * positive or forced for width or height.
  */
 
 typedef enum {
-       JCROP_UNSET,
-       JCROP_POS,
-       JCROP_NEG
+        JCROP_UNSET,
+        JCROP_POS,
+        JCROP_NEG,
+        JCROP_FORCE
 } JCROP_CODE;
 
 /*
@@ -123,14 +131,21 @@ typedef struct {
   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().
    */
   JDIMENSION crop_width;       /* Width of selected region */
-  JCROP_CODE crop_width_set;
+  JCROP_CODE crop_width_set;   /* (forced disables adjustment) */
   JDIMENSION crop_height;      /* Height of selected region */
-  JCROP_CODE crop_height_set;
+  JCROP_CODE crop_height_set;  /* (forced disables adjustment) */
   JDIMENSION crop_xoffset;     /* X offset of selected region */
   JCROP_CODE crop_xoffset_set; /* (negative measures from right edge) */
   JDIMENSION crop_yoffset;     /* Y offset of selected region */
@@ -143,8 +158,8 @@ typedef struct {
   JDIMENSION output_height;
   JDIMENSION x_crop_offset;    /* destination crop offsets measured in iMCUs */
   JDIMENSION y_crop_offset;
-  int max_h_samp_factor;       /* destination iMCU size */
-  int max_v_samp_factor;
+  int iMCU_sample_width;       /* destination iMCU size */
+  int iMCU_sample_height;
 } jpeg_transform_info;
 
 
@@ -154,7 +169,7 @@ typedef struct {
 EXTERN(boolean) jtransform_parse_crop_spec
        JPP((jpeg_transform_info *info, const char *spec));
 /* Request any required workspace */
-EXTERN(void) jtransform_request_workspace
+EXTERN(boolean) jtransform_request_workspace
        JPP((j_decompress_ptr srcinfo, jpeg_transform_info *info));
 /* Adjust output image parameters */
 EXTERN(jvirt_barray_ptr *) jtransform_adjust_parameters
-- 
2.1.4

----------------------------------------------------------- 
If you wish to unsubscribe from this mailing, send mail to
[email protected] with a subject of: unsubscribe exact-image

Reply via email to