X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/d17ee71782853db5969e70999cfe0a17d9a30c12..c5e09af4359bc56ec00feeda9c6cfa686f59f0d2:/filters.im diff --git a/filters.im b/filters.im index 6f36a0fe..e247c9cc 100644 --- a/filters.im +++ b/filters.im @@ -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 */ @@ -972,7 +1069,7 @@ i_gradgen(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *ival, int d fdist[p] = i_max(xd*xd, yd*yd); /* manhattan distance */ break; default: - i_fatal(3,"i_gradgen: Unknown distance measure\n"); + im_fatal(aIMCTX, 3,"i_gradgen: Unknown distance measure\n"); } cs += fdist[p]; } @@ -1027,7 +1124,7 @@ i_nearest_color_foo(i_img *im, int num, i_img_dim *xo, i_img_dim *yo, i_color *i mindist = i_max(xd*xd, yd*yd); /* manhattan distance */ break; default: - i_fatal(3,"i_nearest_color: Unknown distance measure\n"); + im_fatal(aIMCTX, 3,"i_nearest_color: Unknown distance measure\n"); } for(p = 1; pysize; ++y) { i_glinf(im, 0, im->xsize, y, line); @@ -2358,8 +2457,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; }