--- jpeg-7/jdcoefct.c.pre	2009-09-21 19:44:39.000000000 +1000
+++ jpeg-7/jdcoefct.c	2009-09-21 22:34:12.000000000 +1000
@@ -155,15 +155,44 @@
   JDIMENSION start_col, output_col;
   jpeg_component_info *compptr;
   inverse_DCT_method_ptr inverse_DCT;
-
+  /* region decoding. this limits decode to the set of blocks +- 1 outside
+   * bounding blocks around the desired region to decode */
+  int blk1 = 0, blk2 = 0, skip = 0;
+
+  if ((cinfo->region_w > 0) && (cinfo->region_h > 0)) {
+    int bsz_w = 0, bsz_h = 0;
+
+    for (ci = 0; ci < cinfo->comps_in_scan; ci++) {
+      compptr = cinfo->cur_comp_info[ci];
+      if (compptr->MCU_sample_width > bsz_w)
+        bsz_w = compptr->MCU_sample_width;
+      if ((compptr->MCU_height * 8) > bsz_h)
+        bsz_h = compptr->MCU_height * 8;
+    }
+    if (((int)cinfo->output_scanline < ((int)cinfo->region_y - bsz_h - 1)) ||
+        ((int)cinfo->output_scanline > ((int)cinfo->region_y + cinfo->region_h + bsz_h)))
+      skip = 1;
+    blk1 = (cinfo->region_x / bsz_w) - 1;
+    if (blk1 < 0) blk1 = 0;
+    blk2 = ((cinfo->region_x + cinfo->region_w + bsz_w - 1) / bsz_w) + 1;
+    if (blk2 < 0) blk2 = 0;
+  }
+  
   /* Loop to process as much as one whole iMCU row */
   for (yoffset = coef->MCU_vert_offset; yoffset < coef->MCU_rows_per_iMCU_row;
        yoffset++) {
     for (MCU_col_num = coef->MCU_ctr; MCU_col_num <= last_MCU_col;
 	 MCU_col_num++) {
+      /* see if we need to skip this MCU or not */
+      if ((cinfo->region_w > 0) && (cinfo->region_h > 0)) {
+        if (!((MCU_col_num < blk1) || (MCU_col_num > blk2) || skip))
+          skip = 0;
+      }
+      /* if we are not skipping this MCU, zero it ready for huffman decode */
+      if (!skip)
+        jzero_far((void FAR *) coef->MCU_buffer[0],
+                  (size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
       /* Try to fetch an MCU.  Entropy decoder expects buffer to be zeroed. */
-      jzero_far((void FAR *) coef->MCU_buffer[0],
-		(size_t) (cinfo->blocks_in_MCU * SIZEOF(JBLOCK)));
       if (! (*cinfo->entropy->decode_mcu) (cinfo, coef->MCU_buffer)) {
 	/* Suspension forced; update state counters and exit */
 	coef->MCU_vert_offset = yoffset;
@@ -172,15 +201,8 @@
       }
       /* region decoding. this limits decode to the set of blocks +- 1 outside
        * bounding blocks around the desired region to decode */
-      if ((cinfo->region_w > 0) && (cinfo->region_h > 0)) {
-        // FIXME: compute outside loop
-        int block1, block2;
-        block1 = (cinfo->region_x / compptr->MCU_width) - 1;
-        if (block1 < 0) block1 = 0;
-        block2 = ((cinfo->region_x + cinfo->region_w + compptr->MCU_width - 1) / compptr->MCU_width) + 1;
-        printf("%i < %i || > %i\n", MCU_col_num, block1, block2);
-        if ((MCU_col_num < block1) || (MCU_col_num > block2)) continue;
-      }
+      if (skip)
+        continue;
       /* Determine where data should go in output_buf and do the IDCT thing.
        * We skip dummy blocks at the right and bottom edges (but blkn gets
        * incremented past them!).  Note the inner loop relies on having
--- jpeg-7/jpeglib.h.pre	2009-09-21 01:15:24.000000000 +1000
+++ jpeg-7/jpeglib.h	2009-09-21 01:22:41.000000000 +1000
@@ -456,6 +456,8 @@
 
   unsigned int scale_num, scale_denom; /* fraction by which to scale image */
 
+  unsigned int region_x, region_y, region_w, region_h; /* if region_w && region_h > 0, then use this region to decode. scale above is done prior to region select */
+   
   double output_gamma;		/* image gamma wanted in output */
 
   boolean buffered_image;	/* TRUE=multiple output passes */
--- jpeg-7/jdapimin.c.pre	2009-09-21 10:31:23.000000000 +1000
+++ jpeg-7/jdapimin.c	2009-09-21 10:30:09.000000000 +1000
@@ -79,6 +79,12 @@
   /* And initialize the overall input controller. */
   jinit_input_controller(cinfo);
 
+  /* Init region to decode to be empty */
+  cinfo->region_x = 0;
+  cinfo->region_y = 0;
+  cinfo->region_w = 0;
+  cinfo->region_h = 0;
+
   /* OK, I'm ready */
   cinfo->global_state = DSTATE_START;
 }
--- jpeg-7/jdmerge.c.pre	2009-09-21 19:45:08.000000000 +1000
+++ jpeg-7/jdmerge.c	2009-09-21 19:39:13.000000000 +1000
@@ -151,7 +151,8 @@
   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
   JSAMPROW work_ptrs[2];
   JDIMENSION num_rows;		/* number of rows returned to caller */
-
+  int skip = 0;
+   
   if (upsample->spare_full) {
     /* If we have a spare row saved from a previous cycle, just return it. */
     jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
@@ -159,6 +160,11 @@
     num_rows = 1;
     upsample->spare_full = FALSE;
   } else {
+    if ((cinfo->region_w > 0) && (cinfo->region_h > 0)) {
+       if (((int)cinfo->output_scanline < (int)cinfo->region_y) ||
+           ((int)cinfo->output_scanline >= ((int)cinfo->region_y + (int)cinfo->region_h)))
+         skip = 1;
+    }
     /* Figure number of rows to return to caller. */
     num_rows = 2;
     /* Not more than the distance to the end of the image. */
@@ -177,7 +183,8 @@
       upsample->spare_full = TRUE;
     }
     /* Now do the upsampling. */
-    (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
+    if (!skip)
+      (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
   }
 
   /* Adjust counts */
@@ -230,6 +237,7 @@
   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
   register int y, cred, cgreen, cblue;
   int cb, cr;
+  int width;
   register JSAMPROW outptr;
   JSAMPROW inptr0, inptr1, inptr2;
   JDIMENSION col;
@@ -245,8 +253,16 @@
   inptr1 = input_buf[1][in_row_group_ctr];
   inptr2 = input_buf[2][in_row_group_ctr];
   outptr = output_buf[0];
+  width = cinfo->output_width;
+  if ((cinfo->region_w > 0) && (cinfo->region_h > 0)) {
+     outptr += RGB_PIXELSIZE * cinfo->region_x;
+     inptr0 += cinfo->region_x;
+     inptr1 += cinfo->region_x / 2;
+     inptr2 += cinfo->region_x / 2;
+     width = cinfo->region_w;
+  }
   /* Loop for each pair of output pixels */
-  for (col = cinfo->output_width >> 1; col > 0; col--) {
+  for (col = width >> 1; col > 0; col--) {
     /* Do the chroma part of the calculation */
     cb = GETJSAMPLE(*inptr1++);
     cr = GETJSAMPLE(*inptr2++);
@@ -266,7 +282,7 @@
     outptr += RGB_PIXELSIZE;
   }
   /* If image width is odd, do the last output column separately */
-  if (cinfo->output_width & 1) {
+  if (width & 1) {
     cb = GETJSAMPLE(*inptr1);
     cr = GETJSAMPLE(*inptr2);
     cred = Crrtab[cr];
@@ -292,6 +308,7 @@
   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
   register int y, cred, cgreen, cblue;
   int cb, cr;
+  int width;
   register JSAMPROW outptr0, outptr1;
   JSAMPROW inptr00, inptr01, inptr1, inptr2;
   JDIMENSION col;
@@ -309,8 +326,18 @@
   inptr2 = input_buf[2][in_row_group_ctr];
   outptr0 = output_buf[0];
   outptr1 = output_buf[1];
+  width = cinfo->output_width;
+  if ((cinfo->region_w > 0) && (cinfo->region_h > 0)) {
+     outptr0 += RGB_PIXELSIZE * cinfo->region_x;
+     outptr1 += RGB_PIXELSIZE * cinfo->region_x;
+     inptr00 += cinfo->region_x;
+     inptr01 += cinfo->region_x;
+     inptr1 += cinfo->region_x / 2;
+     inptr2 += cinfo->region_x / 2;
+     width = cinfo->region_w;
+  }
   /* Loop for each group of output pixels */
-  for (col = cinfo->output_width >> 1; col > 0; col--) {
+  for (col = width >> 1; col > 0; col--) {
     /* Do the chroma part of the calculation */
     cb = GETJSAMPLE(*inptr1++);
     cr = GETJSAMPLE(*inptr2++);
@@ -340,7 +367,7 @@
     outptr1 += RGB_PIXELSIZE;
   }
   /* If image width is odd, do the last output column separately */
-  if (cinfo->output_width & 1) {
+  if (width & 1) {
     cb = GETJSAMPLE(*inptr1);
     cr = GETJSAMPLE(*inptr2);
     cred = Crrtab[cr];
