add i_gsamp_bg/i_gsampf_bg functions, sample based versions of
authorTony Cook <tony@develop=help.com>
Tue, 1 Apr 2008 09:24:17 +0000 (09:24 +0000)
committerTony Cook <tony@develop=help.com>
Tue, 1 Apr 2008 09:24:17 +0000 (09:24 +0000)
i_adapt_colors()

revert the pnm/jpeg writing code to closer to the older version, using
i_gsamp_bg() to avoid the extra steps

imager.h
jpeg.c
paste.im
pnm.c

index 24fd57e..de45b78 100644 (file)
--- a/imager.h
+++ b/imager.h
@@ -599,4 +599,12 @@ extern void
 i_adapt_fcolors_bg(int dest_channels, int src_channels, i_fcolor *colors, 
                   size_t count, i_fcolor const *bg);
 
+extern int
+i_gsamp_bg(i_img *im, int l, int r, int y, i_sample_t *samples, 
+          int out_channels, i_color const *bg);
+
+extern int
+i_gsampf_bg(i_img *im, int l, int r, int y, i_fsample_t *samples, 
+          int out_channels, i_fcolor const *bg);
+
 #endif
diff --git a/jpeg.c b/jpeg.c
index 38566f5..f886df2 100644 (file)
--- a/jpeg.c
+++ b/jpeg.c
@@ -673,7 +673,10 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
       (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
     }
   }
-  else if (im->channels == want_channels) {
+  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) {
@@ -681,8 +684,8 @@ i_writejpeg_wiol(i_img *im, io_glue *ig, int qfactor) {
          * 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);
       }
@@ -694,35 +697,6 @@ 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 */
 
index 669c6ca..ef7d144 100644 (file)
--- a/paste.im
+++ b/paste.im
@@ -325,7 +325,125 @@ i_adapt_fcolors_bg
     }
     break;
   }
+}
+
+/*
+=item i_gsamp_bg(im, l, r, y, samples, out_channels, bg)
+
+=item i_gsampf_bg(im, l, r, y, samples, out_channels, bg)
+
+This is similar to i_adapt_colors_bg() except it can only strip an
+alpha channel.  It cannot be used to convert a source RGB image to
+greyscale.
+
+The samples parameter MUST include enough space for all samples of the
+source image.
+
+=cut
+*/
+int
+#ifdef IM_EIGHT_BIT
+i_gsamp_bg
+#else
+i_gsampf_bg
+#endif
+(i_img *im, int l, int r, int y, IM_SAMPLE_T *samples, 
+ int out_channels, IM_COLOR const *bg) {
+  if (out_channels == im->channels)
+    return IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
+  
+  switch (out_channels) {
+  case 1:
+    switch (im->channels) {
+    case 2:
+      {
+       int x;
+       IM_SAMPLE_T *inp = samples, *outp = samples;
+       IM_WORK_T grey_bg = IM_ROUND(color_to_grey(bg));
+       int count;
+
+       count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
+       if (!count)
+         return 0;
+       
+       for (x = l; x < r; ++x) {
+         *outp++ = ( inp[0] * inp[1] +
+                     grey_bg * (IM_SAMPLE_MAX - inp[1])) / IM_SAMPLE_MAX;
+         inp += 2;
+       }
+
+       return count;
+      }
+      break;
+
+    default:
+      i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
+      break;
+    }
+    break;
+  case 3:
+    switch (im->channels) {
+    case 1:
+      {
+       int channels[3] = { 0, 0, 0 };
+       return IM_GSAMP(im, l, r, y, samples, channels, out_channels);
+      }
+    case 2:
+      {
+       int x, ch;
+       IM_SAMPLE_T *inp = samples, *outp = samples;
+       int count;
+       int channels[4] = { 0, 0, 0, 1 };
+
+       count = IM_GSAMP(im, l, r, y, samples, channels, im->channels);
+       if (!count)
+         return 0;
+       
+       for (x = l; x < r; ++x) {
+         IM_WORK_T alpha = inp[3];
+         for (ch = 0; ch < 3; ++ch) {
+           *outp++ = ( *inp++ * alpha +
+                       bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
+         }
+         ++inp;
+       }
+
+       return count;
+      }
+
+    case 4:
+      {
+       int x, ch;
+       IM_SAMPLE_T *inp = samples, *outp = samples;
+       int count;
+
+       count = IM_GSAMP(im, l, r, y, samples, NULL, im->channels);
+       if (!count)
+         return 0;
+       
+       for (x = l; x < r; ++x) {
+         IM_WORK_T alpha = inp[3];
+         for (ch = 0; ch < 3; ++ch) {
+           *outp++ = ( *inp++ * alpha +
+                       bg->channel[ch] * (IM_SAMPLE_MAX - alpha)) / IM_SAMPLE_MAX;
+         }
+         ++inp;
+       }
+
+       return count;
+      }
+      break;
+    default:
+      i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
+      break;
+    }
+    break;
+
+  default:
+    i_fatal(0, "i_gsamp_bg() can only remove alpha channels");
+  }
 
+  return 0;
 }
 
 #/code
diff --git a/pnm.c b/pnm.c
index 609fbbc..ca35437 100644 (file)
--- a/pnm.c
+++ b/pnm.c
@@ -753,38 +753,23 @@ static
 int
 write_ppm_data_8(i_img *im, io_glue *ig, int want_channels) {
   int write_size = im->xsize * want_channels;
-  i_color *line_buf = mymalloc(sizeof(i_color) * im->xsize);
-  unsigned char *data = mymalloc(write_size);
+  int buf_size = im->xsize * im->channels;
+  unsigned char *data = mymalloc(buf_size);
   int y = 0;
-  int x;
-  int ch;
   int rc = 1;
   i_color bg;
 
   i_get_file_background(im, &bg);
   while (y < im->ysize && rc >= 0) {
-    i_color *linep = line_buf;
-    unsigned char *datap = data;
-
-    i_glin(im, 0, im->xsize, y, line_buf);
-    i_adapt_colors_bg(want_channels, im->channels, line_buf, im->xsize, &bg);
-    for (x = 0; x < im->xsize; ++x) {
-      for (ch = 0; ch < want_channels; ++ch) {
-       *datap++ = linep->channel[ch];
-      }
-      ++linep;
-    }
+    i_gsamp_bg(im, 0, im->xsize, y, data, want_channels, &bg);
     if (i_io_write(ig, data, write_size) != write_size) {
       i_push_error(errno, "could not write ppm data");
-      myfree(data);
-      myfree(line_buf);
       rc = 0;
       break;
     }
     ++y;
   }
   myfree(data);
-  myfree(line_buf);
 
   return rc;
 }
@@ -792,10 +777,14 @@ write_ppm_data_8(i_img *im, io_glue *ig, int want_channels) {
 static
 int
 write_ppm_data_16(i_img *im, io_glue *ig, int want_channels) {
+  int line_size = im->channels * im->xsize * sizeof(i_fsample_t);
   int sample_count = want_channels * im->xsize;
   int write_size = sample_count * 2;
-  i_fcolor *line_buf = mymalloc(sizeof(i_fcolor) * im->xsize);
+  i_fsample_t *line_buf = mymalloc(line_size);
+  i_fsample_t *samplep;
   unsigned char *write_buf = mymalloc(write_size);
+  unsigned char *writep;
+  int sample_num;
   int y = 0;
   int x, ch;
   int rc = 1;
@@ -804,20 +793,14 @@ write_ppm_data_16(i_img *im, io_glue *ig, int want_channels) {
   i_get_file_backgroundf(im, &bg);
 
   while (y < im->ysize) {
-    i_fcolor *linep = line_buf;
-    unsigned char *writep = write_buf;
-
-    i_glinf(im, 0, im->xsize, y, line_buf);
-    i_adapt_fcolors_bg(want_channels, im->channels, line_buf, im->xsize, &bg);
-    for (x = 0; x < im->xsize; ++x) {
-      for (ch = 0; ch < want_channels; ++ch) {
-       unsigned sample16 = SampleFTo16(linep->channel[ch]);
-       *writep++ = sample16 >> 8;
-       *writep++ = sample16 & 0xFF;
-      }
-      ++linep;
+    i_gsampf_bg(im, 0, im->xsize, y, line_buf, want_channels, &bg);
+    samplep = line_buf;
+    writep = write_buf;
+    for (sample_num = 0; sample_num < sample_count; ++sample_num) {
+      unsigned sample16 = SampleFTo16(*samplep++);
+      *writep++ = sample16 >> 8;
+      *writep++ = sample16 & 0xFF;
     }
-    
     if (i_io_write(ig, write_buf, write_size) != write_size) {
       i_push_error(errno, "could not write ppm data");
       rc = 0;