diff --git a/turbojpeg-mapfile b/turbojpeg-mapfile
index 5477fed2..4eae5b45 100644
--- a/turbojpeg-mapfile
+++ b/turbojpeg-mapfile
@@ -62,4 +62,5 @@ TURBOJPEG_2.0
     tjGetErrorStr2;
     tjLoadImage;
     tjSaveImage;
+    tjCropDecompress2;
 } TURBOJPEG_1.4;
diff --git a/turbojpeg.c b/turbojpeg.c
index d780dc25..64bcf281 100644
--- a/turbojpeg.c
+++ b/turbojpeg.c
@@ -1276,6 +1276,98 @@ DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors)
 }


+DLLEXPORT int tjCropDecompress2(tjhandle handle, const unsigned char *jpegBuf,
+                                unsigned long jpegSize, unsigned char *dstBuf,
+                                int width, int pitch, int height, int pixelFormat,
+                                int flags, int crop_x, int crop_y, int crop_h, int crop_w)
+{
+  JSAMPROW *row_pointer = NULL;
+  int i, retval = 0, jpegwidth, jpegheight, scaledw, scaledh;
+  struct my_progress_mgr progress;
+
+  GET_DINSTANCE(handle);
+  this->jerr.stopOnWarning = (flags & TJFLAG_STOPONWARNING) ? TRUE : FALSE;
+  if ((this->init & DECOMPRESS) == 0)
+    THROW("tjDecompress2(): Instance has not been initialized for decompression");
+
+  if (jpegBuf == NULL || jpegSize <= 0 || dstBuf == NULL || width < 0 ||
+      pitch < 0 || height < 0 || pixelFormat < 0 || pixelFormat >= TJ_NUMPF)
+    THROW("tjDecompress2(): Invalid argument");
+
+#ifndef NO_PUTENV
+  if (flags & TJFLAG_FORCEMMX) putenv("JSIMD_FORCEMMX=1");
+  else if (flags & TJFLAG_FORCESSE) putenv("JSIMD_FORCESSE=1");
+  else if (flags & TJFLAG_FORCESSE2) putenv("JSIMD_FORCESSE2=1");
+#endif
+
+  if (flags & TJFLAG_LIMITSCANS) {
+    memset(&progress, 0, sizeof(struct my_progress_mgr));
+    progress.pub.progress_monitor = my_progress_monitor;
+    progress.this = this;
+    dinfo->progress = &progress.pub;
+  } else
+    dinfo->progress = NULL;
+
+  if (setjmp(this->jerr.setjmp_buffer)) {
+    /* If we get here, the JPEG code has signaled an error. */
+    retval = -1;  goto bailout;
+  }
+
+  jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
+  jpeg_read_header(dinfo, TRUE);
+  this->dinfo.out_color_space = pf2cs[pixelFormat];
+  if (flags & TJFLAG_FASTDCT) this->dinfo.dct_method = JDCT_FASTEST;
+  if (flags & TJFLAG_FASTUPSAMPLE) dinfo->do_fancy_upsampling = FALSE;
+
+  jpegwidth = dinfo->image_width;  jpegheight = dinfo->image_height;
+  if (width == 0) width = jpegwidth;
+  if (height == 0) height = jpegheight;
+  for (i = 0; i < NUMSF; i++) {
+    scaledw = TJSCALED(jpegwidth, sf[i]);
+    scaledh = TJSCALED(jpegheight, sf[i]);
+    if (scaledw <= width && scaledh <= height)
+      break;
+  }
+  if (i >= NUMSF)
+    THROW("tjCropDecompress2(): Could not scale down to desired image dimensions");
+  width = scaledw;  height = scaledh;
+  dinfo->scale_num = sf[i].num;
+  dinfo->scale_denom = sf[i].denom;
+
+  jpeg_start_decompress(dinfo);
+  if (pitch == 0) pitch = crop_w * tjPixelSize[pixelFormat];
+
+  if ((row_pointer =
+       (JSAMPROW *)malloc(sizeof(JSAMPROW) * crop_h)) == NULL)
+    THROW("tjDecompress2(): Memory allocation failure");
+  if (setjmp(this->jerr.setjmp_buffer)) {
+    /* If we get here, the JPEG code has signaled an error. */
+    retval = -1;  goto bailout;
+  }
+  for (i = 0; i < crop_h; i++) {
+    if (flags & TJFLAG_BOTTOMUP)
+      row_pointer[i] = &dstBuf[(crop_h - i - 1) * (size_t)pitch];
+    else
+      row_pointer[i] = &dstBuf[i * (size_t)pitch];
+  }
+    //crop image
+    jpeg_crop_scanline(dinfo, &crop_y, &crop_w);
+    jpeg_skip_scanlines(dinfo, crop_x);
+  while (dinfo->output_scanline < dinfo->output_height && dinfo->output_scanline < crop_h + crop_x)
+    jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline-crop_x],
+                        crop_x + crop_h - dinfo->output_scanline);
+  jpeg_skip_scanlines(dinfo, dinfo->output_height - dinfo->output_scanline);
+  jpeg_finish_decompress(dinfo);
+
+bailout:
+  if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo);
+  free(row_pointer);
+  if (this->jerr.warning) retval = -1;
+  this->jerr.stopOnWarning = FALSE;
+  return retval;
+}
+
+
 DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf,
                             unsigned long jpegSize, unsigned char *dstBuf,
                             int width, int pitch, int height, int pixelFormat,
diff --git a/turbojpeg.h b/turbojpeg.h
index 5b33ad84..64b5e86c 100644
--- a/turbojpeg.h
+++ b/turbojpeg.h
@@ -1224,6 +1224,13 @@ DLLEXPORT tjscalingfactor *tjGetScalingFactors(int *numscalingfactors);
  * @return 0 if successful, or -1 if an error occurred (see #tjGetErrorStr2()
  * and #tjGetErrorCode().)
  */
+
+DLLEXPORT int tjCropDecompress2(tjhandle handle, const unsigned char *jpegBuf,
+                                unsigned long jpegSize, unsigned char *dstBuf,
+                                int width, int pitch, int height, int pixelFormat,
+                                int flags, int crop_x, int crop_y,int crop_h, int crop_w);
+
+
 DLLEXPORT int tjDecompress2(tjhandle handle, const unsigned char *jpegBuf,
                             unsigned long jpegSize, unsigned char *dstBuf,
                             int width, int pitch, int height, int pixelFormat,
