kopia lustrzana https://gitlab.com/sane-project/backends
- shading calibration rework for gl646 based scanners
rodzic
18e88c02a7
commit
a7a759b896
|
@ -1,3 +1,7 @@
|
|||
2009-04-14 Stéphane Voltz <stef.dev@free.fr>
|
||||
* backend/genesys.c backend/genesys_devices.c backend/genesys_gl646.c:
|
||||
shading calibration rework for GL646 based scanners
|
||||
|
||||
2009-04-13 m. allan noah <kitno455 a t gmail d o t com>
|
||||
* tools/sane-desc.c: fix double summing of untested column
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
|
||||
#include "../include/sane/config.h"
|
||||
|
||||
#define BUILD 10
|
||||
#define BUILD 11
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
@ -188,6 +188,7 @@ sanei_genesys_write_pnm_file (char *filename, uint8_t * data, int depth,
|
|||
int channels, int pixels_per_line, int lines)
|
||||
{
|
||||
FILE *out;
|
||||
int count;
|
||||
|
||||
DBG (DBG_info,
|
||||
"sanei_genesys_write_pnm_file: depth=%d, channels=%d, ppl=%d, lines=%d\n",
|
||||
|
@ -205,7 +206,6 @@ sanei_genesys_write_pnm_file (char *filename, uint8_t * data, int depth,
|
|||
pixels_per_line, lines, (int) pow (2, depth) - 1);
|
||||
if (channels == 3)
|
||||
{
|
||||
int count = 0;
|
||||
for (count = 0; count < (pixels_per_line * lines * 3); count++)
|
||||
{
|
||||
if (depth == 16)
|
||||
|
@ -217,7 +217,6 @@ sanei_genesys_write_pnm_file (char *filename, uint8_t * data, int depth,
|
|||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
for (count = 0; count < (pixels_per_line * lines); count++)
|
||||
{
|
||||
if (depth == 8)
|
||||
|
@ -1308,7 +1307,7 @@ genesys_send_offset_and_shading (Genesys_Device * dev, uint8_t * data,
|
|||
|
||||
dpihw = sanei_genesys_read_reg_from_set (dev->reg, 0x05) >> 6;
|
||||
|
||||
if (dev->settings.scan_mode < 2 && dev->model->ccd_type != CCD_HP2300 && dev->model->ccd_type != CCD_HP2400 && dev->model->ccd_type != CCD_5345) /* lineart, halftone */
|
||||
if (dev->settings.scan_mode < 2 && dev->model->ccd_type != CCD_HP2300 && dev->model->ccd_type != CCD_HP2400 && dev->model->ccd_type != CCD_HP3670 && dev->model->ccd_type != CCD_5345) /* lineart, halftone */
|
||||
{
|
||||
if (dpihw == 0) /* 600 dpi */
|
||||
start_address = 0x02a00;
|
||||
|
@ -2310,40 +2309,25 @@ genesys_dark_shading_calibration (Genesys_Device * dev)
|
|||
status = dev->model->cmd_set->end_scan (dev, dev->calib_reg, SANE_TRUE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (calibration_data);
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_shading_calibration: Failed to end scan: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
dev->model->cmd_set->set_motor_power (dev->calib_reg, SANE_FALSE);
|
||||
dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_TRUE);
|
||||
|
||||
status =
|
||||
dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg,
|
||||
dev->model->cmd_set->
|
||||
bulk_full_size ());
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
free (calibration_data);
|
||||
DBG (DBG_error,
|
||||
"genesys_dark_shading_calibration: Failed to bulk write registers: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
sanei_genesys_write_pnm_file ("black_shading.pnm", calibration_data, 16,
|
||||
channels, pixels_per_line,
|
||||
dev->model->shading_lines);
|
||||
|
||||
genesys_average_data (dev->dark_average_data, calibration_data,
|
||||
dev->model->shading_lines,
|
||||
pixels_per_line * channels);
|
||||
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
sanei_genesys_write_pnm_file ("black_shading.pnm", calibration_data, 16,
|
||||
channels, pixels_per_line,
|
||||
dev->model->shading_lines);
|
||||
sanei_genesys_write_pnm_file ("black_average.pnm", dev->dark_average_data,
|
||||
16, channels, pixels_per_line, 1);
|
||||
}
|
||||
|
||||
free (calibration_data);
|
||||
|
||||
|
@ -2468,6 +2452,8 @@ genesys_white_shading_calibration (Genesys_Device * dev)
|
|||
pixels_per_line =
|
||||
(genesys_pixels_per_line (dev->calib_reg)
|
||||
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
|
||||
/* XXX STEF XXX */
|
||||
pixels_per_line = dev->calib_pixels;
|
||||
|
||||
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
|
||||
channels = 3;
|
||||
|
@ -2497,7 +2483,7 @@ genesys_white_shading_calibration (Genesys_Device * dev)
|
|||
|
||||
/* turn on motor and lamp power */
|
||||
dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_TRUE);
|
||||
dev->model->cmd_set->set_motor_power (dev->calib_reg, SANE_FALSE); /* XXX STEF */
|
||||
dev->model->cmd_set->set_motor_power (dev->calib_reg, SANE_TRUE);
|
||||
|
||||
status =
|
||||
dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg,
|
||||
|
@ -2595,7 +2581,6 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
|
||||
DBG (DBG_proc, "genesys_black_white_shading_calibration (lines = %d)\n",
|
||||
dev->model->shading_lines);
|
||||
|
||||
pixels_per_line =
|
||||
(genesys_pixels_per_line (dev->calib_reg)
|
||||
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
|
||||
|
@ -2641,7 +2626,7 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
|
||||
/* turn on motor and lamp power */
|
||||
dev->model->cmd_set->set_lamp_power (dev, dev->calib_reg, SANE_TRUE);
|
||||
dev->model->cmd_set->set_motor_power (dev->calib_reg, SANE_TRUE);
|
||||
dev->model->cmd_set->set_motor_power (dev->calib_reg, SANE_FALSE);
|
||||
|
||||
status =
|
||||
dev->model->cmd_set->bulk_write_register (dev, dev->calib_reg,
|
||||
|
@ -2772,6 +2757,163 @@ genesys_dark_white_shading_calibration (Genesys_Device * dev)
|
|||
return SANE_STATUS_GOOD;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
compute_coefficient (unsigned int coeff,
|
||||
unsigned int target_code, unsigned int val)
|
||||
{
|
||||
if (val <= 0)
|
||||
return 65535;
|
||||
|
||||
val = (coeff * target_code) / val;
|
||||
|
||||
if (val > 65535)
|
||||
val = 65535;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes shading coefficient using formula in data sheet. 16bit data values
|
||||
* manipulated here are little endian.
|
||||
* @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
|
||||
*/
|
||||
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)
|
||||
{
|
||||
uint8_t *ptr; /*contain 16bit words in little endian */
|
||||
unsigned int x, j;
|
||||
unsigned int val, dk;
|
||||
|
||||
for (x = 0; x < pixels_per_line - offset - avgpixels - 1; x += avgpixels)
|
||||
{
|
||||
/* dark data */
|
||||
ptr = shading_data + (x + offset) * 2 * 2 * 3;
|
||||
dk = 0;
|
||||
for (j = 0; j < avgpixels; j++)
|
||||
{
|
||||
dk += dev->dark_average_data[(x + j) * 2 * channels];
|
||||
dk += 256 * dev->dark_average_data[(x + j) * 2 * channels + 1];
|
||||
}
|
||||
dk /= j;
|
||||
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;
|
||||
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;
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static SANE_Status
|
||||
genesys_send_shading_coefficient (Genesys_Device * dev)
|
||||
|
@ -2780,7 +2922,7 @@ 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;
|
||||
int x, j, o;
|
||||
unsigned int x, j, o;
|
||||
unsigned int i, res;
|
||||
unsigned int coeff, target_code, val, avgpixels, dk, words_per_color = 0;
|
||||
unsigned int target_dark, target_bright, br;
|
||||
|
@ -2831,147 +2973,42 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
coeff = 0x4000;
|
||||
else
|
||||
coeff = 0x2000;
|
||||
|
||||
switch (dev->model->ccd_type)
|
||||
{
|
||||
case CCD_5345:
|
||||
/* from the logs, we can see that the first 2 coefficients are zeroed,
|
||||
which surely means that coeff depends in a way or another on the 2 previous
|
||||
pixel columns */
|
||||
/* depends upon R06 shading gain */
|
||||
|
||||
target_code = 0xFA00;
|
||||
target_code = 0xfa00;
|
||||
memset (shading_data, 0x00, pixels_per_line * 4 * channels);
|
||||
|
||||
/* todo: if GAIN4, shading data is 'chunky', while it is 'line' when
|
||||
GAIN4 is reset */
|
||||
for (x = 2; x < pixels_per_line; x++)
|
||||
{
|
||||
/* dark data */
|
||||
shading_data[x * 2 * 2 * 3] =
|
||||
dev->dark_average_data[x * 2 * channels];
|
||||
shading_data[x * 2 * 2 * 3 + 1] =
|
||||
dev->dark_average_data[x * 2 * channels + 1];
|
||||
if (channels > 1)
|
||||
{
|
||||
shading_data[x * 2 * 2 * 3 + 4] =
|
||||
dev->dark_average_data[x * 2 * channels + 2];
|
||||
shading_data[x * 2 * 2 * 3 + 5] =
|
||||
dev->dark_average_data[x * 2 * channels + 3];
|
||||
shading_data[x * 2 * 2 * 3 + 8] =
|
||||
dev->dark_average_data[x * 2 * channels + 4];
|
||||
shading_data[x * 2 * 2 * 3 + 9] =
|
||||
dev->dark_average_data[x * 2 * channels + 5];
|
||||
}
|
||||
else
|
||||
{
|
||||
shading_data[x * 2 * 2 * 3 + 4] =
|
||||
dev->dark_average_data[x * 2 * channels];
|
||||
shading_data[x * 2 * 2 * 3 + 5] =
|
||||
dev->dark_average_data[x * 2 * channels + 1];
|
||||
shading_data[x * 2 * 2 * 3 + 8] =
|
||||
dev->dark_average_data[x * 2 * channels];
|
||||
shading_data[x * 2 * 2 * 3 + 9] =
|
||||
dev->dark_average_data[x * 2 * channels + 1];
|
||||
}
|
||||
|
||||
/* white data */
|
||||
/* red channel */
|
||||
val = 0;
|
||||
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - 2) * 2 * channels + 1] +
|
||||
dev->white_average_data[(x - 2) * 2 * channels];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x - 2) * 2 * channels + 1] +
|
||||
dev->dark_average_data[(x - 2) * 2 * channels]);
|
||||
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - 1) * 2 * channels + 1] +
|
||||
dev->white_average_data[(x - 1) * 2 * channels];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x - 1) * 2 * channels + 1] +
|
||||
dev->dark_average_data[(x - 1) * 2 * channels]);
|
||||
|
||||
val +=
|
||||
256 * dev->white_average_data[(x) * 2 * channels + 1] +
|
||||
dev->white_average_data[(x) * 2 * channels];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x) * 2 * channels + 1] +
|
||||
dev->dark_average_data[(x) * 2 * channels]);
|
||||
|
||||
val /= 3;
|
||||
if ((65535 * val) / coeff > target_code)
|
||||
val = (coeff * target_code) / val;
|
||||
else
|
||||
val = 65535;
|
||||
shading_data[x * 2 * 2 * 3 + 2] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 3] = val >> 8;
|
||||
if (channels > 1)
|
||||
{
|
||||
/* green */
|
||||
val = 0;
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - 2) * 2 * channels + 3] +
|
||||
dev->white_average_data[(x - 2) * 2 * channels + 2];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x - 2) * 2 * channels + 3] +
|
||||
dev->dark_average_data[(x - 2) * 2 * channels + 2]);
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - 1) * 2 * channels + 3] +
|
||||
dev->white_average_data[(x - 1) * 2 * channels + 2];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x - 1) * 2 * channels + 3] +
|
||||
dev->dark_average_data[(x - 1) * 2 * channels + 2]);
|
||||
val +=
|
||||
256 * dev->white_average_data[(x) * 2 * channels + 3] +
|
||||
dev->white_average_data[(x) * 2 * channels + 2];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x) * 2 * channels + 3] +
|
||||
dev->dark_average_data[(x) * 2 * channels + 2]);
|
||||
val /= 3;
|
||||
if ((65535 * val) / coeff > target_code)
|
||||
val = (coeff * target_code) / val;
|
||||
else
|
||||
val = 65535;
|
||||
shading_data[x * 2 * 2 * 3 + 6] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 7] = val >> 8;
|
||||
|
||||
/* blue */
|
||||
val = 0;
|
||||
val +=
|
||||
256 * dev->white_average_data[(x) * 2 * channels + 5] +
|
||||
dev->white_average_data[(x) * 2 * channels + 4];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x) * 2 * channels + 5] +
|
||||
dev->dark_average_data[(x) * 2 * channels + 4]);
|
||||
val +=
|
||||
256 * dev->white_average_data[(x) * 2 * channels + 5] +
|
||||
dev->white_average_data[(x) * 2 * channels + 4];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x) * 2 * channels + 5] +
|
||||
dev->dark_average_data[(x) * 2 * channels + 4]);
|
||||
val +=
|
||||
256 * dev->white_average_data[(x) * 2 * channels + 5] +
|
||||
dev->white_average_data[(x) * 2 * channels + 4];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x) * 2 * channels + 5] +
|
||||
dev->dark_average_data[(x) * 2 * channels + 4]);
|
||||
val /= 3;
|
||||
if ((65535 * val) / coeff > target_code)
|
||||
val = (coeff * target_code) / val;
|
||||
else
|
||||
val = 65535;
|
||||
shading_data[x * 2 * 2 * 3 + 10] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 11] = val >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
shading_data[x * 2 * 2 * 3 + 6] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 7] = val >> 8;
|
||||
shading_data[x * 2 * 2 * 3 + 10] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 11] = val >> 8;
|
||||
}
|
||||
}
|
||||
o=2;
|
||||
avgpixels = 1;
|
||||
compute_coefficients(dev,
|
||||
shading_data,
|
||||
pixels_per_line,
|
||||
channels,
|
||||
avgpixels,
|
||||
o,
|
||||
coeff,
|
||||
target_code);
|
||||
break;
|
||||
case CCD_HP2300:
|
||||
case CCD_HP2400:
|
||||
case CCD_HP3670:
|
||||
target_code = 0xfa00;
|
||||
memset (shading_data, 0x00, pixels_per_line * 4 * channels);
|
||||
o = 2; /* when ~AVEENB, o=3 if AVEENB ? */
|
||||
if(dev->settings.xres<=150)
|
||||
avgpixels = 2;
|
||||
else
|
||||
avgpixels = 1;
|
||||
/* TODO: if FASTMODE, shading data is 'color component line by line' */
|
||||
compute_coefficients(dev,
|
||||
shading_data,
|
||||
pixels_per_line,
|
||||
channels,
|
||||
avgpixels,
|
||||
o,
|
||||
coeff,
|
||||
target_code);
|
||||
break;
|
||||
case CCD_CANONLIDE35:
|
||||
target_bright = 0xfa00;
|
||||
|
@ -3046,21 +3083,25 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
for (i = 0; i < avgpixels; i++)
|
||||
{
|
||||
/* dark data */
|
||||
dk += (dev->dark_average_data[(x + i + pixels_per_line * j) * 2]
|
||||
| (dev->
|
||||
dark_average_data[(x + i + pixels_per_line * j) * 2 +
|
||||
1] << 8));
|
||||
|
||||
dk +=
|
||||
(dev->dark_average_data[(x + i +
|
||||
pixels_per_line * j) *
|
||||
2] |
|
||||
(dev->dark_average_data
|
||||
[(x + i + pixels_per_line * j) * 2 + 1] << 8));
|
||||
|
||||
/* white data */
|
||||
br += (dev->white_average_data[(x + i + pixels_per_line * j) * 2]
|
||||
| (dev->
|
||||
white_average_data[(x + i + pixels_per_line * j) * 2 +
|
||||
1] << 8));
|
||||
br +=
|
||||
(dev->white_average_data[(x + i +
|
||||
pixels_per_line * j) *
|
||||
2] |
|
||||
(dev->white_average_data
|
||||
[(x + i + pixels_per_line * j) * 2 + 1] << 8));
|
||||
}
|
||||
|
||||
|
||||
br /= avgpixels;
|
||||
dk /= avgpixels;
|
||||
|
||||
|
||||
if (br * target_dark > dk * target_bright)
|
||||
val = 0;
|
||||
else if (dk * target_bright - br * target_dark >
|
||||
|
@ -3104,8 +3145,7 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
{
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * j] =
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * 0];
|
||||
shading_data[(x + o + i) * 2 * 2 + words_per_color * 0];
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
words_per_color * j + 1] =
|
||||
shading_data[(x + o + i) * 2 * 2 +
|
||||
|
@ -3134,134 +3174,11 @@ genesys_send_shading_coefficient (Genesys_Device * dev)
|
|||
}
|
||||
*/
|
||||
break;
|
||||
case CCD_HP2300:
|
||||
case CCD_HP2400:
|
||||
default:
|
||||
target_code = 0xFA00;
|
||||
for (x = 6; x < pixels_per_line; x++)
|
||||
{
|
||||
/* dark data */
|
||||
val = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
val += dev->dark_average_data[(x - i) * 2 * channels];
|
||||
val += 256 * dev->dark_average_data[(x - i) * 2 * channels + 1];
|
||||
}
|
||||
val /= i;
|
||||
shading_data[x * 2 * 2 * 3] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 1] = val >> 8;
|
||||
|
||||
if (channels > 1)
|
||||
{
|
||||
val = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
val += dev->dark_average_data[(x - i) * 2 * channels + 2];
|
||||
val +=
|
||||
256 * dev->dark_average_data[(x - i) * 2 * channels + 3];
|
||||
}
|
||||
val /= i;
|
||||
shading_data[x * 2 * 2 * 3 + 4] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 5] = val >> 8;
|
||||
|
||||
val = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
val += dev->dark_average_data[(x - i) * 2 * channels + 4];
|
||||
val +=
|
||||
256 * dev->dark_average_data[(x - i) * 2 * channels + 5];
|
||||
}
|
||||
val /= i;
|
||||
shading_data[x * 2 * 2 * 3 + 8] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 9] = val >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
shading_data[x * 2 * 2 * 3 + 4] = shading_data[x * 2 * 2 * 3];
|
||||
shading_data[x * 2 * 2 * 3 + 5] =
|
||||
shading_data[x * 2 * 2 * 3 + 1];
|
||||
shading_data[x * 2 * 2 * 3 + 8] = shading_data[x * 2 * 2 * 3];
|
||||
shading_data[x * 2 * 2 * 3 + 9] =
|
||||
shading_data[x * 2 * 2 * 3 + 1];
|
||||
}
|
||||
|
||||
/* white data */
|
||||
val = 0;
|
||||
|
||||
/* average on 7 rows */
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - i) * 2 * channels + 1] +
|
||||
dev->white_average_data[(x - i) * 2 * channels];
|
||||
val -=
|
||||
(256 * dev->dark_average_data[(x - i) * 2 * channels + 1] +
|
||||
dev->dark_average_data[(x - i) * 2 * channels]);
|
||||
}
|
||||
val /= i;
|
||||
|
||||
if ((65535 * val) / coeff > target_code)
|
||||
val = (coeff * target_code) / val;
|
||||
else
|
||||
val = 65535;
|
||||
shading_data[x * 2 * 2 * 3 + 2] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 3] = val >> 8;
|
||||
if (channels > 1)
|
||||
{
|
||||
/* green */
|
||||
/* average on 7 rows */
|
||||
val = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - i) * 2 * channels +
|
||||
3] +
|
||||
dev->white_average_data[(x - i) * 2 * channels + 2];
|
||||
val -=
|
||||
(256 *
|
||||
dev->dark_average_data[(x - i) * 2 * channels + 3] +
|
||||
dev->dark_average_data[(x - i) * 2 * channels + 2]);
|
||||
}
|
||||
val /= i;
|
||||
|
||||
if ((65535 * val) / coeff > target_code)
|
||||
val = (coeff * target_code) / val;
|
||||
else
|
||||
val = 65535;
|
||||
shading_data[x * 2 * 2 * 3 + 6] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 7] = val >> 8;
|
||||
|
||||
/* blue */
|
||||
/* average on 7 rows */
|
||||
val = 0;
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
val +=
|
||||
256 * dev->white_average_data[(x - i) * 2 * channels +
|
||||
5] +
|
||||
dev->white_average_data[(x - i) * 2 * channels + 4];
|
||||
val -=
|
||||
(256 *
|
||||
dev->dark_average_data[(x - i) * 2 * channels + 5] +
|
||||
dev->dark_average_data[(x - i) * 2 * channels + 4]);
|
||||
}
|
||||
val /= i;
|
||||
|
||||
if ((65535 * val) / coeff > target_code)
|
||||
val = (coeff * target_code) / val;
|
||||
else
|
||||
val = 65535;
|
||||
shading_data[x * 2 * 2 * 3 + 10] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 11] = val >> 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
shading_data[x * 2 * 2 * 3 + 6] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 7] = val >> 8;
|
||||
shading_data[x * 2 * 2 * 3 + 10] = val & 0xff;
|
||||
shading_data[x * 2 * 2 * 3 + 11] = val >> 8;
|
||||
}
|
||||
}
|
||||
DBG (DBG_error,
|
||||
"genesys_send_shading_coefficient: sensor %d not supported\n",
|
||||
dev->model->ccd_type);
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3353,7 +3270,7 @@ genesys_restore_calibration (Genesys_Device * dev)
|
|||
static SANE_Status
|
||||
genesys_save_calibration (Genesys_Device * dev)
|
||||
{
|
||||
SANE_Status status;
|
||||
SANE_Status status=SANE_STATUS_UNSUPPORTED;
|
||||
Genesys_Calibration_Cache *cache;
|
||||
uint8_t *tmp;
|
||||
|
||||
|
@ -3362,22 +3279,17 @@ genesys_save_calibration (Genesys_Device * dev)
|
|||
if (!dev->model->cmd_set->is_compatible_calibration)
|
||||
return SANE_STATUS_UNSUPPORTED;
|
||||
|
||||
for(cache = dev->calibration_cache; cache; cache = cache->next)
|
||||
for(cache = dev->calibration_cache; cache && status==SANE_STATUS_UNSUPPORTED; cache = cache->next)
|
||||
{
|
||||
status = dev->model->cmd_set->is_compatible_calibration(dev, cache,
|
||||
SANE_TRUE);
|
||||
if (status == SANE_STATUS_UNSUPPORTED)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else if (status != SANE_STATUS_GOOD)
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"genesys_save_calibration: fail while checking compatibility: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(cache)
|
||||
|
@ -3600,9 +3512,13 @@ genesys_flatbed_calibration (Genesys_Device * dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
/* GL646 scanners set up calib_pixels in init_regs_for_shading */
|
||||
if (dev->model->asic_type != GENESYS_GL646)
|
||||
{
|
||||
dev->calib_pixels =
|
||||
(genesys_pixels_per_line (dev->calib_reg)
|
||||
* genesys_dpiset (dev->calib_reg)) / dev->sensor.optical_res;
|
||||
}
|
||||
|
||||
if (dev->model->flags & GENESYS_FLAG_DARK_WHITE_CALIBRATION)
|
||||
{
|
||||
|
@ -3872,9 +3788,10 @@ genesys_start_scan (Genesys_Device * dev)
|
|||
RIE (genesys_warmup_lamp (dev));
|
||||
}
|
||||
|
||||
/* set top left x and y values if flatbed scanners */
|
||||
/* set top left x and y values by scanning the internals if flatbed scanners */
|
||||
if (dev->model->is_sheetfed == SANE_FALSE)
|
||||
{
|
||||
/* do the geometry detection only once */
|
||||
if ((dev->model->flags & GENESYS_FLAG_SEARCH_START)
|
||||
&& (dev->model->y_offset_calib == 0))
|
||||
{
|
||||
|
@ -5299,7 +5216,7 @@ init_options (Genesys_Scanner * s)
|
|||
s->opt[OPT_CALIBRATE].type = SANE_TYPE_BUTTON;
|
||||
s->opt[OPT_CALIBRATE].unit = SANE_UNIT_NONE;
|
||||
if (model->buttons & GENESYS_HAS_CALIBRATE)
|
||||
s->opt[OPT_CALIBRATE].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC;
|
||||
s->opt[OPT_CALIBRATE].cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT | SANE_CAP_ADVANCED | SANE_CAP_AUTOMATIC;
|
||||
else
|
||||
s->opt[OPT_CALIBRATE].cap = SANE_CAP_INACTIVE;
|
||||
s->val[OPT_CALIBRATE].b = 0;
|
||||
|
|
|
@ -104,8 +104,8 @@ static Genesys_Frontend Wolfson[] = {
|
|||
, /* 6: CANONLIDE35 */
|
||||
{DAC_AD_XP200,{0x58, 0x00, 0x00, 0x00} /* TODO create an AnalogDevice struct */
|
||||
, {0x00, 0x00, 0x00}
|
||||
, {0x06, 0x00, 0x00}
|
||||
, {0x0c, 0x00, 0x00}
|
||||
, {0x0a, 0x00, 0x00} /* offset */
|
||||
, {0x20, 0x00, 0x00} /* gain */
|
||||
, {0x00, 0x00, 0x00}
|
||||
}
|
||||
,
|
||||
|
@ -830,7 +830,7 @@ static Genesys_Model hp2300c_model = {
|
|||
GPO_HP2300,
|
||||
MOTOR_HP2300,
|
||||
GENESYS_FLAG_14BIT_GAMMA
|
||||
/* | GENESYS_FLAG_NO_CALIBRATION */
|
||||
| GENESYS_FLAG_LAZY_INIT
|
||||
| GENESYS_FLAG_SEARCH_START
|
||||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_OFFSET_CALIBRATION
|
||||
|
@ -885,6 +885,7 @@ Genesys_Model hp2400c_model = {
|
|||
GPO_HP2400,
|
||||
MOTOR_HP2400,
|
||||
GENESYS_FLAG_UNTESTED /* not fully working yet */
|
||||
| GENESYS_FLAG_LAZY_INIT
|
||||
| GENESYS_FLAG_14BIT_GAMMA
|
||||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_OFFSET_CALIBRATION
|
||||
|
@ -943,7 +944,7 @@ Genesys_Model visioneer_xp200_model = {
|
|||
| GENESYS_FLAG_CUSTOM_GAMMA
|
||||
| GENESYS_FLAG_SKIP_WARMUP
|
||||
| GENESYS_FLAG_NO_CALIBRATION,
|
||||
GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW | GENESYS_HAS_CALIBRATE,
|
||||
GENESYS_HAS_SCAN_SW | GENESYS_HAS_PAGE_LOADED_SW, /* | GENESYS_HAS_CALIBRATE, */
|
||||
20,
|
||||
132
|
||||
};
|
||||
|
@ -992,6 +993,7 @@ static Genesys_Model hp3670c_model = {
|
|||
MOTOR_HP3670,
|
||||
GENESYS_FLAG_14BIT_GAMMA
|
||||
| GENESYS_FLAG_SEARCH_START
|
||||
| GENESYS_FLAG_SKIP_WARMUP
|
||||
| GENESYS_FLAG_DARK_CALIBRATION
|
||||
| GENESYS_FLAG_OFFSET_CALIBRATION
|
||||
| GENESYS_FLAG_CUSTOM_GAMMA,
|
||||
|
|
|
@ -1278,9 +1278,9 @@ gl646_setup_registers (Genesys_Device * dev,
|
|||
|
||||
/* vfinal=(exposure/(1200/dpi))/step_type */
|
||||
/* DBG (DBG_info, "XXX STEF XXX vfinal=%d, vend1=%d\n",
|
||||
(sensor->exposure * sensor->xdpi) / ((1 << motor->steptype) *
|
||||
dev->sensor.optical_res),
|
||||
motor->vend1);*/
|
||||
(sensor->exposure * sensor->xdpi) / ((1 << motor->steptype) *
|
||||
dev->sensor.optical_res),
|
||||
motor->vend1); */
|
||||
|
||||
/* half_ccd if manual clock programming or dpi is half dpiset */
|
||||
half_ccd = sensor->half_ccd;
|
||||
|
@ -1353,9 +1353,9 @@ gl646_setup_registers (Genesys_Device * dev,
|
|||
|
||||
/* allow moving when buffer full by default */
|
||||
if (dev->model->is_sheetfed == SANE_FALSE)
|
||||
dev->reg[reg_0x02].value &= ~REG02_ACDCDIS;
|
||||
dev->reg[reg_0x02].value &= ~REG02_ACDCDIS;
|
||||
else
|
||||
dev->reg[reg_0x02].value |= REG02_ACDCDIS;
|
||||
dev->reg[reg_0x02].value |= REG02_ACDCDIS;
|
||||
|
||||
/* setup motor power */
|
||||
regs[reg_0x02].value |= REG02_MTRPWR;
|
||||
|
@ -1393,6 +1393,10 @@ gl646_setup_registers (Genesys_Device * dev,
|
|||
regs[reg_0x02].value |= REG02_AGOHOME;
|
||||
}
|
||||
|
||||
/* R03 */
|
||||
regs[reg_0x03].value &= ~REG03_AVEENB;
|
||||
/* regs[reg_0x03].value |= REG03_AVEENB; */
|
||||
|
||||
/* R04 */
|
||||
if (depth > 8)
|
||||
{
|
||||
|
@ -1619,8 +1623,15 @@ gl646_setup_registers (Genesys_Device * dev,
|
|||
gl646_set_double_reg (regs, REG_Z2MOD, z2);
|
||||
regs[reg_0x6b].value = motor->steps2;
|
||||
regs[reg_0x6c].value =
|
||||
(regs[reg_0x6c].
|
||||
value & REG6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16) & 0x07);
|
||||
(regs[reg_0x6c].value & REG6C_TGTIME) | ((z1 >> 13) & 0x38) | ((z2 >> 16)
|
||||
& 0x07);
|
||||
|
||||
/* the 3670 seems to behave differently regarding GPIO */
|
||||
/* TODO to be added in the sensor setting struct ?? */
|
||||
if (dev->model->ccd_type==CCD_HP3670)
|
||||
{
|
||||
dev->reg[reg_0x66].value = 0;
|
||||
}
|
||||
|
||||
RIE (write_control (dev, xresolution));
|
||||
|
||||
|
@ -1986,6 +1997,7 @@ gl646_init_regs (Genesys_Device * dev)
|
|||
dev->reg[reg_0x20].value = 0x20;
|
||||
break;
|
||||
case CCD_HP2400:
|
||||
case CCD_HP3670:
|
||||
dev->reg[reg_0x1e].value = 0x80;
|
||||
dev->reg[reg_0x1f].value = 0x10;
|
||||
dev->reg[reg_0x20].value = 0x20;
|
||||
|
@ -2064,6 +2076,11 @@ gl646_init_regs (Genesys_Device * dev)
|
|||
dev->reg[reg_0x6b].value = 0x08; /* table two steps number for acc/dec */
|
||||
dev->reg[reg_0x6d].value = 0x01; /* select deceleration steps whenever go home (0), accel/decel stop time (31 * LPeriod) */
|
||||
break;
|
||||
case MOTOR_HP3670:
|
||||
dev->reg[reg_0x6a].value = 0x41; /* table two steps number for acc/dec */
|
||||
dev->reg[reg_0x6b].value = 0xc8; /* table two steps number for acc/dec */
|
||||
dev->reg[reg_0x6d].value = 0x7f;
|
||||
break;
|
||||
default:
|
||||
dev->reg[reg_0x6a].value = 0x40; /* table two fast moving step type, PWM duty for table two */
|
||||
dev->reg[reg_0x6b].value = 0xff; /* table two steps number for acc/dec */
|
||||
|
@ -2238,30 +2255,34 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set)
|
|||
{
|
||||
status = sanei_genesys_fe_write_data (dev, 0x01, 0x02);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
DBG (DBG_error, "gl646_set_fe: writing data failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing data failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/* here starts AFE_SET */
|
||||
/* TODO : base this test on cfg reg3 or a CCD family flag to be created */
|
||||
/*if (dev->model->ccd_type != CCD_HP2300
|
||||
&& dev->model->ccd_type != CCD_HP2400) */
|
||||
{
|
||||
status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing reg0 failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
status = sanei_genesys_fe_write_data (dev, 0x02, dev->frontend.reg[2]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing reg2 failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
/* if (dev->model->ccd_type != CCD_HP2300
|
||||
&& dev->model->ccd_type != CCD_HP3670
|
||||
&& dev->model->ccd_type != CCD_HP2400) */
|
||||
{
|
||||
status = sanei_genesys_fe_write_data (dev, 0x00, dev->frontend.reg[0]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing reg0 failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
status = sanei_genesys_fe_write_data (dev, 0x02, dev->frontend.reg[2]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing reg2 failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* start with reg3 */
|
||||
status = sanei_genesys_fe_write_data (dev, 0x03, dev->frontend.reg[3]);
|
||||
|
@ -2309,26 +2330,28 @@ gl646_set_fe (Genesys_Device * dev, uint8_t set)
|
|||
}
|
||||
}
|
||||
break;
|
||||
/* STEF just can't have it to work, seems polarity is inversed
|
||||
case CCD_HP2300:
|
||||
status = sanei_genesys_fe_write_data (dev, 0x28, dev->frontend.gain[1]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing gain[1] failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
/* just can't have it to work ....
|
||||
case CCD_HP2300:
|
||||
case CCD_HP2400:
|
||||
case CCD_HP3670:
|
||||
|
||||
status =
|
||||
sanei_genesys_fe_write_data (dev, 0x23, dev->frontend.offset[1]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl646_set_fe: writing offset[1] failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
break; */
|
||||
status =
|
||||
sanei_genesys_fe_write_data (dev, 0x23, dev->frontend.offset[1]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"gl646_set_fe: writing offset[1] failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
status = sanei_genesys_fe_write_data (dev, 0x28, dev->frontend.gain[1]);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
{
|
||||
DBG (DBG_error, "gl646_set_fe: writing gain[1] failed: %s\n",
|
||||
sane_strstatus (status));
|
||||
return status;
|
||||
}
|
||||
break; */
|
||||
}
|
||||
|
||||
/* end with reg1 */
|
||||
|
@ -2754,7 +2777,7 @@ static SANE_Status
|
|||
gl646_eject_document (Genesys_Device * dev)
|
||||
{
|
||||
SANE_Status status = SANE_STATUS_GOOD;
|
||||
Genesys_Register_Set regs[7];
|
||||
Genesys_Register_Set regs[11];
|
||||
unsigned int used, vfinal, count;
|
||||
uint16_t slope_table[255];
|
||||
uint8_t val;
|
||||
|
@ -3346,7 +3369,7 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
|
|||
|
||||
/* when shading all line, we must adapt to half_ccd case */
|
||||
if ((dev->model->flags & GENESYS_FLAG_HALF_CCD_MODE)
|
||||
&& (dev->settings.xres <= dev->sensor.optical_res / 2))
|
||||
&& (dev->settings.xres < dev->sensor.optical_res / 2))
|
||||
{
|
||||
/* we are going to use half the pixel number */
|
||||
half_ccd = 2;
|
||||
|
@ -3359,7 +3382,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/half_ccd;
|
||||
settings.lines = dev->model->shading_lines;
|
||||
settings.depth = 16;
|
||||
settings.color_filter = dev->settings.color_filter;
|
||||
|
@ -3371,11 +3394,15 @@ gl646_init_regs_for_shading (Genesys_Device * dev)
|
|||
/* we don't want top offset, but we need right margin to be the same
|
||||
* than the one for the final scan */
|
||||
status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE);
|
||||
|
||||
/* used when sending shading calibration data */
|
||||
dev->calib_pixels = settings.pixels;
|
||||
|
||||
/* no shading */
|
||||
dev->reg[reg_0x01].value &= ~REG01_DVDSET;
|
||||
dev->reg[reg_0x02].value |= REG02_ACDCDIS; /* ease backtracking */
|
||||
dev->reg[reg_0x02].value &= ~(REG02_FASTFED | REG02_AGOHOME);
|
||||
dev->reg[reg_0x05].value &= ~REG05_GMMENB;
|
||||
gl646_set_motor_power (dev->reg, SANE_FALSE);
|
||||
|
||||
/* TODO another flag to setup regs ? */
|
||||
|
@ -3760,7 +3787,14 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
|
||||
/* setup for a RGB scan, one full sensor's width line */
|
||||
/* resolution is the one from the final scan */
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, 150, SANE_TRUE);
|
||||
if (dev->settings.xres > dev->sensor.optical_res)
|
||||
{
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, SANE_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, dev->settings.xres, SANE_TRUE);
|
||||
}
|
||||
channels = 3;
|
||||
black_pixels =
|
||||
(dev->sensor.black_pixels * resolution) / dev->sensor.optical_res;
|
||||
|
@ -3788,7 +3822,10 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
dev->frontend.gain[2] = 0;
|
||||
|
||||
/* scan with no move */
|
||||
bottom = 90;
|
||||
if (dev->model->ccd_type == CIS_XP200)
|
||||
bottom = 4;
|
||||
else
|
||||
bottom = 90;
|
||||
dev->frontend.offset[0] = bottom;
|
||||
dev->frontend.offset[1] = bottom;
|
||||
dev->frontend.offset[2] = bottom;
|
||||
|
@ -3801,7 +3838,8 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
}
|
||||
if (DBG_LEVEL >= DBG_data)
|
||||
{
|
||||
sanei_genesys_write_pnm_file ("offset000.pnm", first_line, 8, channels,
|
||||
sprintf (title, "offset%03d.pnm", bottom);
|
||||
sanei_genesys_write_pnm_file (title, first_line, 8, channels,
|
||||
settings.pixels, settings.lines);
|
||||
}
|
||||
bottomavg =
|
||||
|
@ -3810,7 +3848,10 @@ gl646_offset_calibration (Genesys_Device * dev)
|
|||
free (first_line);
|
||||
|
||||
/* now top value */
|
||||
top = 231;
|
||||
if (dev->model->ccd_type == CIS_XP200)
|
||||
top=0x80;
|
||||
else
|
||||
top = 231;
|
||||
dev->frontend.offset[0] = top;
|
||||
dev->frontend.offset[1] = top;
|
||||
dev->frontend.offset[2] = top;
|
||||
|
@ -3922,7 +3963,17 @@ gl646_coarse_gain_calibration (Genesys_Device * dev, int dpi)
|
|||
/* setup for a RGB scan, one full sensor's width line */
|
||||
/* resolution is the one from the final scan */
|
||||
channels = 3;
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, 150, SANE_TRUE);
|
||||
/* XXX STEF XXX resolution = get_closest_resolution (dev->model->ccd_type, 150, SANE_TRUE); */
|
||||
|
||||
/* we are searching a sensor resolution */
|
||||
if (dev->settings.xres > dev->sensor.optical_res)
|
||||
{
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, dev->sensor.optical_res, SANE_TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, dev->settings.xres, SANE_TRUE);
|
||||
}
|
||||
|
||||
settings.scan_method = SCAN_METHOD_FLATBED;
|
||||
settings.scan_mode = SCAN_MODE_COLOR;
|
||||
|
@ -4061,7 +4112,6 @@ gl646_init_regs_for_warmup (Genesys_Device * dev,
|
|||
|
||||
DBG (DBG_proc, "gl646_init_regs_for_warmup: start\n");
|
||||
|
||||
/* we scan at sensor maximum resolution */
|
||||
resolution = get_closest_resolution (dev->model->ccd_type, 300, SANE_FALSE);
|
||||
|
||||
/* set up for a half width 2 lines color scan without moving */
|
||||
|
@ -4285,9 +4335,8 @@ gl646_init (Genesys_Device * dev)
|
|||
"gl646_init: could not allocate memory for gamma table\n");
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
sanei_genesys_create_gamma_table (dev->sensor.
|
||||
green_gamma_table, size,
|
||||
size - 1, size - 1,
|
||||
sanei_genesys_create_gamma_table (dev->sensor.green_gamma_table,
|
||||
size, size - 1, size - 1,
|
||||
dev->sensor.green_gamma);
|
||||
}
|
||||
if (dev->sensor.blue_gamma_table == NULL)
|
||||
|
@ -4299,9 +4348,8 @@ gl646_init (Genesys_Device * dev)
|
|||
"gl646_init: could not allocate memory for gamma table\n");
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
sanei_genesys_create_gamma_table (dev->sensor.
|
||||
blue_gamma_table, size,
|
||||
size - 1, size - 1,
|
||||
sanei_genesys_create_gamma_table (dev->sensor.blue_gamma_table,
|
||||
size, size - 1, size - 1,
|
||||
dev->sensor.blue_gamma);
|
||||
}
|
||||
|
||||
|
@ -4484,8 +4532,9 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
unsigned char **data)
|
||||
{
|
||||
SANE_Status status;
|
||||
unsigned int size, lines;
|
||||
unsigned int size, lines, x, y, bpp, pixels;
|
||||
SANE_Bool empty;
|
||||
unsigned char *buffer;
|
||||
|
||||
DBG (DBG_proc, "simple_scan: starting\n");
|
||||
status = setup_for_scan (dev, settings, SANE_TRUE, SANE_FALSE, SANE_FALSE);
|
||||
|
@ -4497,10 +4546,20 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
}
|
||||
|
||||
/* allocate memory fo scan : LINCNT may have been adjusted for CCD reordering */
|
||||
lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) + 1;
|
||||
if (dev->model->is_cis == SANE_TRUE)
|
||||
{
|
||||
lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) / 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
lines = gl646_get_triple_reg (dev->reg, REG_LINCNT) + 1;
|
||||
}
|
||||
size = lines * settings.pixels;
|
||||
if (settings.depth == 16)
|
||||
size *= 2;
|
||||
bpp = 2;
|
||||
else
|
||||
bpp = 1;
|
||||
size *= bpp;
|
||||
if (dev->settings.scan_mode == SCAN_MODE_COLOR) /* single pass color */
|
||||
size *= 3;
|
||||
*data = malloc (size);
|
||||
|
@ -4525,18 +4584,15 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
/* no shading correction and not wathc dog for simple scan */
|
||||
dev->reg[reg_0x01].value &= ~(REG01_DVDSET | REG01_DOGENB);
|
||||
|
||||
/* clear motor power flag if no move */
|
||||
if (move == SANE_FALSE)
|
||||
{
|
||||
dev->reg[reg_0x02].value &= ~REG02_MTRPWR;
|
||||
}
|
||||
|
||||
/* one table movement for simple scan */
|
||||
dev->reg[reg_0x02].value &= ~REG02_FASTFED;
|
||||
|
||||
/* no automatic go home if no movement */
|
||||
if (move == SANE_FALSE)
|
||||
{
|
||||
/* clear motor power flag if no move */
|
||||
dev->reg[reg_0x02].value &= ~REG02_MTRPWR;
|
||||
|
||||
/* no automatic go home if no movement */
|
||||
dev->reg[reg_0x02].value &= ~REG02_AGOHOME;
|
||||
}
|
||||
|
||||
|
@ -4579,6 +4635,61 @@ simple_scan (Genesys_Device * dev, Genesys_Settings settings, SANE_Bool move,
|
|||
return status;
|
||||
}
|
||||
|
||||
/* in case of CIS scanner, we must reorder data */
|
||||
if (dev->model->is_cis == SANE_TRUE
|
||||
&& settings.scan_mode == SCAN_MODE_COLOR)
|
||||
{
|
||||
/* alloc one line sized working buffer */
|
||||
size = size / settings.lines;
|
||||
buffer = (unsigned char *) malloc (size);
|
||||
if (buffer == NULL)
|
||||
{
|
||||
DBG (DBG_error,
|
||||
"simple_scan: failed to allocate %d bytes of memory\n", size);
|
||||
return SANE_STATUS_NO_MEM;
|
||||
}
|
||||
|
||||
/* reorder one line of data and put it back to buffer */
|
||||
if (bpp == 1)
|
||||
{
|
||||
for (y = 0; y < settings.lines; y++)
|
||||
{
|
||||
/* reorder line */
|
||||
for (x = 0; x < settings.pixels; x++)
|
||||
{
|
||||
buffer[x * 3] = (*data)[y * size + x];
|
||||
buffer[x * 3 + 1] = (*data)[y * size + settings.pixels + x];
|
||||
buffer[x * 3 + 2] =
|
||||
(*data)[y * size + 2 * settings.pixels + x];
|
||||
}
|
||||
/* copy line back */
|
||||
memcpy ((*data) + size * y, buffer, size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (y = 0; y < settings.lines; y++)
|
||||
{
|
||||
/* reorder line */
|
||||
for (x = 0; x < settings.pixels; x++)
|
||||
{
|
||||
buffer[x * 6] = (*data)[y * size + x];
|
||||
buffer[x * 6 + 1] = (*data)[y * size + x + 1];
|
||||
buffer[x * 6 + 2] = (*data)[y * size + settings.pixels + x];
|
||||
buffer[x * 6 + 3] =
|
||||
(*data)[y * size + settings.pixels + x + 1];
|
||||
buffer[x * 6 + 4] =
|
||||
(*data)[y * size + 2 * settings.pixels + x];
|
||||
buffer[x * 6 + 5] =
|
||||
(*data)[y * size + 2 * settings.pixels + x + 1];
|
||||
}
|
||||
/* copy line back */
|
||||
memcpy ((*data) + size * y, buffer, size);
|
||||
}
|
||||
}
|
||||
free (buffer);
|
||||
}
|
||||
|
||||
/* end scan , waiting the motor to stop if needed (if moving), but without ejecting doc */
|
||||
status = end_scan (dev, dev->reg, SANE_TRUE, SANE_FALSE);
|
||||
if (status != SANE_STATUS_GOOD)
|
||||
|
@ -4757,11 +4868,11 @@ write_control (Genesys_Device * dev, int resolution)
|
|||
break;
|
||||
case MOTOR_5345:
|
||||
case MOTOR_HP3670:
|
||||
default:
|
||||
control[0] = dev->control[2];
|
||||
control[1] = dev->control[3];
|
||||
control[2] = dev->control[4];
|
||||
control[3] = dev->control[5];
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue