From dba2f29195275566f1496c47a1b67c795cc027de Mon Sep 17 00:00:00 2001 From: Pierre Willenbrock Date: Sat, 2 Dec 2006 21:57:08 +0000 Subject: [PATCH] * backend/genesys_devices.c: fixed gamma settings(1.0 now) * backend/genesys.c backend/genesys_gl841.c: improved calibration for dark shades --- ChangeLog | 6 +++++ backend/genesys.c | 47 ++++++++++++++++++++++++++++++--------- backend/genesys_devices.c | 2 +- backend/genesys_gl841.c | 33 +++++++++++++++++++++------ 4 files changed, 69 insertions(+), 19 deletions(-) diff --git a/ChangeLog b/ChangeLog index c59c10a24..8c2a8c780 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2006-12-02 Pierre Willenbrock + + * backend/genesys_devices.c: fixed gamma settings(1.0 now) + * backend/genesys.c backend/genesys_gl841.c: improved calibration + for dark shades + 2006-12-02 Alessandro Zummo * Added missing bits for epson2 driver. diff --git a/backend/genesys.c b/backend/genesys.c index ea6437608..818b0d815 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -2726,6 +2726,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev) int x, j, o; unsigned int i; unsigned int coeff, target_code, val, avgpixels, dk, words_per_color = 0; + unsigned int target_dark, target_bright, br; DBG (DBG_proc, "genesys_send_shading_coefficient\n"); @@ -2917,7 +2918,8 @@ genesys_send_shading_coefficient (Genesys_Device * dev) } break; case CCD_CANONLIDE35: - target_code = 0xfa00; + target_bright = 0xfa00; + target_dark = 0xa00; o = 4;/*first four pixels are ignored*/ memset(shading_data, 0xff, words_per_color * 3); @@ -2931,6 +2933,22 @@ genesys_send_shading_coefficient (Genesys_Device * dev) another one: the dark/white shading is actually performed _after_ reducing resolution via averaging. only dark/white shading data for what would be first pixel at full resolution is used. + */ +/* + scanner raw input to output value calculation: + o=(i-off)*(gain/coeff) + + from datasheet: + off=dark_average + gain=coeff*bright_target/(bright_average-dark_average) + works for dark_target==0 + + what we want is these: + bright_target=(bright_average-off)*(gain/coeff) + dark_target=(dark_average-off)*(gain/coeff) + leading to + off = (dark_average*bright_target - bright_average*dark_target)/(bright_target - dark_target) + gain = (bright_target - dark_target)/(bright_average - dark_average)*coeff */ /*this should be evenly dividable*/ avgpixels = dev->sensor.optical_res/genesys_dpiset(dev->calib_reg); @@ -2946,8 +2964,21 @@ genesys_send_shading_coefficient (Genesys_Device * dev) for ( j = 0; j < channels; j++) { /* dark data */ - val = dev->dark_average_data[(x + pixels_per_line * j) * 2] | + dk = dev->dark_average_data[(x + pixels_per_line * j) * 2] | (dev->dark_average_data[(x + pixels_per_line * j) * 2 + 1] << 8); + + /* white data */ + br = (dev->white_average_data[(x + pixels_per_line * j) * 2] + | (dev->white_average_data[(x + pixels_per_line * j) * 2 + 1] << 8)); + + if (br*target_dark > dk*target_bright) + val = 0; + else if (dk*target_bright - br*target_dark > 65535 * (target_bright - target_dark)) + val = 65535; + else + val = (dk*target_bright - br*target_dark)/(target_bright - target_dark); + + /*fill all pixels, even if only the first one is relevant*/ for (i = 0; i < avgpixels; i++) { shading_data[ @@ -2958,16 +2989,10 @@ genesys_send_shading_coefficient (Genesys_Device * dev) ] = val >> 8; } - dk = val; + val = br - dk; - /* white data */ - val = (dev->white_average_data[(x + pixels_per_line * j) * 2] - | (dev->white_average_data[(x + pixels_per_line * j) * 2 + 1] << 8)); - - val -= dk; - - if (65535 * val > target_code * coeff) - val = (coeff * target_code) / val; + if (65535 * val > (target_bright - target_dark) * coeff) + val = (coeff * (target_bright - target_dark)) / val; else val = 65535; diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index 32ebad89f..fc82b8f08 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -215,7 +215,7 @@ static Genesys_Sensor Sensor[] = { 0x00, 0x00, 0x00, 0x00 /*TODO (these do no harm, but may be neccessery for CCD)*/ } , - 0.45, 0.45, 0.45, + 1.0, 1.0, 1.0, NULL, NULL, NULL} }; diff --git a/backend/genesys_gl841.c b/backend/genesys_gl841.c index 80e576077..86b9bb222 100644 --- a/backend/genesys_gl841.c +++ b/backend/genesys_gl841.c @@ -4362,6 +4362,7 @@ gl841_offset_calibration (Genesys_Device * dev) int turn; char fn[20]; SANE_Bool acceptable = SANE_FALSE; + int mintgt = 0x600; DBG (DBG_proc, "gl841_offset_calibration\n"); @@ -4492,9 +4493,9 @@ gl841_offset_calibration (Genesys_Device * dev) val = first_line[i * 2 * channels + 2 * j + 1] * 256 + first_line[i * 2 * channels + 2 * j]; - if (val == 0) + if (val < 10) cmin[j]++; - if (val == 65535) + if (val > 65525) cmax[j]++; } @@ -4578,7 +4579,7 @@ gl841_offset_calibration (Genesys_Device * dev) } DBG (DBG_info, - "gl841_offset_calibration: starting first line reading\n"); + "gl841_offset_calibration: starting second line reading\n"); RIE (gl841_begin_scan (dev, dev->calib_reg, SANE_TRUE)); RIE (sanei_genesys_read_data_from_scanner (dev, second_line, total_size)); @@ -4608,9 +4609,9 @@ gl841_offset_calibration (Genesys_Device * dev) val = second_line[i * 2 * channels + 2 * j + 1] * 256 + second_line[i * 2 * channels + 2 * j]; - if (val == 0) + if (val < 10) cmin[j]++; - if (val == 65535) + if (val > 65525) cmax[j]++; } @@ -4676,17 +4677,35 @@ gl841_offset_calibration (Genesys_Device * dev) DBG(DBG_info,"gl841_offset_calibration: second set: %d/%d,%d/%d,%d/%d\n", off2[0],min2[0],off2[1],min2[1],off2[2],min2[2]); +/* + calculate offset for each channel + based on minimal pixel value min1 at offset off1 and minimal pixel value min2 + at offset off2 + + to get min at off, values are linearly interpolated: + min=real+off*fact + min1=real+off1*fact + min2=real+off2*fact + + fact=(min1-min2)/(off1-off2) + real=min1-off1*(min1-min2)/(off1-off2) + + off=(min-min1+off1*(min1-min2)/(off1-off2))/((min1-min2)/(off1-off2)) + + off=(min*(off1-off2)+min1*off2-off1*min2)/(min1-min2) + + */ for (j = 0; j < channels; j++) { if (min2[j]-min1[j] == 0) { /*TODO: try to avoid this*/ DBG(DBG_warn,"gl841_offset_calibration: difference too small\n"); - if (min1[j] * off2[j] - min2[j] * off1[j] >= 0) + if (mintgt * (off1[j] - off2[j]) + min1[j] * off2[j] - min2[j] * off1[j] >= 0) off[j] = 0x0000; else off[j] = 0xffff; } else - off[j] = -(min1[j] * off2[j] - min2[j] * off1[j])/(min2[j]-min1[j]); + off[j] = -(mintgt * (off1[j] - off2[j]) + min2[j] * off1[j] - min1[j] * off2[j])/(min2[j]-min1[j]); dev->frontend.offset[j] = off[j]; }