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
merge-requests/1/head
Stéphane Voltz 2009-07-08 08:06:42 +02:00 zatwierdzone przez Stphane Voltz
rodzic 247b585de7
commit 0d82a5fba2
4 zmienionych plików z 110 dodań i 164 usunięć

Wyświetl plik

@ -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)
{

Wyświetl plik

@ -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
};

Wyświetl plik

@ -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;

Wyświetl plik

@ -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 */