in turbojpeg.c [2032:2195]
DLLEXPORT int tj3DecompressToYUVPlanes8(tjhandle handle,
const unsigned char *jpegBuf,
size_t jpegSize,
unsigned char **dstPlanes,
int *strides)
{
static const char FUNCTION_NAME[] = "tj3DecompressToYUVPlanes8";
int i, row, retval = 0;
int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
tmpbufsize = 0, usetmpbuf = 0, th[MAX_COMPONENTS];
JSAMPLE *_tmpbuf = NULL, *ptr;
JSAMPROW *outbuf[MAX_COMPONENTS], *tmpbuf[MAX_COMPONENTS];
int dctsize;
struct my_progress_mgr progress;
GET_DINSTANCE(handle);
for (i = 0; i < MAX_COMPONENTS; i++) {
tmpbuf[i] = NULL; outbuf[i] = NULL;
}
if ((this->init & DECOMPRESS) == 0)
THROW("Instance has not been initialized for decompression");
if (jpegBuf == NULL || jpegSize <= 0 || !dstPlanes || !dstPlanes[0])
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");
if (this->subsamp == TJSAMP_UNKNOWN)
THROW("Could not determine subsampling level of JPEG image");
if (this->subsamp != TJSAMP_GRAY && (!dstPlanes[1] || !dstPlanes[2]))
THROW("Invalid argument");
if (dinfo->num_components > 3)
THROW("JPEG image must have 3 or fewer components");
dinfo->scale_num = this->scalingFactor.num;
dinfo->scale_denom = this->scalingFactor.denom;
jpeg_calc_output_dimensions(dinfo);
dctsize = DCTSIZE * this->scalingFactor.num / this->scalingFactor.denom;
for (i = 0; i < dinfo->num_components; i++) {
jpeg_component_info *compptr = &dinfo->comp_info[i];
int ih;
iw[i] = compptr->width_in_blocks * dctsize;
ih = compptr->height_in_blocks * dctsize;
pw[i] = tj3YUVPlaneWidth(i, dinfo->output_width, this->subsamp);
ph[i] = tj3YUVPlaneHeight(i, dinfo->output_height, this->subsamp);
if (iw[i] != pw[i] || ih != ph[i]) usetmpbuf = 1;
th[i] = compptr->v_samp_factor * dctsize;
tmpbufsize += iw[i] * th[i];
if ((outbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph[i])) == NULL)
THROW("Memory allocation failure");
ptr = dstPlanes[i];
for (row = 0; row < ph[i]; row++) {
outbuf[i][row] = ptr;
ptr += (strides && strides[i] != 0) ? strides[i] : pw[i];
}
}
if (usetmpbuf) {
if ((_tmpbuf = (JSAMPLE *)MALLOC(sizeof(JSAMPLE) * tmpbufsize)) == NULL)
THROW("Memory allocation failure");
ptr = _tmpbuf;
for (i = 0; i < dinfo->num_components; i++) {
if ((tmpbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * th[i])) == NULL)
THROW("Memory allocation failure");
for (row = 0; row < th[i]; row++) {
tmpbuf[i][row] = ptr;
ptr += iw[i];
}
}
}
if (setjmp(this->jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error. */
retval = -1; goto bailout;
}
dinfo->do_fancy_upsampling = !this->fastUpsample;
dinfo->dct_method = this->fastDCT ? JDCT_FASTEST : JDCT_ISLOW;
dinfo->raw_data_out = TRUE;
dinfo->mem->max_memory_to_use = (long)this->maxMemory * 1048576L;
jpeg_start_decompress(dinfo);
for (row = 0; row < (int)dinfo->output_height;
row += dinfo->max_v_samp_factor * dinfo->_min_DCT_scaled_size) {
JSAMPARRAY yuvptr[MAX_COMPONENTS];
int crow[MAX_COMPONENTS];
for (i = 0; i < dinfo->num_components; i++) {
jpeg_component_info *compptr = &dinfo->comp_info[i];
if (this->subsamp == TJSAMP_420) {
/* When 4:2:0 subsampling is used with IDCT scaling, libjpeg will try
to be clever and use the IDCT to perform upsampling on the U and V
planes. For instance, if the output image is to be scaled by 1/2
relative to the JPEG image, then the scaling factor and upsampling
effectively cancel each other, so a normal 8x8 IDCT can be used.
However, this is not desirable when using the decompress-to-YUV
functionality in TurboJPEG, since we want to output the U and V
planes in their subsampled form. Thus, we have to override some
internal libjpeg parameters to force it to use the "scaled" IDCT
functions on the U and V planes. */
compptr->_DCT_scaled_size = dctsize;
compptr->MCU_sample_width = tjMCUWidth[this->subsamp] *
this->scalingFactor.num / this->scalingFactor.denom *
compptr->v_samp_factor / dinfo->max_v_samp_factor;
dinfo->idct->inverse_DCT[i] = dinfo->idct->inverse_DCT[0];
}
crow[i] = row * compptr->v_samp_factor / dinfo->max_v_samp_factor;
if (usetmpbuf) yuvptr[i] = tmpbuf[i];
else yuvptr[i] = &outbuf[i][crow[i]];
}
jpeg_read_raw_data(dinfo, yuvptr,
dinfo->max_v_samp_factor * dinfo->_min_DCT_scaled_size);
if (usetmpbuf) {
int j;
for (i = 0; i < dinfo->num_components; i++) {
for (j = 0; j < MIN(th[i], ph[i] - crow[i]); j++) {
memcpy(outbuf[i][crow[i] + j], tmpbuf[i][j], pw[i]);
}
}
}
}
jpeg_finish_decompress(dinfo);
bailout:
if (dinfo->global_state > DSTATE_START) jpeg_abort_decompress(dinfo);
for (i = 0; i < MAX_COMPONENTS; i++) {
free(tmpbuf[i]);
free(outbuf[i]);
}
free(_tmpbuf);
if (this->jerr.warning) retval = -1;
return retval;
}