*/
i_img*
i_readjpeg_wiol(io_glue *data, int length, char** iptc_itext, int *itlength) {
- i_img *im;
+ i_img * volatile im = NULL;
#ifdef IMEXIF_ENABLE
int seen_exif = 0;
#endif
jpeg_saved_marker_ptr markerp;
transfer_function_t transfer_f;
int channels;
+ volatile int src_set = 0;
mm_log((1,"i_readjpeg_wiol(data 0x%p, length %d,iptc_itext 0x%p)\n", data, length, iptc_itext));
/* Set error handler */
if (setjmp(jerr.setjmp_buffer)) {
+ if (src_set)
+ wiol_term_source(&cinfo);
jpeg_destroy_decompress(&cinfo);
*iptc_itext=NULL;
*itlength=0;
if (line_buffer)
myfree(line_buffer);
+ if (im)
+ i_img_destroy(im);
return NULL;
}
jpeg_save_markers(&cinfo, JPEG_APP1, 0xFFFF);
jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
jpeg_wiol_src(&cinfo, data, length);
+ src_set = 1;
(void) jpeg_read_header(&cinfo, TRUE);
(void) jpeg_start_decompress(&cinfo);
channels = cinfo.output_components;
switch (cinfo.out_color_space) {
case JCS_GRAYSCALE:
+ if (cinfo.output_components != 1) {
+ mm_log((1, "i_readjpeg: grayscale image with %d channels\n", cinfo.output_components));
+ i_push_errorf(0, "grayscale image with invalid components %d", cinfo.output_components);
+ wiol_term_source(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ return NULL;
+ }
transfer_f = transfer_gray;
break;
case JCS_RGB:
transfer_f = transfer_rgb;
+ if (cinfo.output_components != 3) {
+ mm_log((1, "i_readjpeg: RGB image with %d channels\n", cinfo.output_components));
+ i_push_errorf(0, "RGB image with invalid components %d", cinfo.output_components);
+ wiol_term_source(&cinfo);
+ jpeg_destroy_decompress(&cinfo);
+ return NULL;
+ }
break;
case JCS_CMYK:
markerp = cinfo.marker_list;
while (markerp != NULL) {
if (markerp->marker == JPEG_COM) {
- i_tags_add(&im->tags, "jpeg_comment", 0, markerp->data,
+ i_tags_add(&im->tags, "jpeg_comment", 0, (const char *)markerp->data,
markerp->data_length, 0);
}
#ifdef IMEXIF_ENABLE
int got_xres, got_yres, aspect_only, resunit;
double xres, yres;
int comment_entry;
+ int want_channels = im->channels;
struct jpeg_compress_struct cinfo;
struct my_error_mgr jerr;
JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
int row_stride; /* physical row width in image buffer */
unsigned char * data = NULL;
+ i_color *line_buf = NULL;
mm_log((1,"i_writejpeg(im %p, ig %p, qfactor %d)\n", im, ig, qfactor));
io_glue_commit_types(ig);
if (!(im->channels==1 || im->channels==3)) {
- i_push_error(0, "only 1 or 3 channels images can be saved as JPEG");
- return 0;
+ want_channels = im->channels - 1;
}
quality = qfactor;
jpeg_destroy_compress(&cinfo);
if (data)
myfree(data);
+ if (line_buf)
+ myfree(line_buf);
return 0;
}
cinfo.image_width = im -> xsize; /* image width and height, in pixels */
cinfo.image_height = im -> ysize;
- if (im->channels==3) {
+ if (want_channels==3) {
cinfo.input_components = 3; /* # of color components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
}
- if (im->channels==1) {
+ if (want_channels==1) {
cinfo.input_components = 1; /* # of color components per pixel */
cinfo.in_color_space = JCS_GRAYSCALE; /* colorspace of input image */
}
jpeg_start_compress(&cinfo, TRUE);
if (i_tags_find(&im->tags, "jpeg_comment", 0, &comment_entry)) {
- jpeg_write_marker(&cinfo, JPEG_COM, im->tags.tags[comment_entry].data,
+ jpeg_write_marker(&cinfo, JPEG_COM,
+ (const JOCTET *)im->tags.tags[comment_entry].data,
im->tags.tags[comment_entry].size);
}
row_stride = im->xsize * im->channels; /* JSAMPLEs per row in image_buffer */
- if (!im->virtual && im->type == i_direct_type && im->bits == i_8_bits) {
+ if (!im->virtual && im->type == i_direct_type && im->bits == i_8_bits
+ && im->channels == want_channels) {
image_buffer=im->idata;
while (cinfo.next_scanline < cinfo.image_height) {
}
}
else {
+ i_color bg;
+
+ i_get_file_background(im, &bg);
data = mymalloc(im->xsize * im->channels);
if (data) {
while (cinfo.next_scanline < cinfo.image_height) {
* Here the array is only one element long, but you could pass
* more than one scanline at a time if that's more convenient.
*/
- i_gsamp(im, 0, im->xsize, cinfo.next_scanline, data,
- NULL, im->channels);
+ i_gsamp_bg(im, 0, im->xsize, cinfo.next_scanline, data,
+ want_channels, &bg);
row_pointer[0] = data;
(void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
}