in turbojpeg.c [1222:1354]
DLLEXPORT int tj3CompressFromYUVPlanes8(tjhandle handle,
const unsigned char * const *srcPlanes,
int width, const int *strides,
int height, unsigned char **jpegBuf,
size_t *jpegSize)
{
static const char FUNCTION_NAME[] = "tj3CompressFromYUVPlanes8";
int i, row, retval = 0;
boolean alloc = TRUE;
int pw[MAX_COMPONENTS], ph[MAX_COMPONENTS], iw[MAX_COMPONENTS],
tmpbufsize = 0, usetmpbuf = 0, th[MAX_COMPONENTS];
JSAMPLE *_tmpbuf = NULL, *ptr;
JSAMPROW *inbuf[MAX_COMPONENTS], *tmpbuf[MAX_COMPONENTS];
GET_CINSTANCE(handle)
for (i = 0; i < MAX_COMPONENTS; i++) {
tmpbuf[i] = NULL; inbuf[i] = NULL;
}
if ((this->init & COMPRESS) == 0)
THROW("Instance has not been initialized for compression");
if (!srcPlanes || !srcPlanes[0] || width <= 0 || height <= 0 ||
jpegBuf == NULL || jpegSize == NULL)
THROW("Invalid argument");
if (this->subsamp != TJSAMP_GRAY && (!srcPlanes[1] || !srcPlanes[2]))
THROW("Invalid argument");
if (this->quality == -1)
THROW("TJPARAM_QUALITY must be specified");
if (this->subsamp == TJSAMP_UNKNOWN)
THROW("TJPARAM_SUBSAMP must be specified");
if (setjmp(this->jerr.setjmp_buffer)) {
/* If we get here, the JPEG code has signaled an error. */
retval = -1; goto bailout;
}
cinfo->image_width = width;
cinfo->image_height = height;
cinfo->data_precision = 8;
if (this->noRealloc) {
alloc = FALSE; *jpegSize = tj3JPEGBufSize(width, height, this->subsamp);
}
jpeg_mem_dest_tj(cinfo, jpegBuf, jpegSize, alloc);
setCompDefaults(this, TJPF_RGB);
cinfo->raw_data_in = TRUE;
jpeg_start_compress(cinfo, TRUE);
for (i = 0; i < cinfo->num_components; i++) {
jpeg_component_info *compptr = &cinfo->comp_info[i];
int ih;
iw[i] = compptr->width_in_blocks * DCTSIZE;
ih = compptr->height_in_blocks * DCTSIZE;
pw[i] = PAD(cinfo->image_width, cinfo->max_h_samp_factor) *
compptr->h_samp_factor / cinfo->max_h_samp_factor;
ph[i] = PAD(cinfo->image_height, cinfo->max_v_samp_factor) *
compptr->v_samp_factor / cinfo->max_v_samp_factor;
if (iw[i] != pw[i] || ih != ph[i]) usetmpbuf = 1;
th[i] = compptr->v_samp_factor * DCTSIZE;
tmpbufsize += iw[i] * th[i];
if ((inbuf[i] = (JSAMPROW *)malloc(sizeof(JSAMPROW) * ph[i])) == NULL)
THROW("Memory allocation failure");
ptr = (JSAMPLE *)srcPlanes[i];
for (row = 0; row < ph[i]; row++) {
inbuf[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 < cinfo->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;
}
for (row = 0; row < (int)cinfo->image_height;
row += cinfo->max_v_samp_factor * DCTSIZE) {
JSAMPARRAY yuvptr[MAX_COMPONENTS];
int crow[MAX_COMPONENTS];
for (i = 0; i < cinfo->num_components; i++) {
jpeg_component_info *compptr = &cinfo->comp_info[i];
crow[i] = row * compptr->v_samp_factor / cinfo->max_v_samp_factor;
if (usetmpbuf) {
int j, k;
for (j = 0; j < MIN(th[i], ph[i] - crow[i]); j++) {
memcpy(tmpbuf[i][j], inbuf[i][crow[i] + j], pw[i]);
/* Duplicate last sample in row to fill out MCU */
for (k = pw[i]; k < iw[i]; k++)
tmpbuf[i][j][k] = tmpbuf[i][j][pw[i] - 1];
}
/* Duplicate last row to fill out MCU */
for (j = ph[i] - crow[i]; j < th[i]; j++)
memcpy(tmpbuf[i][j], tmpbuf[i][ph[i] - crow[i] - 1], iw[i]);
yuvptr[i] = tmpbuf[i];
} else
yuvptr[i] = &inbuf[i][crow[i]];
}
jpeg_write_raw_data(cinfo, yuvptr, cinfo->max_v_samp_factor * DCTSIZE);
}
jpeg_finish_compress(cinfo);
bailout:
if (cinfo->global_state > CSTATE_START && alloc)
(*cinfo->dest->term_destination) (cinfo);
if (cinfo->global_state > CSTATE_START || retval == -1)
jpeg_abort_compress(cinfo);
for (i = 0; i < MAX_COMPONENTS; i++) {
free(tmpbuf[i]);
free(inbuf[i]);
}
free(_tmpbuf);
if (this->jerr.warning) retval = -1;
return retval;
}