diff -c jpeg-6b/jpegtran.c jpeg-new/jpegtran.c
*** jpeg-6b/jpegtran.c	Wed Jul 23 20:37:26 1997
--- jpeg-new/jpegtran.c	Tue Jan 18 22:56:46 2000
***************
*** 69,74 ****
--- 69,75 ----
    fprintf(stderr, "  -rotate [90|180|270]         Rotate image (degrees clockwise)\n");
    fprintf(stderr, "  -transpose     Transpose image\n");
    fprintf(stderr, "  -transverse    Transverse transpose image\n");
+   fprintf(stderr, "  -crop widthxheight+xofs+yofs Crop image\n");
    fprintf(stderr, "  -trim          Drop non-transformable edge blocks\n");
  #endif /* TRANSFORMS_SUPPORTED */
    fprintf(stderr, "Switches for advanced users:\n");
***************
*** 195,200 ****
--- 196,217 ----
  	select_transform(JXFORM_FLIP_V);
        else
  	usage();
+ 
+     } else if (keymatch(arg, "crop", 1)) {
+       /* crop image */
+       if (++argn >= argc)	/* advance to next argument */
+ 	usage();
+       transformoption.crop_width=0;
+       transformoption.crop_height=0;
+       transformoption.crop_xofs=0;
+       transformoption.crop_yofs=0;
+       if (sscanf(argv[argn],"%dx%d+%d+%d",
+ 		 &transformoption.crop_width,&transformoption.crop_height,
+ 		 &transformoption.crop_xofs,&transformoption.crop_yofs)<2)
+ 	usage();
+       if ((transformoption.crop_width<=0)||(transformoption.crop_height<=0))
+ 	usage();
+       select_transform(JXFORM_CROP);
  
      } else if (keymatch(arg, "grayscale", 1) || keymatch(arg, "greyscale",1)) {
        /* Force to grayscale. */
diff -c jpeg-6b/transupp.c jpeg-new/transupp.c
*** jpeg-6b/transupp.c	Sat Aug  9 18:15:26 1997
--- jpeg-new/transupp.c	Wed Jan 19 10:26:47 2000
***************
*** 553,558 ****
--- 553,617 ----
    }
  }
  
+ LOCAL(void)
+ do_crop (j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
+ 	 jvirt_barray_ptr *src_coef_arrays,
+ 	 jpeg_transform_info *info)
+ /* crop; done in-place so no separate dest array is required */
+ {
+   JDIMENSION MCU_cols, MCU_xofs, comp_width, comp_xofs, blk_x;
+   JDIMENSION MCU_rows, MCU_yofs, comp_height, comp_yofs, blk_y;
+   int ci, k, offset_y;
+   JBLOCKARRAY srcbuffer, dstbuffer;
+   jpeg_component_info *compptr;
+ 
+   /* verify that crop parameters are sane */
+   if (info->crop_width>srcinfo->image_width)
+     info->crop_width=srcinfo->image_width;
+   if (info->crop_height>srcinfo->image_height)
+     info->crop_height=srcinfo->image_height;
+   if (info->crop_xofs<0)
+     info->crop_xofs=0;
+   if (info->crop_yofs<0)
+     info->crop_yofs=0;
+   if (info->crop_xofs+info->crop_width>srcinfo->image_width)
+     info->crop_xofs=srcinfo->image_width-info->crop_width;
+   if (info->crop_yofs+info->crop_height>srcinfo->image_height)
+     info->crop_yofs=srcinfo->image_height-info->crop_height;
+ 
+   /* cropping with an offset requires that blocks be offset some whole
+    * number of blocks; therefore, crop_xofs and crop_yofs will be rounded
+    * down */
+   MCU_cols = srcinfo->image_width / (dstinfo->max_h_samp_factor * DCTSIZE);
+   MCU_xofs = info->crop_xofs / (dstinfo->max_h_samp_factor * DCTSIZE);
+   MCU_rows = srcinfo->image_height / (dstinfo->max_v_samp_factor * DCTSIZE);
+   MCU_yofs = info->crop_yofs / (dstinfo->max_v_samp_factor * DCTSIZE);
+ 
+   for (ci = 0; ci < dstinfo->num_components; ci++) {
+     compptr = dstinfo->comp_info + ci;
+     comp_width = MCU_cols * compptr->h_samp_factor;
+     comp_xofs = MCU_xofs * compptr->h_samp_factor;
+     comp_height = MCU_rows * compptr->v_samp_factor;
+     comp_yofs = MCU_yofs * compptr->v_samp_factor;
+     for (blk_y = 0; blk_y < comp_height-comp_yofs;  
+ 	 blk_y += compptr->v_samp_factor) {
+       dstbuffer = (*srcinfo->mem->access_virt_barray)
+ 	((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y,
+ 	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+       srcbuffer = (*srcinfo->mem->access_virt_barray)
+ 	((j_common_ptr) srcinfo, src_coef_arrays[ci], blk_y+comp_yofs,
+ 	 (JDIMENSION) compptr->v_samp_factor, TRUE);
+       for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
+ 	for (blk_x = 0; blk_x < comp_width-comp_xofs; blk_x++) {
+ 	  memcpy(dstbuffer[offset_y][blk_x],
+ 		 srcbuffer[offset_y][blk_x+comp_xofs],
+ 		 DCTSIZE2*sizeof(JCOEF));
+ 	}
+       }
+     }
+   }
+ }
+ 
  
  /* Request any required workspace.
   *
***************
*** 585,590 ****
--- 644,650 ----
    switch (info->transform) {
    case JXFORM_NONE:
    case JXFORM_FLIP_H:
+   case JXFORM_CROP:
      /* Don't need a workspace array */
      break;
    case JXFORM_FLIP_V:
***************
*** 797,802 ****
--- 857,866 ----
      if (info->trim)
        trim_bottom_edge(dstinfo);
      break;
+   case JXFORM_CROP:
+     dstinfo->image_width = MIN(dstinfo->image_width,info->crop_width);
+     dstinfo->image_height = MIN(dstinfo->image_height,info->crop_height);
+     break;
    }
  
    /* Return the appropriate output data set */
***************
*** 831,836 ****
--- 895,903 ----
      break;
    case JXFORM_FLIP_V:
      do_flip_v(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
+     break;
+   case JXFORM_CROP:
+     do_crop(srcinfo, dstinfo, src_coef_arrays, info);
      break;
    case JXFORM_TRANSPOSE:
      do_transpose(srcinfo, dstinfo, src_coef_arrays, dst_coef_arrays);
diff -c jpeg-6b/transupp.h jpeg-new/transupp.h
*** jpeg-6b/transupp.h	Wed Jul 23 20:39:12 1997
--- jpeg-new/transupp.h	Wed Jan 19 10:31:26 2000
***************
*** 45,51 ****
  	JXFORM_TRANSVERSE,	/* transpose across UR-to-LL axis */
  	JXFORM_ROT_90,		/* 90-degree clockwise rotation */
  	JXFORM_ROT_180,		/* 180-degree rotation */
! 	JXFORM_ROT_270		/* 270-degree clockwise (or 90 ccw) */
  } JXFORM_CODE;
  
  /*
--- 45,52 ----
  	JXFORM_TRANSVERSE,	/* transpose across UR-to-LL axis */
  	JXFORM_ROT_90,		/* 90-degree clockwise rotation */
  	JXFORM_ROT_180,		/* 180-degree rotation */
! 	JXFORM_ROT_270,		/* 270-degree clockwise (or 90 ccw) */
! 	JXFORM_CROP             /* crop image */
  } JXFORM_CODE;
  
  /*
***************
*** 88,93 ****
--- 89,99 ----
    JXFORM_CODE transform;	/* image transform operator */
    boolean trim;			/* if TRUE, trim partial MCUs as needed */
    boolean force_grayscale;	/* if TRUE, convert color image to grayscale */
+   /* Options: set by caller when transform=JXFORM_CROP */
+   JDIMENSION crop_width;        /* cropped width */
+   JDIMENSION crop_height;       /* cropped height */
+   JDIMENSION crop_xofs;         /* xoffset (rounded to lower iMCU boundary */
+   JDIMENSION crop_yofs;         /* yoffset (rounded to lower iMCU boundary */
  
    /* Internal workspace: caller should not touch these */
    int num_components;		/* # of components in workspace */
