From: Udi F. <udi...@us...> - 2007-09-22 18:45:11
|
Update of /cvsroot/ufraw/ufraw In directory sc8-pr-cvs8.sourceforge.net:/tmp/cvs-serv6925 Modified Files: dcraw_api.cc dcraw_api.h ufraw_ufraw.c Log Message: Move darkframe subtraction code to dcraw_api.h (patch by Bruce Guenter). Index: dcraw_api.h =================================================================== RCS file: /cvsroot/ufraw/ufraw/dcraw_api.h,v retrieving revision 1.25 retrieving revision 1.26 diff -u -d -r1.25 -r1.26 --- dcraw_api.h 28 Jul 2007 20:22:20 -0000 1.25 +++ dcraw_api.h 22 Sep 2007 18:45:07 -0000 1.26 @@ -34,6 +34,7 @@ int flip, shrink; double pixel_aspect; dcraw_image_data raw; + dcraw_image_type thresholds; float pre_mul[4], post_mul[4], cam_mul[4], rgb_cam[3][4]; double cam_rgb[4][3]; int rgbMax, black, fuji_width; @@ -54,7 +55,8 @@ int dcraw_open(dcraw_data *h, char *filename); int dcraw_load_raw(dcraw_data *h); int dcraw_load_thumb(dcraw_data *h, dcraw_image_data *thumb); -int dcraw_finalize_shrink(dcraw_image_data *f, dcraw_data *h, int scale); +int dcraw_finalize_shrink(dcraw_image_data *f, dcraw_data *h, + dcraw_data *dark, int scale); int dcraw_image_resize(dcraw_image_data *image, int size); int dcraw_image_stretch(dcraw_image_data *image, double pixel_aspect); int dcraw_flip_image(dcraw_image_data *image, int flip); @@ -63,7 +65,7 @@ int dcraw_wavelet_denoise_shrinked(dcraw_image_data *f, dcraw_data *h, float threshold); int dcraw_finalize_interpolate(dcraw_image_data *f, dcraw_data *h, - int interpolation, int rgbWB[4]); + dcraw_data *dark, int interpolation, int rgbWB[4]); void dcraw_close(dcraw_data *h); int dcraw_image_dimensions(dcraw_data *raw, int flip, int *height, int *width); Index: ufraw_ufraw.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_ufraw.c,v retrieving revision 1.114 retrieving revision 1.115 diff -u -d -r1.114 -r1.115 --- ufraw_ufraw.c 20 Sep 2007 23:02:40 -0000 1.114 +++ ufraw_ufraw.c 22 Sep 2007 18:45:07 -0000 1.115 @@ -459,92 +459,6 @@ return UFRAW_SUCCESS; } -/* Calculate dark frame hot pixel thresholds as the 99.99th percentile - * value. That is, the value at which 99.99% of the pixels are darker. - * Pixels below this threshold are considered to be bias noise, and - * those above are "hot". */ -static void calc_thresholds(dcraw_image_type thresholds, - const dcraw_image_data *img) -{ - int color; - int i; - long frequency[65536]; - long sum; - long point = img->width * img->height / 10000; - - for (color = 0; color < img->colors; ++color) { - memset(frequency, 0, sizeof frequency); - for (i = 0; i < img->width * img->height; ++i) - frequency[img->image[i][color]]++; - for (sum = 0, i = 65535; i > 1; --i) { - sum += frequency[i]; - if (sum >= point) - break; - } - thresholds[color] = i + 1; - } -} - -/* Remove dark frame noise from the original image. The most obvious - * algorithm here is to simply subtract the dark frame from the image - * (rounding negative values to zero). However, this leaves holes in - * the resulting image that need to be interpolated from the surrounding - * pixels. - * - * The processing works by subtracting the dark frame as usual, but then - * a second pass is made over the processed data. For any pixels where - * the dark frame value is above the threshold calculated above, the - * output pixel is interpolated from the 4 surrounding pixels. By this - * method, only hot pixels (as determined by the threshold) are examined - * and recalculated. - */ -static void ufraw_subtract_darkframe(ufraw_data *uf) -{ - dcraw_data *df = uf->conf->darkframe->raw; - dcraw_data *org = uf->raw; - int i, cl; - int pixels; - dcraw_image_type *orgimage = org->raw.image; - dcraw_image_type *dfimage = df->raw.image; - dcraw_image_type thresholds; - int width = org->raw.width; - - if (org->raw.width!=df->raw.width && - org->raw.height!=df->raw.height && - org->raw.colors!=df->raw.colors){ - - ufraw_message(UFRAW_SET_WARNING, - _("Darkframe is incompatible with main image")); - return; - } - pixels = org->raw.height * org->raw.width; - for( i=0; i<pixels; i++ ) { - for( cl=0; cl<org->raw.colors; cl++ ) { - orgimage[i][cl] = (orgimage[i][cl] >= dfimage[i][cl]) - ? (orgimage[i][cl] - dfimage[i][cl]) - : 0; - } - } - /* Try to eliminate black spots left by subtracting out hot pixels. */ - calc_thresholds(thresholds, &df->raw); - for( i=0; i<pixels; i++ ) { - for( cl=0; cl<org->raw.colors; cl++ ) { - if (dfimage[i][cl] > thresholds[cl]) - orgimage[i][cl] = - (orgimage[i + ((i >= 1) ? -1 : 1)][cl] + - orgimage[i + ((i < pixels-1) ? 1 : -1)][cl] + - orgimage[i + ((i >= width) ? -width : width)][cl] + - orgimage[i + ((i < pixels-width) ? width : -width)][cl]) - / 4; - } - } - org->black = org->black >= df->black ? - org->black - df->black : - 0; - ufraw_message(UFRAW_SET_LOG, "subtracted darkframe '%s'\n", - uf->conf->darkframeFile); -} - int ufraw_load_raw(ufraw_data *uf) { int status; @@ -565,11 +479,7 @@ ufraw_message(status, raw->message); if (status!=DCRAW_WARNING) return status; } - /* raw->black can change in ufraw_subtract_darkframe() so we must - * calculate uf->rgbMax first */ uf->rgbMax = raw->rgbMax - raw->black; - if (uf->conf->darkframe!=NULL) - ufraw_subtract_darkframe(uf); memcpy(uf->rgb_cam, raw->rgb_cam, sizeof uf->rgb_cam); /* Canon EOS cameras require special exposure normalization */ @@ -697,7 +607,9 @@ dcraw_image_data final; if ( uf->ConvertShrink>1 || !uf->HaveFilters ) { - dcraw_finalize_shrink(&final, raw, uf->ConvertShrink); + dcraw_finalize_shrink(&final, raw, + uf->conf->darkframe ? uf->conf->darkframe->raw : 0, + uf->ConvertShrink); uf->image.height = final.height; uf->image.width = final.width; @@ -707,8 +619,9 @@ if ( (status=dcraw_wavelet_denoise(raw, uf->conf->threshold))!=DCRAW_SUCCESS ) return status; - dcraw_finalize_interpolate(&final, raw, uf->conf->interpolation, - uf->developer->rgbWB); + dcraw_finalize_interpolate(&final, raw, + uf->conf->darkframe ? uf->conf->darkframe->raw : 0, + uf->conf->interpolation, uf->developer->rgbWB); uf->developer->rgbMax = uf->developer->max; for (c=0; c<4; c++) uf->developer->rgbWB[c] = 0x10000; Index: dcraw_api.cc =================================================================== RCS file: /cvsroot/ufraw/ufraw/dcraw_api.cc,v retrieving revision 1.28 retrieving revision 1.29 diff -u -d -r1.28 -r1.29 --- dcraw_api.cc 17 Sep 2007 22:10:21 -0000 1.28 +++ dcraw_api.cc 22 Sep 2007 18:45:07 -0000 1.29 @@ -177,6 +177,32 @@ return DCRAW_SUCCESS; } +/* Calculate dark frame hot pixel thresholds as the 99.99th percentile + * value. That is, the value at which 99.99% of the pixels are darker. + * Pixels below this threshold are considered to be bias noise, and + * those above are "hot". */ +static void calc_thresholds(dcraw_image_type thresholds, + const dcraw_image_data *img) +{ + int color; + int i; + long frequency[65536]; + long sum; + long point = img->width * img->height / 10000; + + for (color = 0; color < img->colors; ++color) { + memset(frequency, 0, sizeof frequency); + for (i = 0; i < img->width * img->height; ++i) + frequency[img->image[i][color]]++; + for (sum = 0, i = 65535; i > 1; --i) { + sum += frequency[i]; + if (sum >= point) + break; + } + thresholds[color] = i + 1; + } +} + int dcraw_load_raw(dcraw_data *h) { DCRaw *d = (DCRaw *)h->dcraw; @@ -234,6 +260,7 @@ for (i=0; i<4; i++) for (j=0; j<3; j++) rgb_cam_transpose[i][j] = d->rgb_cam[j][i]; d->pseudoinverse (rgb_cam_transpose, h->cam_rgb, d->colors); + calc_thresholds(h->thresholds, &h->raw); h->message = d->messageBuffer; return d->lastStatus; @@ -270,15 +297,55 @@ return d->lastStatus; } -int dcraw_finalize_shrink(dcraw_image_data *f, dcraw_data *hh, int scale) +/* Grab a pixel from the raw data, doing dark frame removal on the fly. + * + * The most obvious algorithm for dark frame removal is to simply + * subtract the dark frame from the image (rounding negative values to + * zero). However, this leaves holes in the resulting image that need + * to be interpolated from the surrounding pixels. + * + * The processing works by subtracting the dark frame as usual for most + * pixels. For all pixels where the dark frame is brighter than a given + * threshold, the result is instead calculated as the average of the + * dark-adjusted values of the 4 surrounding pixels. By this method, + * only hot pixels (as determined by the threshold) are examined and + * recalculated. + */ +static int get_dark_pixel(const dcraw_data *h, const dcraw_data *dark, + int i, int cl) +{ + return MAX(h->raw.image[i][cl] - dark->raw.image[i][cl], 0); +} + +static int get_pixel(const dcraw_data *h, const dcraw_data *dark, + int r, int c, int cl, int pixels) +{ + int i = r * h->raw.width + c; + int pixel = h->raw.image[i][cl]; + if (dark != 0) { + int w = h->raw.width; + pixel = (dark->raw.image[i][cl] <= dark->thresholds[cl]) + ? MAX(pixel - dark->raw.image[i][cl], 0) + : (get_dark_pixel(h, dark, i + ((i >= 1) ? -1 : 1), cl) + + get_dark_pixel(h, dark, i + ((i < pixels-1) ? 1 : -1), cl) + + get_dark_pixel(h, dark, i + ((i >= w) ? -w : w), cl) + + get_dark_pixel(h, dark, i + ((i < pixels-w) ? w : -w), cl)) + / 4; + } + return pixel; +} + +int dcraw_finalize_shrink(dcraw_image_data *f, dcraw_data *hh, + dcraw_data *dark, int scale) { DCRaw *d = (DCRaw *)hh->dcraw; - int h, w, fujiWidth, r, c, ri, ci, cl, norm, s, recombine; + int h, w, fujiWidth, r, c, ri, ci, cl, norm, s, recombine, pixels; int f4, sum[4], count[4]; g_free(d->messageBuffer); d->messageBuffer = NULL; d->lastStatus = DCRAW_SUCCESS; + pixels = hh->raw.width * hh->raw.height; recombine = ( hh->colors==3 && hh->raw.colors==4 ); f->colors = hh->colors; @@ -298,11 +365,10 @@ for (cl=0; cl<hh->raw.colors; cl++) sum[cl] = count[cl] = 0; for (ri=0; ri<scale; ri++) for (ci=0; ci<scale; ci++) { + cl = fc_INDI(f4, r*scale+ri, c*scale+ci); sum[fc_INDI(f4, r*scale+ri, c*scale+ci)] += - hh->raw.image - [(r*scale+ri)/2*hh->raw.width+(c*scale+ci)/2] - [fc_INDI(f4, r*scale+ri, c*scale+ci)]; - count[fc_INDI(f4, r*scale+ri, c*scale+ci)]++; + get_pixel(hh, dark, r*scale+ri, c*scale+ci, cl, pixels); + count[cl]++; } for (cl=0; cl<hh->raw.colors; cl++) f->image[r*w+c][cl] = @@ -324,8 +390,7 @@ for (cl=0; cl<hh->raw.colors; cl++) { for (ri=0, s=0; ri<scale; ri++) for (ci=0; ci<scale; ci++) - s += hh->raw.image - [(r*scale+ri)*hh->raw.width+c*scale+ci][cl]; + s += get_pixel(hh, dark, r*scale+ri, c*scale+ci, cl, pixels); f->image[r*w+c][cl] = MAX(s/norm - hh->black,0); } if (recombine) f->image[r*w+c][1] = @@ -481,15 +546,16 @@ } int dcraw_finalize_interpolate(dcraw_image_data *f, dcraw_data *h, - int interpolation, int rgbWB[4]) + dcraw_data *dark, int interpolation, int rgbWB[4]) { DCRaw *d = (DCRaw *)h->dcraw; - int fujiWidth, i, r, c, cl; + int fujiWidth, i, r, c, cl, pixels; unsigned ff, f4; g_free(d->messageBuffer); d->messageBuffer = NULL; d->lastStatus = DCRAW_SUCCESS; + pixels = h->raw.width * h->raw.height; f->width = h->width; f->height = h->height; @@ -518,10 +584,12 @@ f4 = h->fourColorFilters; if (h->colors==3) rgbWB[3] = rgbWB[1]; for(r=0; r<h->height; r++) - for(c=0; c<h->width; c++) + for(c=0; c<h->width; c++) { + cl = fc_INDI(f4,r,c); f->image[r*f->width+c][fc_INDI(ff,r,c)] = MIN( MAX( (gint64) - (h->raw.image[r/2*h->raw.width+c/2][fc_INDI(f4,r,c)] - h->black) * - rgbWB[fc_INDI(f4,r,c)]/0x10000, 0), 0xFFFF); + (get_pixel(h, dark, r/2, c/2, cl, pixels) - h->black) * + rgbWB[cl]/0x10000, 0), 0xFFFF); + } if (interpolation==dcraw_bilinear_interpolation) lin_interpolate_INDI(f->image, ff, f->width, f->height, cl, d); |