Update of /cvsroot/ufraw/ufraw In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv13176
Modified Files: ufraw_ufraw.c Log Message: Fix bug #373: CA correction removes red, blue from bottom 2-3 rows of image, adds large amounts of noise. Index: ufraw_ufraw.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_ufraw.c,v retrieving revision 1.285 retrieving revision 1.286 diff -u -d -r1.285 -r1.286 --- ufraw_ufraw.c 9 Feb 2015 16:30:14 -0000 1.285 +++ ufraw_ufraw.c 11 Feb 2015 07:00:16 -0000 1.286 @@ -867,6 +867,94 @@ } #endif +/* + ufraw_interpolate_pixel_linearly() + Interpolate a new pixel value, for one or all colors, from a 2x2 pixel + patch around coordinates x and y in the image, and write it to dst. +*/ +/* + Because integer arithmetic is faster than floating point operations, + on popular CISC architectures, we cast floats to 32 bit integers, + scaling them first will maintain sufficient precision. +*/ +#define SCALAR 256 + +static inline void ufraw_interpolate_pixel_linearly(ufraw_image_data *image, float x, float y, ufraw_image_type *dst, int color) +{ + + int i, j, c, cmax, xx, yy; + unsigned int dx, dy, v, weights[2][2]; + ufraw_image_type *src; + + /* + When casting a float to an integer it will be rounded toward zero, + that will cause problems when x or y is negative (along the top and + left border) so, we add 2 and subtract that later, using floor() + and round() is much slower. + */ + x += 2; + y += 2; + + xx = x; + yy = y; + + /* + Calculate weights for every pixel in the patch using the fractional + part of the coordinates. + */ + dx = (int)(x * SCALAR + 0.5) - (xx * SCALAR); + dy = (int)(y * SCALAR + 0.5) - (yy * SCALAR); + + weights[0][0] = (SCALAR - dy) * (SCALAR - dx); + weights[0][1] = (SCALAR - dy) * dx; + weights[1][0] = dy * (SCALAR - dx); + weights[1][1] = dy * dx; + + xx -= 2; + yy -= 2; + + src = (ufraw_image_type *)image->buffer + yy * image->width + xx; + + /* If an existing color number is given, then only that color will be interpolated, else all will be. */ + if (color < 0 || color >= (3 + (image->rgbg == TRUE))) + c = 0, cmax = 2 + (image->rgbg == TRUE); + else + c = cmax = color; + + /* Check if the source pixels are near a border, if they aren't we can use faster code. */ + if (xx >= 0 && yy >= 0 && xx + 1 < image->width && yy + 1 < image->height) { + + for (; c <= cmax ; c++) { + + v = 0; + + for (i = 0 ; i < 2 ; i++) + for (j = 0 ; j < 2 ; j++) + v += weights[i][j] * src[i * image->width + j][c]; + + dst[0][c] = v / (SCALAR * SCALAR); + } + + } else { /* Near a border. */ + + for (; c <= cmax ; c++) { + + v = 0; + + for (i = 0 ; i < 2 ; i++) + for (j = 0 ; j < 2 ; j++) + /* Check if the source pixel lies inside the image */ + if (xx + j >= 0 && yy + i >= 0 && xx + j < image->width && yy + i < image->height) + v += weights[i][j] * src[i * image->width + j][c]; + + dst[0][c] = v / (SCALAR * SCALAR); + } + } +} + +#undef SCALAR + + /* Apply distortion, geometry and rotation in a single pass */ static void ufraw_convert_image_transform(ufraw_data *uf, ufraw_image_data *img, ufraw_image_data *outimg, UFRectangle *area) @@ -886,7 +974,7 @@ #ifdef HAVE_LENSFUN gboolean applyLF = uf->modifier != NULL && (uf->modFlags & UF_LF_TRANSFORM); #endif - int x, y, c; + int x, y; for (y = area->y; y < area->y + area->height; y++) { guint8 *cur0 = outimg->buffer + y * outimg->rowstride; float srcX0 = y * sine + baseX; @@ -904,22 +992,7 @@ srcY = buff[1]; } #endif - gint32 xx = (gint32)srcX; - gint32 yy = (gint32)srcY; - // TODO: better handling of the borders. - if (xx < 0 || yy < 0 || xx + 1 >= img->width || yy + 1 >= img->height) { - for (c = 0; c < uf->colors; c++) - cur[c] = 0; - continue; - } - ufraw_image_type *src = (ufraw_image_type *)(img->buffer + - yy * img->rowstride + xx * img->depth); - guint64 dx = (gint32)(srcX * 4096.0) - (xx << 12); - guint64 dy = (gint32)(srcY * 4096.0) - (yy << 12); - for (c = 0; c < uf->colors; c++) - cur[c] = ((4096 - dy) * ((4096 - dx) * src[0][c] + dx * src[1][c]) - + dy * ((4096 - dx) * src[img->width][c] - + (dx) * src[img->width + 1][c])) >> 24; + ufraw_interpolate_pixel_linearly(img, srcX, srcY, (ufraw_image_type *)cur, -1); } } } @@ -1318,26 +1391,9 @@ for (; src < srcEnd; src++, dst += outimg->depth / 2) { int c; // Only red and blue channels get corrected - for (c = 0; c <= 2; c += 2, modcoord += 4) { - float srcX = modcoord[0]; - float srcY = modcoord[1]; - /* Do it in integer arithmetic, it's faster */ - int xx = (int)srcX; - int yy = (int)srcY; - // TODO: better handling of the borders. - if (xx < 0 || yy < 0 || xx + 1 >= img->width || yy + 1 >= img->height) { - dst[c] = 0; - continue; - } - ufraw_image_type *lf_src = (ufraw_image_type *)(img->buffer + - yy * img->rowstride + xx * img->depth); - guint64 dx = (int)(srcX * 4096.0) - (xx << 12); - guint64 dy = (int)(srcY * 4096.0) - (yy << 12); - dst[c] = ((4096 - dy) * ((4096 - dx) * lf_src[0][c] - + dx * lf_src[1][c]) - + dy * ((4096 - dx) * lf_src[img->width][c] - + (dx) * lf_src[img->width + 1][c])) >> 24; - } + for (c = 0; c <= 2; c += 2, modcoord += 4) + ufraw_interpolate_pixel_linearly(img, modcoord[0], modcoord[1], (ufraw_image_type *)dst, c); + modcoord -= 2; // Green channels are intact for (c = 1; c <= 3; c += 2) ------------------------------------------------------------------------------ Dive into the World of Parallel Programming. The Go Parallel Website, sponsored by Intel and developed in partnership with Slashdot Media, is your hub for all things parallel software development, from weekly thought leadership blogs to news, videos, case studies, tutorials and more. Take a look and join the conversation now. http://goparallel.sourceforge.net/ _______________________________________________ ufraw-cvs mailing list ufraw-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ufraw-cvs