From 0d82a5fba2ca50029a15ea95d130799b88f6af16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Voltz?= Date: Wed, 8 Jul 2009 08:06:42 +0200 Subject: [PATCH] hp2300 shading calibration fix - change 300 dpi mode to be in 'half ccd' mode - fix sensor pixel number - allow for negative offset in shading data building - rewrite compute_coefficients to handle negative offset and specialised it for pixel deletion case - fix calibration handling of flatbed scanners --- backend/genesys.c | 252 ++++++++++++++------------------------ backend/genesys_devices.c | 4 +- backend/genesys_gl646.c | 2 +- backend/genesys_gl646.h | 16 ++- 4 files changed, 110 insertions(+), 164 deletions(-) diff --git a/backend/genesys.c b/backend/genesys.c index 36e02c8a2..9ee101199 100644 --- a/backend/genesys.c +++ b/backend/genesys.c @@ -2754,166 +2754,97 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev) return SANE_STATUS_GOOD; } +/* computes one coefficient given bright-dark value + * @param coeff factor giving 1.00 gain + * @param target desired target code + * @param value brght-dark value + * */ static unsigned int -compute_coefficient (unsigned int coeff, - unsigned int target_code, unsigned int val) +compute_coefficient (unsigned int coeff, unsigned int target, unsigned int value) { - if (val <= 0) - return 0; + int result; - val = (coeff * target_code) / val; - - if (val > 65535) - val = 65535; - return val; + if (value > 0) + { + result = (coeff * target) / value; + if (result >= 65535) + { + result = 65535; + } + } + else + { + result = coeff; + } + return result; } /** * Computes shading coefficient using formula in data sheet. 16bit data values - * manipulated here are little endian. + * manipulated here are little endian. For now we assume deletion scanning type + * and that there is always 3 channels. * @param dev scanner's device * @shading_data memory area where to store the computed shading coefficients * @param pixels_per_line number of pixels per line * @param channels number of color channels (actually 1 or 3) - * @param avgpixels number of pixels to average * @param offset shading coefficients left offset * @param coeff 4000h or 2000h depending on fast scan mode or not + * @param target value of the target code */ static void compute_coefficients (Genesys_Device * dev, uint8_t * shading_data, unsigned int pixels_per_line, unsigned int channels, - unsigned int avgpixels, - unsigned int offset, - unsigned int coeff, unsigned int target_code) + int cmat[3], + int offset, + unsigned int coeff, + unsigned int target) { - uint8_t *ptr; /*contain 16bit words in little endian */ - unsigned int x, j; - unsigned int val, dk; + uint8_t *ptr; /* contain 16bit words in little endian */ + unsigned int x, c; + unsigned int val, br, dk; + unsigned int start, end; - for (x = 0; x < pixels_per_line - offset - avgpixels - 1; x += avgpixels) + DBG (DBG_io, + "compute_coefficients: pixels_per_line=%d, coeff=0x%04x\n", pixels_per_line, coeff); + + /* compute start & end values depending of the offset */ + if (offset < 0) + { + start = -1 * offset; + end = pixels_per_line; + } + else + { + start = 0; + end = pixels_per_line - offset; + } + + for (c = 0; c < channels; c++) { - /* dark data */ - ptr = shading_data + (x + offset) * 2 * 2 * 3; - dk = 0; - for (j = 0; j < avgpixels; j++) + for (x = start; x < end; x++) { - dk += dev->dark_average_data[(x + j) * 2 * channels]; - dk += 256 * dev->dark_average_data[(x + j) * 2 * channels + 1]; - } - dk /= j; - if (dk > 65535) - dk = 65535; - for (j = 0; j < avgpixels; j++) - { - ptr[0 + j * 2 * 2 * 3] = dk & 255; - ptr[1 + j * 2 * 2 * 3] = dk / 256; - } - if (channels > 1) - { - dk = 0; - for (j = 0; j < avgpixels; j++) - { - dk += dev->dark_average_data[(x + j) * 2 * channels + 2]; - dk += 256 * dev->dark_average_data[(x + j) * 2 * channels + 3]; - } - dk /= j; - if (dk > 65535) - dk = 65535; - for (j = 0; j < avgpixels; j++) - { - ptr[4 + j * 2 * 2 * 3] = dk & 255; - ptr[5 + j * 2 * 2 * 3] = dk / 256; - } - dk = 0; - for (j = 0; j < avgpixels; j++) - { - dk += dev->dark_average_data[(x + j) * 2 * channels + 4]; - dk += 256 * dev->dark_average_data[(x + j) * 2 * channels + 5]; - } - dk /= j; - if (dk > 65535) - dk = 65535; - for (j = 0; j < avgpixels; j++) - { - ptr[8 + j * 2 * 2 * 3] = dk & 255; - ptr[9 + j * 2 * 2 * 3] = dk / 256; - } - } - else - { - for (j = 0; j < avgpixels; j++) - { - ptr[4 + j * 2 * 2 * 3] = ptr[0]; - ptr[5 + j * 2 * 2 * 3] = ptr[1]; - ptr[8 + j * 2 * 2 * 3] = ptr[0]; - ptr[9 + j * 2 * 2 * 3] = ptr[1]; - } - } + /* TODO if channels=1 , use filter to know the base addr */ + ptr = shading_data + 4 * ((x + offset) * channels + cmat[c]); - /* white data */ - /* red channel */ - val = 0; - for (j = 0; j < avgpixels; j++) - { - val += 256 * dev->white_average_data[(x + j) * 2 * channels + 1]; - val += dev->white_average_data[(x + j) * 2 * channels]; - } - val /= j; - val -= (256 * ptr[1] + ptr[0]); - val = compute_coefficient (coeff, target_code, val); - for (j = 0; j < avgpixels; j++) - { - ptr[2 + j * 2 * 2 * 3] = val & 0xff; - ptr[3 + j * 2 * 2 * 3] = val / 256; - } + /* dark data */ + dk = dev->dark_average_data[x * 2 * channels + c * 2]; + dk += 256 * dev->dark_average_data[x * 2 * channels + c * 2 + 1]; - if (channels > 1) - { - /* green */ - val = 0; - for (j = 0; j < avgpixels; j++) - { - val += - 256 * dev->white_average_data[(x + j) * 2 * channels + 3]; - val += dev->white_average_data[(x + j) * 2 * channels + 2]; - } - val /= j; - val -= (256 * ptr[5] + ptr[4]); - val = compute_coefficient (coeff, target_code, val); - for (j = 0; j < avgpixels; j++) - { - ptr[6 + j * 2 * 2 * 3] = val & 0xff; - ptr[7 + j * 2 * 2 * 3] = val / 256; - } + /* white data */ + br = dev->white_average_data[x * 2 * channels + c * 2]; + br += 256 * dev->white_average_data[x * 2 * channels + c * 2 + 1]; + + /* compute coeff */ + val=compute_coefficient(coeff,target,br-dk); + + /* assign it */ + ptr[0] = dk & 255; + ptr[1] = dk / 256; + ptr[2] = val & 0xff; + ptr[3] = val / 256; - /* blue */ - val = 0; - for (j = 0; j < avgpixels; j++) - { - val += - 256 * dev->white_average_data[(x + j) * 2 * channels + 5]; - val += dev->white_average_data[(x + j) * 2 * channels + 4]; - } - val /= j; - val -= (256 * ptr[9] + ptr[8]); - val = compute_coefficient (coeff, target_code, val); - for (j = 0; j < avgpixels; j++) - { - ptr[10 + j * 2 * 2 * 3] = val & 255; - ptr[11 + j * 2 * 2 * 3] = val / 256; - } - } - else - { - for (j = 0; j < avgpixels; j++) - { - ptr[6 + j * 2 * 2 * 3] = val & 255; - ptr[7 + j * 2 * 2 * 3] = val / 256; - ptr[10 + j * 2 * 2 * 3] = val & 255; - ptr[11 + j * 2 * 2 * 3] = val / 256; - } } } } @@ -2943,10 +2874,9 @@ compute_planar_coefficients (Genesys_Device * dev, unsigned int coeff, unsigned int target) { uint8_t *ptr; /* contains 16bit words in little endian */ - unsigned int x, j, c; + unsigned int x, c; unsigned int val, dk, br; - DBG (DBG_io, "compute_planar_coefficients: pixels_per_line=%d, words=%d, coeff=0x%04x\n", pixels_per_line, words_per_color, coeff); @@ -2998,7 +2928,8 @@ genesys_send_shading_coefficient (Genesys_Device * dev) uint16_t pixels_per_line; uint8_t *shading_data; /**> contains 16bit words in little endian */ uint8_t channels; - unsigned int x, j, o; + unsigned int x, j; + int o; unsigned int length; /**> number of shading calibration data words */ unsigned int i, res; int cmat[3]; /**> matrix of color channels */ @@ -3012,9 +2943,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev) channels = dev->calib_channels; /* we always build data for three channels, even for gray */ - if (dev->model->is_cis) - { - if (dev->model->asic_type != GENESYS_GL646) + if (dev->model->is_cis && dev->model->asic_type != GENESYS_GL646) { switch (sanei_genesys_read_reg_from_set (dev->reg, 0x05) >> 6) { @@ -3055,12 +2984,6 @@ genesys_send_shading_coefficient (Genesys_Device * dev) /* 3 channels, 2 bytes a word */ length = words_per_color * 3 * 2; } - shading_data = malloc (length); /* 16 bit black, 16 bit white */ - } - else /* chunky calibration data case */ - { - length = pixels_per_line * 2 * 2 * 3; /* 16 bit black, 16 bit white */ - } /* allocate computed size */ shading_data = malloc (length); @@ -3102,25 +3025,36 @@ genesys_send_shading_coefficient (Genesys_Device * dev) words_per_color, channels, cmat, o, coeff, target_code); break; - case CCD_5345: - target_code = 0xfa00; - o = 4; - avgpixels = 1; + case CCD_HP2300: + target_code = 0xdc00; + if(dev->settings.xres>300) + { + o = 2; + } + else + { + o = -8; + } + cmat[0] = 0; + cmat[1] = 1; + cmat[2] = 2; compute_coefficients (dev, shading_data, pixels_per_line, - channels, avgpixels, o, coeff, target_code); + 3, cmat, o, coeff, target_code); break; - case CCD_HP2300: + case CCD_5345: case CCD_HP2400: case CCD_HP3670: target_code = 0xfa00; - o = 2; - avgpixels = 1; + o = 4; + cmat[0] = 0; + cmat[1] = 1; + cmat[2] = 2; compute_coefficients (dev, shading_data, pixels_per_line, - channels, avgpixels, o, coeff, target_code); + 3, cmat, o, coeff, target_code); break; case CCD_CANONLIDE35: target_bright = 0xfa00; @@ -4109,7 +4043,7 @@ genesys_start_scan (Genesys_Device * dev) if (status != SANE_STATUS_GOOD) { DBG (DBG_error, - "genesys_flatbed_calibration: failed to init gamma table: %s\n", + "genesys_start_scan: failed to init gamma table: %s\n", sane_strstatus (status)); return status; } @@ -4120,7 +4054,7 @@ genesys_start_scan (Genesys_Device * dev) { /* calibration : sheetfed scanners can't calibrate before each scan */ /* so we use a NO_CALIBRATION flags for those scanners */ - if (!dev->model->flags & GENESYS_FLAG_NO_CALIBRATION) + if (!(dev->model->flags & GENESYS_FLAG_NO_CALIBRATION)) { status = genesys_scanner_calibration (dev); if (status != SANE_STATUS_GOOD) @@ -4133,6 +4067,10 @@ genesys_start_scan (Genesys_Device * dev) genesys_save_calibration (dev); } + else + { + DBG (DBG_warn, "genesys_start_scan: no calibration done\n"); + } } else if (status != SANE_STATUS_GOOD) { diff --git a/backend/genesys_devices.c b/backend/genesys_devices.c index 0566b2bd7..d2978fa28 100644 --- a/backend/genesys_devices.c +++ b/backend/genesys_devices.c @@ -213,7 +213,7 @@ static Genesys_Sensor Sensor[] = { /* 5: HP2300c */ {CCD_HP2300,600, 48, - 20, 0, 5454, 180, 180, + 20, 0, 5368, 180, 180, /* 5376 */ {0x16, 0x00, 0x01, 0x03} , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x0a, 0x20, 0x2a, 0x6a, 0x8a, @@ -868,7 +868,7 @@ static Genesys_Model hp2300c_model = { | GENESYS_FLAG_HALF_CCD_MODE | GENESYS_FLAG_CUSTOM_GAMMA, GENESYS_HAS_SCAN_SW | GENESYS_HAS_COPY_SW, - 18, + 40, 132 }; diff --git a/backend/genesys_gl646.c b/backend/genesys_gl646.c index 1d13a02a0..7a13b68ad 100644 --- a/backend/genesys_gl646.c +++ b/backend/genesys_gl646.c @@ -2898,7 +2898,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev) settings.yres = dev->sensor.optical_res / half_ccd; settings.tl_x = 0; settings.tl_y = 0; - settings.pixels = dev->sensor.sensor_pixels / half_ccd; + settings.pixels = (dev->sensor.sensor_pixels * settings.xres) / dev->sensor.optical_res; settings.lines = dev->model->shading_lines * (3 - half_ccd); settings.depth = 16; settings.color_filter = dev->settings.color_filter; diff --git a/backend/genesys_gl646.h b/backend/genesys_gl646.h index 0e7384647..fbb85e4b4 100644 --- a/backend/genesys_gl646.h +++ b/backend/genesys_gl646.h @@ -464,14 +464,18 @@ static Sensor_Master sensor_master[] = { /* HP 2300 master settings */ {CCD_HP2300, 75, SANE_TRUE , 75, 4480, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 150, SANE_TRUE , 150, 4350, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, - {CCD_HP2300, 300, SANE_TRUE , 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300, 300, SANE_TRUE, 600, 4350, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 600, SANE_TRUE , 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300,1200, SANE_TRUE , 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300, 75, SANE_FALSE, 75, 4480, 150, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 150, SANE_FALSE, 150, 4350, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, - {CCD_HP2300, 300, SANE_FALSE, 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300, 300, SANE_FALSE, 600, 4350, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x20, 0x85}, {CCD_HP2300, 600, SANE_FALSE, 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, {CCD_HP2300,1200, SANE_FALSE, 600, 8700, 600, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + /* non half ccd 300 dpi settings + {CCD_HP2300, 300, SANE_TRUE , 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + {CCD_HP2300, 300, SANE_FALSE, 300, 8700, 300, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_FALSE, 0x20, 0x05}, + */ /* MD5345/6471 master settings */ {CCD_5345 , 50, SANE_TRUE , 50, 12000, 100, 1, 42, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, SANE_TRUE , 0x28, 0x03}, @@ -537,14 +541,18 @@ static Motor_Master motor_master[] = { /* HP scanjet 2300c */ {MOTOR_HP2300, 75, SANE_TRUE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 150, SANE_TRUE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, - {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_FALSE, 63, 3, 2175, 1087, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 600, SANE_TRUE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300,1200, SANE_TRUE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 17400, 8700, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 75, SANE_FALSE, 75, FULL_STEP, SANE_FALSE, SANE_TRUE , 63, 120, 8139, 560, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 150, SANE_FALSE, 150, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 67, 7903, 543, 120, 4905, 337, 0.3, 0.4, 16}, - {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_FALSE, 63, 3, 2175, 1087, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300, 600, SANE_FALSE, 600, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 8700, 4350, 120, 4905, 337, 0.3, 0.4, 16}, {MOTOR_HP2300,1200, SANE_FALSE,1200, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 3, 17400, 8700, 120, 4905, 337, 0.3, 0.4, 16}, + /* non half ccd settings for 300 dpi + {MOTOR_HP2300, 300, SANE_TRUE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, + {MOTOR_HP2300, 300, SANE_FALSE, 300, HALF_STEP, SANE_FALSE, SANE_TRUE , 63, 44, 5386, 2175, 120, 4905, 337, 0.3, 0.4, 16}, + */ /* MD5345/6471 motor settings */ /* vfinal=(exposure/(1200/dpi))/step_type */