in turbojpeg-mp.c [141:280]
DLLEXPORT int GET_NAME(tj3Decompress, BITS_IN_JSAMPLE)
(tjhandle handle, const unsigned char *jpegBuf, size_t jpegSize,
_JSAMPLE *dstBuf, int pitch, int pixelFormat)
{
static const char FUNCTION_NAME[] =
GET_STRING(tj3Decompress, BITS_IN_JSAMPLE);
_JSAMPROW *row_pointer = NULL;
int croppedHeight, i, retval = 0;
#if BITS_IN_JSAMPLE != 16
int scaledWidth;
#endif
struct my_progress_mgr progress;
GET_DINSTANCE(handle);
if ((this->init & DECOMPRESS) == 0)
THROW("Instance has not been initialized for decompression");
if (jpegBuf == NULL || jpegSize <= 0 || dstBuf == NULL || pitch < 0 ||
pixelFormat < 0 || pixelFormat >= TJ_NUMPF)
THROW("Invalid argument");
if (this->scanLimit) {
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;
dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L;
if (setjmp(this->jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error. */
retval = -1; goto bailout;
}
if (dinfo->global_state <= DSTATE_INHEADER) {
jpeg_mem_src_tj(dinfo, jpegBuf, jpegSize);
jpeg_read_header(dinfo, TRUE);
}
setDecompParameters(this);
if (this->maxPixels &&
(unsigned long long)this->jpegWidth * this->jpegHeight >
(unsigned long long)this->maxPixels)
THROW("Image is too large");
this->dinfo.out_color_space = pf2cs[pixelFormat];
#if BITS_IN_JSAMPLE != 16
scaledWidth = TJSCALED(dinfo->image_width, this->scalingFactor);
#endif
dinfo->do_fancy_upsampling = !this->fastUpsample;
this->dinfo.dct_method = this->fastDCT ? JDCT_FASTEST : JDCT_ISLOW;
dinfo->scale_num = this->scalingFactor.num;
dinfo->scale_denom = this->scalingFactor.denom;
jpeg_start_decompress(dinfo);
#if BITS_IN_JSAMPLE != 16
if (this->croppingRegion.x != 0 ||
(this->croppingRegion.w != 0 && this->croppingRegion.w != scaledWidth)) {
JDIMENSION crop_x = this->croppingRegion.x;
JDIMENSION crop_w = this->croppingRegion.w;
_jpeg_crop_scanline(dinfo, &crop_x, &crop_w);
if ((int)crop_x != this->croppingRegion.x)
THROWI("Unexplained mismatch between specified (%d) and\n"
"actual (%d) cropping region left boundary",
this->croppingRegion.x, (int)crop_x);
if ((int)crop_w != this->croppingRegion.w)
THROWI("Unexplained mismatch between specified (%d) and\n"
"actual (%d) cropping region width",
this->croppingRegion.w, (int)crop_w);
}
#endif
if (pitch == 0) pitch = dinfo->output_width * tjPixelSize[pixelFormat];
croppedHeight = dinfo->output_height;
#if BITS_IN_JSAMPLE != 16
if (this->croppingRegion.y != 0 || this->croppingRegion.h != 0)
croppedHeight = this->croppingRegion.h;
#endif
if ((row_pointer =
(_JSAMPROW *)malloc(sizeof(_JSAMPROW) * croppedHeight)) == NULL)
THROW("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 < (int)croppedHeight; i++) {
if (this->bottomUp)
row_pointer[i] = &dstBuf[(croppedHeight - i - 1) * (size_t)pitch];
else
row_pointer[i] = &dstBuf[i * (size_t)pitch];
}
#if BITS_IN_JSAMPLE != 16
if (this->croppingRegion.y != 0 || this->croppingRegion.h != 0) {
if (this->croppingRegion.y != 0) {
JDIMENSION lines = _jpeg_skip_scanlines(dinfo, this->croppingRegion.y);
if ((int)lines != this->croppingRegion.y)
THROWI("Unexplained mismatch between specified (%d) and\n"
"actual (%d) cropping region upper boundary",
this->croppingRegion.y, (int)lines);
}
while ((int)dinfo->output_scanline <
this->croppingRegion.y + this->croppingRegion.h)
_jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline -
this->croppingRegion.y],
this->croppingRegion.y + this->croppingRegion.h -
dinfo->output_scanline);
if (this->croppingRegion.y + this->croppingRegion.h !=
(int)dinfo->output_height) {
JDIMENSION lines = _jpeg_skip_scanlines(dinfo, dinfo->output_height -
this->croppingRegion.y -
this->croppingRegion.h);
if (lines != dinfo->output_height - this->croppingRegion.y -
this->croppingRegion.h)
THROWI("Unexplained mismatch between specified (%d) and\n"
"actual (%d) cropping region lower boundary",
this->croppingRegion.y + this->croppingRegion.h,
(int)(dinfo->output_height - lines));
}
} else
#endif
{
while (dinfo->output_scanline < dinfo->output_height)
_jpeg_read_scanlines(dinfo, &row_pointer[dinfo->output_scanline],
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;
return retval;
}