Update of /cvsroot/ufraw/ufraw In directory sfp-cvs-1.v30.ch3.sourceforge.com:/tmp/cvs-serv5948
Modified Files: README dcraw_api.cc dcraw_api.h dcraw_indi.c ufraw.h ufraw_conf.c ufraw_preview.c Log Message: Use xtrans_interpolate() from DCRaw v9.18 for the FUJIFILM 'X-Trans' sensor. There are still some interpolation artifacts to iron out of this code. Index: dcraw_api.h =================================================================== RCS file: /cvsroot/ufraw/ufraw/dcraw_api.h,v retrieving revision 1.48 retrieving revision 1.49 diff -u -d -r1.48 -r1.49 --- dcraw_api.h 17 Oct 2013 04:30:17 -0000 1.48 +++ dcraw_api.h 17 Oct 2013 08:00:19 -0000 1.49 @@ -52,7 +52,7 @@ enum { dcraw_ahd_interpolation, dcraw_vng_interpolation, dcraw_four_color_interpolation, dcraw_ppg_interpolation, dcraw_bilinear_interpolation, - dcraw_none_interpolation + dcraw_xtrans_interpolation, dcraw_none_interpolation }; enum { unknown_thumb_type, jpeg_thumb_type, ppm_thumb_type }; int dcraw_open(dcraw_data *h, char *filename); Index: dcraw_indi.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/dcraw_indi.c,v retrieving revision 1.112 retrieving revision 1.113 diff -u -d -r1.112 -r1.113 --- dcraw_indi.c 17 Oct 2013 05:15:15 -0000 1.112 +++ dcraw_indi.c 17 Oct 2013 08:00:19 -0000 1.113 @@ -590,6 +590,243 @@ #define TS 512 /* Tile Size */ /* + Frank Markesteijn's algorithm for Fuji X-Trans sensors + */ +void CLASS xtrans_interpolate_INDI(ushort(*image)[4], const unsigned filters, + const int width, const int height, + const int colors, const float rgb_cam[3][4], + void *dcraw, dcraw_data *hh, const int passes) +{ + int c, d, f, g, h, i, v, ng, row, col, top, left, mrow, mcol; + int val, ndir, pass, hm[8], avg[4], color[3][8]; + static const short orth[12] = { 1, 0, 0, 1, -1, 0, 0, -1, 1, 0, 0, 1 }, + patt[2][16] = { { 0, 1, 0, -1, 2, 0, -1, 0, 1, 1, 1, -1, 0, 0, 0, 0 }, + { 0, 1, 0, -2, 1, 0, -2, 0, 1, 1, -2, -2, 1, -1, -1, 1 } + }, + dir[4] = { 1, TS, TS + 1, TS - 1 }; + short allhex[3][3][2][8], *hex; + ushort min, max, sgrow = 0, sgcol = 0; + ushort(*rgb)[TS][TS][3], (*rix)[3], (*pix)[4]; + short(*lab) [TS][3], (*lix)[3]; + float(*drv)[TS][TS], diff[6], tr; + char(*homo)[TS][TS], *buffer; + + dcraw_message(dcraw, DCRAW_VERBOSE, _("%d-pass X-Trans interpolation...\n"), passes); /*NKBJ*/ + + cielab_INDI(0, 0, colors, rgb_cam); + border_interpolate_INDI(height, width, image, filters, colors, 6, hh); + ndir = 4 << (passes > 1); + buffer = (char *) malloc(TS * TS * (ndir * 11 + 6)); + merror(buffer, "xtrans_interpolate()"); + rgb = (ushort(*)[TS][TS][3]) buffer; + lab = (short(*) [TS][3])(buffer + TS * TS * (ndir * 6)); + drv = (float(*)[TS][TS])(buffer + TS * TS * (ndir * 6 + 6)); + homo = (char(*)[TS][TS])(buffer + TS * TS * (ndir * 10 + 6)); + + /* Map a green hexagon around each non-green pixel and vice versa: */ + for (row = 0; row < 3; row++) + for (col = 0; col < 3; col++) + for (ng = d = 0; d < 10; d += 2) { + g = fcol_INDI(filters, row, col, hh->top_margin, hh->left_margin, hh->xtrans) == 1; + if (fcol_INDI(filters, row + orth[d], col + orth[d + 2], hh->top_margin, hh->left_margin, hh->xtrans) == 1) ng = 0; + else ng++; + if (ng == 4) { + sgrow = row; + sgcol = col; + } + if (ng == g + 1) FORC(8) { + v = orth[d ] * patt[g][c * 2] + orth[d + 1] * patt[g][c * 2 + 1]; + h = orth[d + 2] * patt[g][c * 2] + orth[d + 3] * patt[g][c * 2 + 1]; + allhex[row][col][0][c ^(g * 2 & d)] = h + v * width; + allhex[row][col][1][c ^(g * 2 & d)] = h + v * TS; + } + } + + /* Set green1 and green3 to the minimum and maximum allowed values: */ + for (row = 2; row < height - 2; row++) + for (min = ~(max = 0), col = 2; col < width - 2; col++) { + if (fcol_INDI(filters, row, col, hh->top_margin, hh->left_margin, hh->xtrans) == 1 && (min = ~(max = 0))) continue; + pix = image + row * width + col; + hex = allhex[row % 3][col % 3][0]; + if (!max) FORC(6) { + val = pix[hex[c]][1]; + if (min > val) min = val; + if (max < val) max = val; + } + pix[0][1] = min; + pix[0][3] = max; + switch ((row - sgrow) % 3) { + case 1: + if (row < height - 3) { + row++; + col--; + } + break; + case 2: + if ((min = ~(max = 0)) && (col += 2) < width - 3 && row > 2) row--; + } + } + + for (top = 3; top < height - 19; top += TS - 16) + for (left = 3; left < width - 19; left += TS - 16) { + mrow = MIN(top + TS, height - 3); + mcol = MIN(left + TS, width - 3); + for (row = top; row < mrow; row++) + for (col = left; col < mcol; col++) + memcpy(rgb[0][row - top][col - left], image[row * width + col], 6); + FORC3 memcpy(rgb[c + 1], rgb[0], sizeof * rgb); + + /* Interpolate green horizontally, vertically, and along both diagonals: */ + for (row = top; row < mrow; row++) + for (col = left; col < mcol; col++) { + if ((f = fcol_INDI(filters, row, col, hh->top_margin, hh->left_margin, hh->xtrans)) == 1) continue; + pix = image + row * width + col; + hex = allhex[row % 3][col % 3][0]; + color[1][0] = 174 * (pix[ hex[1]][1] + pix[ hex[0]][1]) - + 46 * (pix[2 * hex[1]][1] + pix[2 * hex[0]][1]); + color[1][1] = 223 * pix[ hex[3]][1] + pix[ hex[2]][1] * 33 + + 92 * (pix[ 0 ][f] - pix[ -hex[2]][f]); + FORC(2) color[1][2 + c] = + 164 * pix[hex[4 + c]][1] + 92 * pix[-2 * hex[4 + c]][1] + 33 * + (2 * pix[0][f] - pix[3 * hex[4 + c]][f] - pix[-3 * hex[4 + c]][f]); + FORC4 rgb[c ^ !((row - sgrow) % 3)][row - top][col - left][1] = + LIM(color[1][c] >> 8, pix[0][1], pix[0][3]); + } + + for (pass = 0; pass < passes; pass++) { + if (pass == 1) + memcpy(rgb += 4, buffer, 4 * sizeof * rgb); + + /* Recalculate green from interpolated values of closer pixels: */ + if (pass) { + for (row = top + 2; row < mrow - 2; row++) + for (col = left + 2; col < mcol - 2; col++) { + if ((f = fcol_INDI(filters, row, col, hh->top_margin, hh->left_margin, hh->xtrans)) == 1) continue; + pix = image + row * width + col; + hex = allhex[row % 3][col % 3][1]; + for (d = 3; d < 6; d++) { + rix = &rgb[(d - 2) ^ !((row - sgrow) % 3)][row - top][col - left]; + val = rix[-2 * hex[d]][1] + 2 * rix[hex[d]][1] + - rix[-2 * hex[d]][f] - 2 * rix[hex[d]][f] + 3 * rix[0][f]; + rix[0][1] = LIM(val / 3, pix[0][1], pix[0][3]); + } + } + } + + /* Interpolate red and blue values for solitary green pixels: */ + for (row = (top - sgrow + 4) / 3 * 3 + sgrow; row < mrow - 2; row += 3) + for (col = (left - sgcol + 4) / 3 * 3 + sgcol; col < mcol - 2; col += 3) { + rix = &rgb[0][row - top][col - left]; + h = fcol_INDI(filters, row, col + 1, hh->top_margin, hh->left_margin, hh->xtrans); + memset(diff, 0, sizeof diff); + for (i = 1, d = 0; d < 6; d++, i ^= TS ^ 1, h ^= 2) { + for (c = 0; c < 2; c++, h ^= 2) { + g = 2 * rix[0][1] - rix[i << c][1] - rix[-i << c][1]; + color[h][d] = g + rix[i << c][h] + rix[-i << c][h]; + if (d > 1) + diff[d] += SQR(rix[i << c][1] - rix[-i << c][1] + - rix[i << c][h] + rix[-i << c][h]) + SQR(g); + } + if (d > 1 && (d & 1)) + if (diff[d - 1] < diff[d]) + FORC(2) color[c * 2][d] = color[c * 2][d - 1]; + if (d < 2 || (d & 1)) { + FORC(2) rix[0][c * 2] = CLIP(color[c * 2][d] / 2); + rix += TS * TS; + } + } + } + + /* Interpolate red for blue pixels and vice versa: */ + for (row = top + 1; row < mrow - 1; row++) + for (col = left + 1; col < mcol - 1; col++) { + if ((f = 2 - fcol_INDI(filters, row, col, hh->top_margin, hh->left_margin, hh->xtrans)) == 1) continue; + rix = &rgb[0][row - top][col - left]; + i = (row - sgrow) % 3 ? TS : 1; + for (d = 0; d < 4; d++, rix += TS * TS) + rix[0][f] = CLIP((rix[i][f] + rix[-i][f] + + 2 * rix[0][1] - rix[i][1] - rix[-i][1]) / 2); + } + + /* Fill in red and blue for 2x2 blocks of green: */ + for (row = top + 2; row < mrow - 2; row++) if ((row - sgrow) % 3) + for (col = left + 2; col < mcol - 2; col++) if ((col - sgcol) % 3) { + rix = &rgb[0][row - top][col - left]; + hex = allhex[row % 3][col % 3][1]; + for (d = 0; d < ndir; d += 2, rix += TS * TS) + if (hex[d] + hex[d + 1]) { + g = 3 * rix[0][1] - 2 * rix[hex[d]][1] - rix[hex[d + 1]][1]; + for (c = 0; c < 4; c += 2) rix[0][c] = + CLIP((g + 2 * rix[hex[d]][c] + rix[hex[d + 1]][c]) / 3); + } else { + g = 2 * rix[0][1] - rix[hex[d]][1] - rix[hex[d + 1]][1]; + for (c = 0; c < 4; c += 2) rix[0][c] = + CLIP((g + rix[hex[d]][c] + rix[hex[d + 1]][c]) / 2); + } + } + } + rgb = (ushort(*)[TS][TS][3]) buffer; + mrow -= top; + mcol -= left; + + /* Convert to CIELab and differentiate in all directions: */ + for (d = 0; d < ndir; d++) { + for (row = 2; row < mrow - 2; row++) + for (col = 2; col < mcol - 2; col++) + cielab_INDI(rgb[d][row][col], lab[row][col], colors, rgb_cam); + for (f = dir[d & 3], row = 3; row < mrow - 3; row++) + for (col = 3; col < mcol - 3; col++) { + lix = &lab[row][col]; + g = 2 * lix[0][0] - lix[f][0] - lix[-f][0]; + drv[d][row][col] = SQR(g) + + SQR((2 * lix[0][1] - lix[f][1] - lix[-f][1] + g * 500 / 232)) + + SQR((2 * lix[0][2] - lix[f][2] - lix[-f][2] - g * 500 / 580)); + } + } + + /* Build homogeneity maps from the derivatives: */ + memset(homo, 0, ndir * TS * TS); + for (row = 4; row < mrow - 4; row++) + for (col = 4; col < mcol - 4; col++) { + for (tr = FLT_MAX, d = 0; d < ndir; d++) + if (tr > drv[d][row][col]) + tr = drv[d][row][col]; + tr *= 8; + for (d = 0; d < ndir; d++) + for (v = -1; v <= 1; v++) + for (h = -1; h <= 1; h++) + if (drv[d][row + v][col + h] <= tr) + homo[d][row][col]++; + } + + /* Average the most homogenous pixels for the final result: */ + if (height - top < TS + 4) mrow = height - top + 2; + if (width - left < TS + 4) mcol = width - left + 2; + for (row = MIN(top, 8); row < mrow - 8; row++) + for (col = MIN(left, 8); col < mcol - 8; col++) { + for (d = 0; d < ndir; d++) + for (hm[d] = 0, v = -2; v <= 2; v++) + for (h = -2; h <= 2; h++) + hm[d] += homo[d][row + v][col + h]; + for (d = 0; d < ndir - 4; d++) + if (hm[d] < hm[d + 4]) hm[d ] = 0; + else if (hm[d] > hm[d + 4]) hm[d + 4] = 0; + for (max = hm[0], d = 1; d < ndir; d++) + if (max < hm[d]) max = hm[d]; + max -= max >> 3; + memset(avg, 0, sizeof avg); + for (d = 0; d < ndir; d++) + if (hm[d] >= max) { + FORC3 avg[c] += rgb[d][row][col][c]; + avg[3]++; + } + FORC3 image[(row + top)*width + col + left][c] = avg[c] / avg[3]; + } + } + free(buffer); +} + +/* Adaptive Homogeneity-Directed interpolation is based on the work of Keigo Hirakawa, Thomas Parks, and Paul Lee. */ Index: README =================================================================== RCS file: /cvsroot/ufraw/ufraw/README,v retrieving revision 1.71 retrieving revision 1.72 diff -u -d -r1.71 -r1.72 --- README 17 Oct 2013 05:15:15 -0000 1.71 +++ README 17 Oct 2013 08:00:19 -0000 1.72 @@ -264,9 +264,9 @@ if there are new global variables or functions and add them to dcraw.h. One should also check if there where changes to the functions hat_transform(), wavelet_denoise(), scale_colors(), pre_interpolate(), border_interpolate(), -lin_interpolate(), vng_interpolate(), ppg_interpolate(), ahd_interpolate(), -cielab(), convert_to_rgb(), fuji_rotate() or main(). Such changes could affect -dcraw_indi.c or dcraw_api.cc. +lin_interpolate(), vng_interpolate(), ppg_interpolate(), cielab(), +xtrans_interpolate(), ahd_interpolate(), convert_to_rgb(), fuji_rotate() or +main(). Such changes could affect dcraw_indi.c or dcraw_api.cc. For Packagers ============= Index: ufraw_preview.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_preview.c,v retrieving revision 1.371 retrieving revision 1.372 diff -u -d -r1.371 -r1.372 --- ufraw_preview.c 17 Oct 2013 05:30:15 -0000 1.371 +++ ufraw_preview.c 17 Oct 2013 08:00:20 -0000 1.372 @@ -4423,6 +4423,8 @@ combo = GTK_COMBO_BOX(uf_combo_box_new_text()); if (data->UF->HaveFilters) { if (data->UF->IsXTrans) { + uf_combo_box_append_text(combo, _("X-Trans interpolation"), + (void*)xtrans_interpolation); uf_combo_box_append_text(combo, _("Bilinear interpolation"), (void*)bilinear_interpolation); } else if (data->UF->colors == 4) { Index: ufraw_conf.c =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw_conf.c,v retrieving revision 1.194 retrieving revision 1.195 diff -u -d -r1.194 -r1.195 --- ufraw_conf.c 16 Oct 2013 03:30:09 -0000 1.194 +++ ufraw_conf.c 17 Oct 2013 08:00:20 -0000 1.195 @@ -150,8 +150,10 @@ "", "", /* real_make, real_model */ }; -static const char *interpolationNames[] = -{ "ahd", "vng", "four-color", "ppg", "bilinear", "none", "half", "eahd", NULL }; +static const char *interpolationNames[] = { + "ahd", "vng", "four-color", "ppg", "bilinear", "xtrans", "none", "half", + "eahd", NULL +}; static const char *restoreDetailsNames[] = { "clip", "lch", "hsv", NULL }; static const char *clipHighlightsNames[] = Index: dcraw_api.cc =================================================================== RCS file: /cvsroot/ufraw/ufraw/dcraw_api.cc,v retrieving revision 1.92 retrieving revision 1.93 diff -u -d -r1.92 -r1.93 --- dcraw_api.cc 17 Oct 2013 04:30:17 -0000 1.92 +++ dcraw_api.cc 17 Oct 2013 08:00:19 -0000 1.93 @@ -52,6 +52,10 @@ void vng_interpolate_INDI(gushort(*image)[4], const unsigned filters, const int width, const int height, const int colors, const int rgb_max, void *dcraw, dcraw_data *h); + void xtrans_interpolate_INDI(ushort(*image)[4], const unsigned filters, + const int width, const int height, + const int colors, const float rgb_cam[3][4], + void *dcraw, dcraw_data *hh, const int passes); void ahd_interpolate_INDI(gushort(*image)[4], const unsigned filters, const int width, const int height, const int colors, float rgb_cam[3][4], void *dcraw, dcraw_data *h); @@ -728,7 +732,7 @@ /* It might be better to report an error here: */ /* (dcraw also forbids AHD for Fuji rotated images) */ if (h->filters == 9) - interpolation = dcraw_bilinear_interpolation; + interpolation = dcraw_xtrans_interpolation; if (interpolation == dcraw_ahd_interpolation && h->colors > 3) interpolation = dcraw_vng_interpolation; if (interpolation == dcraw_ppg_interpolation && h->colors > 3) @@ -747,15 +751,20 @@ else if (interpolation == dcraw_none_interpolation) smoothing = 0; #endif - else if (interpolation == dcraw_vng_interpolation) + else if (interpolation == dcraw_vng_interpolation || h->colors > 3) vng_interpolate_INDI(f->image, ff, f->width, f->height, cl, 0xFFFF, d, h); - else if (interpolation == dcraw_ahd_interpolation) { + else if (interpolation == dcraw_ppg_interpolation && h->filters > 1000) + ppg_interpolate_INDI(f->image, ff, f->width, f->height, cl, d, h); + + else if (interpolation == dcraw_xtrans_interpolation) { + xtrans_interpolate_INDI(f->image, h->filters, f->width, f->height, + h->colors, h->rgb_cam, d, h, 3); + smoothing = 0; + } else if (interpolation == dcraw_ahd_interpolation) { ahd_interpolate_INDI(f->image, ff, f->width, f->height, cl, h->rgb_cam, d, h); smoothPasses = 3; - } else if (interpolation == dcraw_ppg_interpolation && h->filters > 1000) - ppg_interpolate_INDI(f->image, ff, f->width, f->height, cl, d, h); - + } if (smoothing) color_smooth(f->image, f->width, f->height, smoothPasses); Index: ufraw.h =================================================================== RCS file: /cvsroot/ufraw/ufraw/ufraw.h,v retrieving revision 1.171 retrieving revision 1.172 diff -u -d -r1.171 -r1.172 --- ufraw.h 17 Oct 2013 05:30:15 -0000 1.171 +++ ufraw.h 17 Oct 2013 08:00:20 -0000 1.172 @@ -112,8 +112,9 @@ /* The following enum should match the dcraw_interpolation enum * in dcraw_api.h. */ enum { ahd_interpolation, vng_interpolation, four_color_interpolation, - ppg_interpolation, bilinear_interpolation, none_interpolation, - half_interpolation, obsolete_eahd_interpolation, num_interpolations + ppg_interpolation, bilinear_interpolation, xtrans_interpolation, + none_interpolation, half_interpolation, obsolete_eahd_interpolation, + num_interpolations }; enum { no_id, also_id, only_id, send_id }; enum { manual_curve, linear_curve, custom_curve, camera_curve }; ------------------------------------------------------------------------------ October Webinars: Code for Performance Free Intel webinars can help you accelerate application performance. Explore tips for MPI, OpenMP, advanced profiling, and more. Get the most from the latest Intel processors and coprocessors. See abstracts and register > http://pubads.g.doubleclick.net/gampad/clk?id=60135031&iu=/4140/ostg.clktrk _______________________________________________ ufraw-cvs mailing list ufraw-cvs@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/ufraw-cvs