]> git.imager.perl.org - imager.git/blobdiff - filters.im
update Changes
[imager.git] / filters.im
index 918963ece368c5ed8491c059b5f571404947b7cd..7c23a5a56ab0fa4d5779c9cb58d03aa22f286d59 100644 (file)
@@ -414,7 +414,6 @@ i_bumpmap_complex(i_img *im,
                  i_color *Is) {
   i_img new_im;
   
-  int inflight;
   i_img_dim x, y;
   int ch;
   i_img_dim mx, Mx, my, My;
@@ -462,7 +461,6 @@ i_bumpmap_complex(i_img *im,
     L.z = -Lz;
     normalize(&L);
   } else {      /* Light is the position of the light source */
-    inflight = 0;
     L.x = -0.2;
     L.y = -0.4;
     L.z =  1;
@@ -650,6 +648,102 @@ i_watermark(i_img *im, i_img *wmark, i_img_dim tx, i_img_dim ty, int pixdiff) {
   }
 }
 
+/*
+=item i_autolevels_mono(im, lsat, usat)
+
+Do autolevels, but monochromatically.
+
+=cut
+*/
+
+void
+i_autolevels_mono(i_img *im, float lsat, float usat) {
+  i_color val;
+  i_img_dim i, x, y, hist[256];
+  i_img_dim sum_lum, min_lum, max_lum;
+  i_img_dim upper_accum, lower_accum;
+  i_color *row;
+  dIMCTXim(im);
+  int adapt_channels = im->channels == 4 ? 2 : 1;
+  int color_channels = i_img_color_channels(im);
+  i_img_dim color_samples = im->xsize * color_channels;
+  
+
+  im_log((aIMCTX, 1,"i_autolevels_mono(im %p, lsat %f,usat %f)\n", im, lsat,usat));
+
+  /* build the histogram in 8-bits, unless the image has a very small
+     range it should make little difference to the result */
+  sum_lum = 0;
+  for (i = 0; i < 256; i++)
+    hist[i] = 0;
+
+  row = mymalloc(im->xsize * sizeof(i_color));
+  /* create histogram for each channel */
+  for (y = 0; y < im->ysize; y++) {
+    i_color *p = row;
+    i_glin(im, 0, im->xsize, y, row);
+    if (im->channels > 2)
+      i_adapt_colors(adapt_channels, im->channels, row, im->xsize);
+    for (x = 0; x < im->xsize; x++) {
+      hist[p->channel[0]]++;
+      ++p;
+    }
+  }
+  myfree(row);
+
+  for(i = 0; i < 256; i++) {
+    sum_lum += hist[i];
+  }
+  
+  min_lum = 0;
+  lower_accum = 0;
+  for (i = 0; i < 256; ++i) {
+    if (lower_accum < sum_lum * lsat)
+      min_lum = i;
+    lower_accum += hist[i];
+  }
+
+  max_lum = 255;
+  upper_accum = 0;
+  for(i = 255; i >= 0; i--) {
+    if (upper_accum < sum_lum * usat)
+      max_lum = i;
+    upper_accum  += hist[i];
+  }
+
+#code im->bits <= 8
+  IM_SAMPLE_T *srow = mymalloc(color_samples * sizeof(IM_SAMPLE_T));
+#ifdef IM_EIGHT_BIT
+  IM_WORK_T low = min_lum;
+  i_sample_t lookup[256];
+#else
+  IM_WORK_T low = min_lum / 255.0 * IM_SAMPLE_MAX;
+#endif
+  double scale = 255.0 / (max_lum - min_lum);
+
+#ifdef IM_EIGHT_BIT
+  for (i = 0; i < 256; ++i) {
+    IM_WORK_T tmp = (i - low) * scale;
+    lookup[i] = IM_LIMIT(tmp);
+  }
+#endif
+
+  for(y = 0; y < im->ysize; y++) {
+    IM_GSAMP(im, 0, im->xsize, y, srow, NULL, color_channels);
+    for(i = 0; i < color_samples; ++i) {
+#ifdef IM_EIGHT_BIT
+      srow[i] = lookup[srow[i]];
+#else
+      IM_WORK_T tmp = (srow[i] - low) * scale;
+      srow[i] = IM_LIMIT(tmp);
+#endif
+    }
+    IM_PSAMP(im, 0, im->xsize, y, srow, NULL, color_channels);
+  }
+  myfree(srow);
+#/code
+}
+
 
 /*
 =item i_autolevels(im, lsat, usat, skew)
@@ -663,6 +757,9 @@ occur when changing the contrast.
   usat - fraction of pixels that will be truncated at the higher end of the spectrum
   skew - not used yet
 
+Note: this code calculates levels and adjusts each channel separately,
+which will typically cause a color shift.
+
 =cut
 */
 
@@ -1236,6 +1333,10 @@ i_nearest_color(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *oval,
 
   i_nearest_color_foo(im, num, xo, yo, ival, dmeasure);
 
+  myfree(cmatch);
+  myfree(ival);
+  myfree(tval);
+
   return 1;
 }
 
@@ -1650,7 +1751,6 @@ i_fountain(i_img *im, double xa, double ya, double xb, double yb,
   i_fcolor *line = NULL;
   i_fcolor *work = NULL;
   size_t line_bytes;
-  i_fountain_seg *my_segs;
   i_fill_combine_f combine_func = NULL;
   i_fill_combinef_f combinef_func = NULL;
   dIMCTXim(im);
@@ -1668,12 +1768,12 @@ i_fountain(i_img *im, double xa, double ya, double xb, double yb,
   line = mymalloc(line_bytes); /* checked 17feb2005 tonyc */
 
   i_get_combine(combine, &combine_func, &combinef_func);
-  if (combinef_func)
+  if (combinef_func) {
     work = mymalloc(line_bytes); /* checked 17feb2005 tonyc */
+  }
 
   fount_init_state(&state, xa, ya, xb, yb, type, repeat, combine, 
                    super_sample, ssample_param, count, segs);
-  my_segs = state.segs;
 
   for (y = 0; y < im->ysize; ++y) {
     i_glinf(im, 0, im->xsize, y, line);
@@ -1685,18 +1785,18 @@ i_fountain(i_img *im, double xa, double ya, double xb, double yb,
       else
         got_one = state.ssfunc(&c, x, y, &state);
       if (got_one) {
-        if (combine)
+        if (combinef_func)
           work[x] = c;
         else 
           line[x] = c;
       }
     }
-    if (combine)
+    if (combinef_func)
       combinef_func(line, work, im->channels, im->xsize);
     i_plinf(im, 0, im->xsize, y, line);
   }
   fount_finish_state(&state);
-  if (work) myfree(work);
+  myfree(work);
   myfree(line);
 
   return 1;
@@ -1872,11 +1972,13 @@ fount_init_state(struct fount_state *state, double xa, double ya,
   case i_fts_random:
   case i_fts_circle:
     ssample_param = floor(0.5+ssample_param);
-    bytes = sizeof(i_fcolor) * ssample_param;
-    if (bytes / sizeof(i_fcolor) == ssample_param) {
-      state->ssample_data = mymalloc(sizeof(i_fcolor) * ssample_param);
+    if (im_size_t_max / sizeof(i_fcolor) > ssample_param) {
+      bytes = sizeof(i_fcolor) * ssample_param;
+      state->ssample_data = mymalloc(bytes);
     }
     else {
+      dIMCTX;
+      im_log((aIMCTX, 1,"size_t overflow calculating super-sample array size for random or circl"));
       super_sample = i_fts_none;
     }
     break;
@@ -2358,8 +2460,9 @@ fill_fountf(i_fill_t *fill, i_img_dim x, i_img_dim y, i_img_dim width,
       got_one = f->state.ssfunc(&c, x, y, &f->state);
     else
       got_one = fount_getat(&c, x, y, &f->state);
-    
-    *data++ = c;
+
+    if (got_one)
+      *data++ = c;
     
     ++x;
   }