- writing a 2 or 4 channel image to a JPEG will now write that image as
[imager.git] / jpeg.c
diff --git a/jpeg.c b/jpeg.c
index f3d5fc7f917ea84cb523e728ff7ae31da4566471..38566f51dee9e5f040450e6a00dec767a468d586 100644 (file)
--- a/jpeg.c
+++ b/jpeg.c
@@ -572,6 +572,7 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
   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;
@@ -579,6 +580,7 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
   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));
   
@@ -586,8 +588,7 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int 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;
 
@@ -601,6 +602,8 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
     jpeg_destroy_compress(&cinfo);
     if (data)
       myfree(data);
+    if (line_buf)
+      myfree(line_buf);
     return 0;
   }
 
@@ -609,12 +612,12 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
   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 */
   }
@@ -657,7 +660,8 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
 
   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) {
@@ -669,7 +673,7 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
       (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
     }
   }
-  else {
+  else if (im->channels == want_channels) {
     data = mymalloc(im->xsize * im->channels);
     if (data) {
       while (cinfo.next_scanline < cinfo.image_height) {
@@ -690,6 +694,35 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
       return 0; /* out of memory? */
     }
   }
+  else {
+    i_color bg;
+    int x;
+    int ch;
+    i_color const *linep;
+    unsigned char * datap;    
+    
+    line_buf = mymalloc(sizeof(i_color) * im->xsize);
+
+    i_get_file_background(im, &bg);
+
+    data = mymalloc(im->xsize * want_channels);
+    while (cinfo.next_scanline < cinfo.image_height) {
+      i_glin(im, 0, im->xsize, cinfo.next_scanline, line_buf);
+      i_adapt_colors_bg(want_channels, im->channels, line_buf, im->xsize, &bg);
+      datap = data;
+      linep = line_buf;
+      for (x = 0; x < im->xsize; ++x) {
+       for (ch = 0; ch < want_channels; ++ch) {
+         *datap++ = linep->channel[ch];
+       }
+       ++linep;
+      }
+      row_pointer[0] = data;
+      (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
+    }
+    myfree(line_buf);
+    myfree(data);
+  }
 
   /* Step 6: Finish compression */