kopia lustrzana https://gitlab.com/sane-project/backends
epjitsu backend v26
- add resolution scaling - fix 150 dpi settings for fi-60F and fi-65F - make adf_height_padding variable - make white_factor variablemerge-requests/1/head
rodzic
b0133c1ed2
commit
683f6d71f4
|
@ -48,29 +48,45 @@ static unsigned char coarseCalData_S1100[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** fi-60F 150dpi *************/
|
/*************** fi-60F 150dpi *************/
|
||||||
/* 1b d1 (set window) before coarse cal (read 1 line of 0x____ bytes) */
|
/* 1b d1 (set window) before coarse cal (read 1 line of 0x1c20 bytes) */
|
||||||
static unsigned char setWindowCoarseCal_FI60F_150[] = {
|
static unsigned char setWindowCoarseCal_FI60F_150[] = {
|
||||||
0
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
|
||||||
|
0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
/* 1b d1 (set window) before fine cal (read 16 lines of 0x____ bytes) */
|
/* 1b d1 (set window) before fine cal (read 16 lines of 0x1c20 bytes) */
|
||||||
static unsigned char setWindowFineCal_FI60F_150[] = {
|
static unsigned char setWindowFineCal_FI60F_150[] = {
|
||||||
0
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
|
||||||
|
0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x80, 0x80, 0x00, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x____ bytes) */
|
/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x3840 bytes) */
|
||||||
static unsigned char setWindowSendCal_FI60F_150[] = {
|
static unsigned char setWindowSendCal_FI60F_150[] = {
|
||||||
0
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
|
||||||
|
0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
/* 1b c3 (gain?) command header */
|
/* 1b c3 (gain?) command header */
|
||||||
static unsigned char sendCal1Header_FI60F_150[] = {
|
static unsigned char sendCal1Header_FI60F_150[] = { /* plus 0x3840 data bytes */
|
||||||
0
|
0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x8c, 0x0f, 0x00, 0x04
|
||||||
};
|
};
|
||||||
/* 1b c4 (offset?) command header */
|
/* 1b c4 (offset?) command header */
|
||||||
static unsigned char sendCal2Header_FI60F_150[] = {
|
static unsigned char sendCal2Header_FI60F_150[] = {
|
||||||
0
|
0x39, 0x3f, 0x39, 0x3f, 0x39, 0x3f, 0x07
|
||||||
};
|
};
|
||||||
/* 1b d1 (set window) before scan */
|
/* 1b d1 (set window) before scan */
|
||||||
static unsigned char setWindowScan_FI60F_150[] = {
|
static unsigned char setWindowScan_FI60F_150[] = {
|
||||||
0
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x2c, 0x00, 0x96, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x60, 0x00, 0x00, 0x03, 0x6b, 0x00, 0x00,
|
||||||
|
0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x80, 0x80, 0x01, 0x48, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************** fi-60F 300dpi *************/
|
/*************** fi-60F 300dpi *************/
|
||||||
|
|
|
@ -141,6 +141,11 @@
|
||||||
v25 2014-06-04, MAN
|
v25 2014-06-04, MAN
|
||||||
- initial support for fi-65F
|
- initial support for fi-65F
|
||||||
- initial support for S1100
|
- initial support for S1100
|
||||||
|
v26 2014-06-28, MAN
|
||||||
|
- add resolution scaling
|
||||||
|
- fix 150 dpi settings for fi-60F and fi-65F
|
||||||
|
- make adf_height_padding variable
|
||||||
|
- make white_factor variable
|
||||||
|
|
||||||
SANE FLOW DIAGRAM
|
SANE FLOW DIAGRAM
|
||||||
|
|
||||||
|
@ -189,7 +194,7 @@
|
||||||
#include "epjitsu-cmd.h"
|
#include "epjitsu-cmd.h"
|
||||||
|
|
||||||
#define DEBUG 1
|
#define DEBUG 1
|
||||||
#define BUILD 25
|
#define BUILD 26
|
||||||
|
|
||||||
#ifndef MAX3
|
#ifndef MAX3
|
||||||
#define MAX3(a,b,c) ((a) > (b) ? ((a) > (c) ? a : c) : ((b) > (c) ? b : c))
|
#define MAX3(a,b,c) ((a) > (b) ? ((a) > (c) ? a : c) : ((b) > (c) ? b : c))
|
||||||
|
@ -212,7 +217,6 @@ unsigned char global_firmware_filename[PATH_MAX];
|
||||||
static int coarse_gain_min[3] = { 88, 88, 88 }; /* front, back, FI-60F 3rd plane */
|
static int coarse_gain_min[3] = { 88, 88, 88 }; /* front, back, FI-60F 3rd plane */
|
||||||
static int coarse_gain_max[3] = { 92, 92, 92 };
|
static int coarse_gain_max[3] = { 92, 92, 92 };
|
||||||
static int fine_gain_target[3] = {185, 150, 170}; /* front, back, FI-60F is this ok? */
|
static int fine_gain_target[3] = {185, 150, 170}; /* front, back, FI-60F is this ok? */
|
||||||
static float white_factor[3] = {1.0, 0.93, 0.98}; /* Blue, Red, Green */
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
#define STRING_FLATBED SANE_I18N("Flatbed")
|
#define STRING_FLATBED SANE_I18N("Flatbed")
|
||||||
|
@ -224,8 +228,6 @@ static float white_factor[3] = {1.0, 0.93, 0.98}; /* Blue, Red, Green */
|
||||||
#define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY
|
#define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY
|
||||||
#define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR
|
#define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR
|
||||||
|
|
||||||
#define ADF_HEIGHT_PADDING 600
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* used by attach* and sane_get_devices
|
* used by attach* and sane_get_devices
|
||||||
* a ptr to a null term array of ptrs to SANE_Device structs
|
* a ptr to a null term array of ptrs to SANE_Device structs
|
||||||
|
@ -490,18 +492,17 @@ attach_one (const char *name)
|
||||||
|
|
||||||
s->has_adf = 1;
|
s->has_adf = 1;
|
||||||
s->has_adf_duplex = 1;
|
s->has_adf_duplex = 1;
|
||||||
s->x_res_150 = 1;
|
s->min_res = 50;
|
||||||
s->x_res_225 = 1;
|
s->max_res = 600;
|
||||||
s->x_res_300 = 1;
|
s->adf_height_padding = 600;
|
||||||
s->x_res_600 = 1;
|
/* Blue, Red, Green */
|
||||||
s->y_res_150 = 1;
|
s->white_factor[0] = 1.0;
|
||||||
s->y_res_225 = 1;
|
s->white_factor[1] = 0.93;
|
||||||
s->y_res_300 = 1;
|
s->white_factor[2] = 0.98;
|
||||||
s->y_res_600 = 1;
|
|
||||||
|
|
||||||
s->source = SOURCE_ADF_FRONT;
|
s->source = SOURCE_ADF_FRONT;
|
||||||
s->mode = MODE_LINEART;
|
s->mode = MODE_LINEART;
|
||||||
s->resolution_x = 300;
|
s->resolution = 300;
|
||||||
s->page_height = 11.5 * 1200;
|
s->page_height = 11.5 * 1200;
|
||||||
s->page_width = 8.5 * 1200;
|
s->page_width = 8.5 * 1200;
|
||||||
|
|
||||||
|
@ -523,18 +524,17 @@ attach_one (const char *name)
|
||||||
|
|
||||||
s->has_adf = 1;
|
s->has_adf = 1;
|
||||||
s->has_adf_duplex = 1;
|
s->has_adf_duplex = 1;
|
||||||
s->x_res_150 = 1;
|
s->min_res = 50;
|
||||||
s->x_res_225 = 1;
|
s->max_res = 600;
|
||||||
s->x_res_300 = 1;
|
s->adf_height_padding = 600;
|
||||||
s->x_res_600 = 1;
|
/* Blue, Red, Green */
|
||||||
s->y_res_150 = 1;
|
s->white_factor[0] = 1.0;
|
||||||
s->y_res_225 = 1;
|
s->white_factor[1] = 0.93;
|
||||||
s->y_res_300 = 1;
|
s->white_factor[2] = 0.98;
|
||||||
s->y_res_600 = 1;
|
|
||||||
|
|
||||||
s->source = SOURCE_ADF_FRONT;
|
s->source = SOURCE_ADF_FRONT;
|
||||||
s->mode = MODE_LINEART;
|
s->mode = MODE_LINEART;
|
||||||
s->resolution_x = 300;
|
s->resolution = 300;
|
||||||
s->page_height = 11.5 * 1200;
|
s->page_height = 11.5 * 1200;
|
||||||
s->page_width = 8.5 * 1200;
|
s->page_width = 8.5 * 1200;
|
||||||
|
|
||||||
|
@ -548,18 +548,17 @@ attach_one (const char *name)
|
||||||
s->usb_power = 1;
|
s->usb_power = 1;
|
||||||
s->has_adf = 1;
|
s->has_adf = 1;
|
||||||
s->has_adf_duplex = 0;
|
s->has_adf_duplex = 0;
|
||||||
s->x_res_150 = 0;
|
s->min_res = 50;
|
||||||
s->x_res_225 = 0;
|
s->max_res = 600;
|
||||||
s->x_res_300 = 1;
|
s->adf_height_padding = 450;
|
||||||
s->x_res_600 = 1;
|
/* Blue, Red, Green */
|
||||||
s->y_res_150 = 0;
|
s->white_factor[0] = 0.95;
|
||||||
s->y_res_225 = 0;
|
s->white_factor[1] = 1.0;
|
||||||
s->y_res_300 = 1;
|
s->white_factor[2] = 1.0;
|
||||||
s->y_res_600 = 1;
|
|
||||||
|
|
||||||
s->source = SOURCE_ADF_FRONT;
|
s->source = SOURCE_ADF_FRONT;
|
||||||
s->mode = MODE_LINEART;
|
s->mode = MODE_LINEART;
|
||||||
s->resolution_x = 300;
|
s->resolution = 300;
|
||||||
s->page_height = 11.5 * 1200;
|
s->page_height = 11.5 * 1200;
|
||||||
s->page_width = 8.5 * 1200;
|
s->page_width = 8.5 * 1200;
|
||||||
|
|
||||||
|
@ -572,16 +571,16 @@ attach_one (const char *name)
|
||||||
s->model = MODEL_FI60F;
|
s->model = MODEL_FI60F;
|
||||||
|
|
||||||
s->has_fb = 1;
|
s->has_fb = 1;
|
||||||
s->x_res_150 = 0;
|
s->min_res = 50;
|
||||||
s->x_res_300 = 1;
|
s->max_res = 600;
|
||||||
s->x_res_600 = 1;
|
/* Blue, Red, Green */
|
||||||
s->y_res_150 = 0;
|
s->white_factor[0] = 1.0;
|
||||||
s->y_res_300 = 1;
|
s->white_factor[1] = 0.93;
|
||||||
s->y_res_600 = 1;
|
s->white_factor[2] = 0.98;
|
||||||
|
|
||||||
s->source = SOURCE_FLATBED;
|
s->source = SOURCE_FLATBED;
|
||||||
s->mode = MODE_COLOR;
|
s->mode = MODE_COLOR;
|
||||||
s->resolution_x = 300;
|
s->resolution = 300;
|
||||||
s->page_height = 5.83 * 1200;
|
s->page_height = 5.83 * 1200;
|
||||||
s->page_width = 4.1 * 1200;
|
s->page_width = 4.1 * 1200;
|
||||||
|
|
||||||
|
@ -595,16 +594,16 @@ attach_one (const char *name)
|
||||||
s->model = MODEL_FI65F;
|
s->model = MODEL_FI65F;
|
||||||
|
|
||||||
s->has_fb = 1;
|
s->has_fb = 1;
|
||||||
s->x_res_150 = 0;
|
s->min_res = 50;
|
||||||
s->x_res_300 = 1;
|
s->max_res = 600;
|
||||||
s->x_res_600 = 1;
|
/* Blue, Red, Green */
|
||||||
s->y_res_150 = 0;
|
s->white_factor[0] = 1.0;
|
||||||
s->y_res_300 = 1;
|
s->white_factor[1] = 0.93;
|
||||||
s->y_res_600 = 1;
|
s->white_factor[2] = 0.98;
|
||||||
|
|
||||||
s->source = SOURCE_FLATBED;
|
s->source = SOURCE_FLATBED;
|
||||||
s->mode = MODE_COLOR;
|
s->mode = MODE_COLOR;
|
||||||
s->resolution_x = 300;
|
s->resolution = 300;
|
||||||
s->page_height = 5.83 * 1200;
|
s->page_height = 5.83 * 1200;
|
||||||
s->page_width = 4.1 * 1200;
|
s->page_width = 4.1 * 1200;
|
||||||
|
|
||||||
|
@ -1089,33 +1088,19 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(option==OPT_X_RES){
|
else if(option==OPT_RES){
|
||||||
i=0;
|
|
||||||
if(s->x_res_150){
|
|
||||||
s->x_res_list[++i] = 150;
|
|
||||||
}
|
|
||||||
if(s->x_res_225){
|
|
||||||
s->x_res_list[++i] = 225;
|
|
||||||
}
|
|
||||||
if(s->x_res_300){
|
|
||||||
s->x_res_list[++i] = 300;
|
|
||||||
}
|
|
||||||
if(s->x_res_600){
|
|
||||||
s->x_res_list[++i] = 600;
|
|
||||||
}
|
|
||||||
s->x_res_list[0] = i;
|
|
||||||
|
|
||||||
opt->name = SANE_NAME_SCAN_RESOLUTION;
|
opt->name = SANE_NAME_SCAN_RESOLUTION;
|
||||||
opt->title = SANE_TITLE_SCAN_X_RESOLUTION;
|
opt->title = SANE_TITLE_SCAN_RESOLUTION;
|
||||||
opt->desc = SANE_DESC_SCAN_X_RESOLUTION;
|
opt->desc = SANE_DESC_SCAN_RESOLUTION;
|
||||||
opt->type = SANE_TYPE_INT;
|
opt->type = SANE_TYPE_INT;
|
||||||
opt->unit = SANE_UNIT_DPI;
|
opt->unit = SANE_UNIT_DPI;
|
||||||
if(i > 1){
|
|
||||||
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||||||
}
|
|
||||||
|
|
||||||
opt->constraint_type = SANE_CONSTRAINT_WORD_LIST;
|
s->res_range.min = s->min_res;
|
||||||
opt->constraint.word_list = s->x_res_list;
|
s->res_range.max = s->max_res;
|
||||||
|
s->res_range.quant = 1;
|
||||||
|
opt->constraint_type = SANE_CONSTRAINT_RANGE;
|
||||||
|
opt->constraint.range = &s->res_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* "Geometry" group ---------------------------------------------------- */
|
/* "Geometry" group ---------------------------------------------------- */
|
||||||
|
@ -1525,8 +1510,8 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
||||||
}
|
}
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
case OPT_X_RES:
|
case OPT_RES:
|
||||||
*val_p = s->resolution_x;
|
*val_p = s->resolution;
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
case OPT_TL_X:
|
case OPT_TL_X:
|
||||||
|
@ -1673,17 +1658,17 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
|
||||||
|
|
||||||
s->mode = tmp;
|
s->mode = tmp;
|
||||||
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||||
return change_params(s);
|
|
||||||
|
|
||||||
case OPT_X_RES:
|
|
||||||
|
|
||||||
if (s->resolution_x == val_c)
|
|
||||||
return SANE_STATUS_GOOD;
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
s->resolution_x = val_c;
|
case OPT_RES:
|
||||||
|
|
||||||
|
if (s->resolution == val_c)
|
||||||
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
|
s->resolution = val_c;
|
||||||
|
|
||||||
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
*info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
|
||||||
return change_params(s);
|
return SANE_STATUS_GOOD;
|
||||||
|
|
||||||
/* Geometry Group */
|
/* Geometry Group */
|
||||||
case OPT_TL_X:
|
case OPT_TL_X:
|
||||||
|
@ -1902,7 +1887,7 @@ static struct model_res settings[] = {
|
||||||
|
|
||||||
/*fi-60F*/
|
/*fi-60F*/
|
||||||
/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */
|
/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */
|
||||||
{ MODEL_FI60F, 150, 150, 0, 648, 32, 875, 32, 1480*3, 632*3, 216, 41, 1480*3, 632*3, 216,
|
{ MODEL_FI60F, 300, 150, 0, 1296, 32, 875, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432,
|
||||||
setWindowCoarseCal_FI60F_150, setWindowFineCal_FI60F_150,
|
setWindowCoarseCal_FI60F_150, setWindowFineCal_FI60F_150,
|
||||||
setWindowSendCal_FI60F_150, sendCal1Header_FI60F_150,
|
setWindowSendCal_FI60F_150, sendCal1Header_FI60F_150,
|
||||||
sendCal2Header_FI60F_150, setWindowScan_FI60F_150 },
|
sendCal2Header_FI60F_150, setWindowScan_FI60F_150 },
|
||||||
|
@ -1919,7 +1904,7 @@ static struct model_res settings[] = {
|
||||||
|
|
||||||
/*fi-65F*/
|
/*fi-65F*/
|
||||||
/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */
|
/* model xres yres u mxx mnx mxy mny lin_s pln_s pln_w bh cls cps cpw */
|
||||||
{ MODEL_FI65F, 150, 150, 0, 648, 32, 875, 32, 1480*3, 632*3, 216, 41, 1480*3, 632*3, 216,
|
{ MODEL_FI65F, 300, 150, 0, 1296, 32, 875, 32, 2400*3, 958*3, 432, 72, 2400*3, 958*3, 432,
|
||||||
setWindowCoarseCal_FI60F_150, setWindowFineCal_FI60F_150,
|
setWindowCoarseCal_FI60F_150, setWindowFineCal_FI60F_150,
|
||||||
setWindowSendCal_FI60F_150, sendCal1Header_FI60F_150,
|
setWindowSendCal_FI60F_150, sendCal1Header_FI60F_150,
|
||||||
sendCal2Header_FI60F_150, setWindowScan_FI60F_150 },
|
sendCal2Header_FI60F_150, setWindowScan_FI60F_150 },
|
||||||
|
@ -1966,9 +1951,10 @@ change_params(struct scanner *s)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(settings[i].model == s->model
|
if(settings[i].model == s->model
|
||||||
&& settings[i].x_res == s->resolution_x
|
&& settings[i].x_res >= s->resolution
|
||||||
&& settings[i].usb_power == s->usb_power)
|
&& settings[i].y_res >= s->resolution
|
||||||
{
|
&& settings[i].usb_power == s->usb_power
|
||||||
|
){
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -1978,14 +1964,16 @@ change_params(struct scanner *s)
|
||||||
return SANE_STATUS_INVAL;
|
return SANE_STATUS_INVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*pull in closest y resolution*/
|
|
||||||
s->resolution_y = settings[i].y_res;
|
|
||||||
|
|
||||||
/*1200 dpi*/
|
/*1200 dpi*/
|
||||||
s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, s->resolution_x );
|
s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, settings[i].x_res );
|
||||||
s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, s->resolution_x );
|
s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, settings[i].x_res );
|
||||||
s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, s->resolution_y );
|
s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, settings[i].y_res );
|
||||||
s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, s->resolution_y );
|
s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, settings[i].y_res );
|
||||||
|
|
||||||
|
/* wrong place for this?*/
|
||||||
|
s->page_width = s->max_x;
|
||||||
|
s->br_x = s->max_x;
|
||||||
|
s->br_y = s->max_y;
|
||||||
|
|
||||||
/*current dpi*/
|
/*current dpi*/
|
||||||
s->setWindowCoarseCal = settings[i].sw_coarsecal;
|
s->setWindowCoarseCal = settings[i].sw_coarsecal;
|
||||||
|
@ -2023,28 +2011,15 @@ change_params(struct scanner *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* height */
|
/* height */
|
||||||
if (s->model == MODEL_S300 || s->model == MODEL_S1300i)
|
|
||||||
{
|
|
||||||
if (s->tl_y > s->max_y - s->min_y)
|
if (s->tl_y > s->max_y - s->min_y)
|
||||||
s->tl_y = s->max_y - s->min_y - ADF_HEIGHT_PADDING;
|
s->tl_y = s->max_y - s->min_y - s->adf_height_padding;
|
||||||
if (s->tl_y + s->page_height > s->max_y - ADF_HEIGHT_PADDING)
|
if (s->tl_y + s->page_height > s->max_y - s->adf_height_padding)
|
||||||
s->page_height = s->max_y - ADF_HEIGHT_PADDING - s->tl_y;
|
s->page_height = s->max_y - s->adf_height_padding - s->tl_y;
|
||||||
if (s->page_height < s->min_y && s->page_height > 0)
|
if (s->page_height < s->min_y && s->page_height > 0)
|
||||||
s->page_height = s->min_y;
|
s->page_height = s->min_y;
|
||||||
if (s->tl_y + s->page_height > s->max_y)
|
if (s->tl_y + s->page_height > s->max_y)
|
||||||
s->tl_y = s->max_y - ADF_HEIGHT_PADDING - s->page_height ;
|
s->tl_y = s->max_y - s->adf_height_padding - s->page_height ;
|
||||||
}
|
|
||||||
else /* MODEL_S1100 or MODEL_FI60F or MODEL_FI65F */
|
|
||||||
{
|
|
||||||
if (s->tl_y > s->max_y - s->min_y)
|
|
||||||
s->tl_y = s->max_y - s->min_y;
|
|
||||||
if (s->tl_y + s->page_height > s->max_y)
|
|
||||||
s->page_height = s->max_y - s->tl_y;
|
|
||||||
if (s->page_height < s->min_y && s->page_height > 0)
|
|
||||||
s->page_height = s->min_y;
|
|
||||||
if (s->tl_y + s->page_height > s->max_y)
|
|
||||||
s->tl_y = s->max_y - s->page_height ;
|
|
||||||
}
|
|
||||||
if (s->page_height > 0) {
|
if (s->page_height > 0) {
|
||||||
s->br_y = s->tl_y + s->page_height;
|
s->br_y = s->tl_y + s->page_height;
|
||||||
}
|
}
|
||||||
|
@ -2067,6 +2042,8 @@ change_params(struct scanner *s)
|
||||||
s->cal_image.line_stride = settings[i].cal_line_stride;
|
s->cal_image.line_stride = settings[i].cal_line_stride;
|
||||||
s->cal_image.plane_stride = settings[i].cal_plane_stride;
|
s->cal_image.plane_stride = settings[i].cal_plane_stride;
|
||||||
s->cal_image.plane_width = settings[i].cal_plane_width;
|
s->cal_image.plane_width = settings[i].cal_plane_width;
|
||||||
|
s->cal_image.x_res = settings[i].x_res;
|
||||||
|
s->cal_image.y_res = settings[i].y_res;
|
||||||
s->cal_image.raw_data = NULL;
|
s->cal_image.raw_data = NULL;
|
||||||
s->cal_image.image = NULL;
|
s->cal_image.image = NULL;
|
||||||
|
|
||||||
|
@ -2074,6 +2051,8 @@ change_params(struct scanner *s)
|
||||||
s->cal_data.line_stride = settings[i].cal_line_stride * 2;
|
s->cal_data.line_stride = settings[i].cal_line_stride * 2;
|
||||||
s->cal_data.plane_stride = settings[i].cal_plane_stride * 2;
|
s->cal_data.plane_stride = settings[i].cal_plane_stride * 2;
|
||||||
s->cal_data.plane_width = settings[i].cal_plane_width;
|
s->cal_data.plane_width = settings[i].cal_plane_width;
|
||||||
|
s->cal_data.x_res = settings[i].x_res;
|
||||||
|
s->cal_data.y_res = settings[i].y_res;
|
||||||
s->cal_data.raw_data = NULL;
|
s->cal_data.raw_data = NULL;
|
||||||
s->cal_data.image = &s->sendcal;
|
s->cal_data.image = &s->sendcal;
|
||||||
|
|
||||||
|
@ -2082,14 +2061,20 @@ change_params(struct scanner *s)
|
||||||
s->block_xfr.line_stride = settings[i].line_stride;
|
s->block_xfr.line_stride = settings[i].line_stride;
|
||||||
s->block_xfr.plane_stride = settings[i].plane_stride;
|
s->block_xfr.plane_stride = settings[i].plane_stride;
|
||||||
s->block_xfr.plane_width = settings[i].plane_width;
|
s->block_xfr.plane_width = settings[i].plane_width;
|
||||||
|
s->block_xfr.x_res = settings[i].x_res;
|
||||||
|
s->block_xfr.y_res = settings[i].y_res;
|
||||||
s->block_xfr.raw_data = NULL;
|
s->block_xfr.raw_data = NULL;
|
||||||
s->block_xfr.image = &s->block_img;
|
s->block_xfr.image = &s->block_img;
|
||||||
|
|
||||||
/* set up the block image used during scanning operation */
|
/* set up the block image used during scanning operation */
|
||||||
width = s->block_xfr.plane_width * img_heads;
|
/* note that this is the same width/x_res as the final output image */
|
||||||
|
/* but the height/y_res are the same as block_xfr */
|
||||||
|
width = (s->block_xfr.plane_width*s->resolution/settings[i].x_res) * img_heads;
|
||||||
s->block_img.width_pix = width;
|
s->block_img.width_pix = width;
|
||||||
s->block_img.width_bytes = width * 3;
|
s->block_img.width_bytes = width * 3;
|
||||||
s->block_img.height = settings[i].block_height;
|
s->block_img.height = settings[i].block_height;
|
||||||
|
s->block_img.x_res = s->resolution;
|
||||||
|
s->block_img.y_res = settings[i].y_res;
|
||||||
s->block_img.pages = img_pages;
|
s->block_img.pages = img_pages;
|
||||||
s->block_img.buffer = NULL;
|
s->block_img.buffer = NULL;
|
||||||
|
|
||||||
|
@ -2098,6 +2083,8 @@ change_params(struct scanner *s)
|
||||||
s->coarsecal.width_pix = s->darkcal.width_pix = s->lightcal.width_pix = width;
|
s->coarsecal.width_pix = s->darkcal.width_pix = s->lightcal.width_pix = width;
|
||||||
s->coarsecal.width_bytes = s->darkcal.width_bytes = s->lightcal.width_bytes = width * 3;
|
s->coarsecal.width_bytes = s->darkcal.width_bytes = s->lightcal.width_bytes = width * 3;
|
||||||
s->coarsecal.height = 1;
|
s->coarsecal.height = 1;
|
||||||
|
s->coarsecal.x_res = s->darkcal.x_res = s->lightcal.x_res = settings[i].x_res;
|
||||||
|
s->coarsecal.y_res = s->darkcal.y_res = s->lightcal.y_res = settings[i].y_res;
|
||||||
s->darkcal.height = s->lightcal.height = 16;
|
s->darkcal.height = s->lightcal.height = 16;
|
||||||
s->coarsecal.pages = s->darkcal.pages = s->lightcal.pages = img_pages;
|
s->coarsecal.pages = s->darkcal.pages = s->lightcal.pages = img_pages;
|
||||||
s->coarsecal.buffer = s->darkcal.buffer = s->lightcal.buffer = NULL;
|
s->coarsecal.buffer = s->darkcal.buffer = s->lightcal.buffer = NULL;
|
||||||
|
@ -2107,24 +2094,47 @@ change_params(struct scanner *s)
|
||||||
s->sendcal.width_pix = width;
|
s->sendcal.width_pix = width;
|
||||||
s->sendcal.width_bytes = width * 6; /* 2 bytes of cal data per pixel component */
|
s->sendcal.width_bytes = width * 6; /* 2 bytes of cal data per pixel component */
|
||||||
s->sendcal.height = 1;
|
s->sendcal.height = 1;
|
||||||
|
s->sendcal.x_res = settings[i].x_res;
|
||||||
|
s->sendcal.y_res = settings[i].y_res;
|
||||||
s->sendcal.pages = img_pages;
|
s->sendcal.pages = img_pages;
|
||||||
s->sendcal.buffer = NULL;
|
s->sendcal.buffer = NULL;
|
||||||
|
|
||||||
/* set up the fullscan parameters */
|
/* set up the fullscan parameters */
|
||||||
s->fullscan.width_bytes = s->block_xfr.line_stride;
|
s->fullscan.width_bytes = s->block_xfr.line_stride;
|
||||||
|
s->fullscan.x_res = settings[i].x_res;
|
||||||
|
s->fullscan.y_res = settings[i].y_res;
|
||||||
if(s->source == SOURCE_FLATBED || !s->page_height)
|
if(s->source == SOURCE_FLATBED || !s->page_height)
|
||||||
{
|
{
|
||||||
/* flatbed and adf in autodetect always ask for all*/
|
/* flatbed and adf in autodetect always ask for all*/
|
||||||
s->fullscan.height = SCANNER_UNIT_TO_PIX(s->max_y, s->resolution_y);
|
s->fullscan.height = SCANNER_UNIT_TO_PIX(s->max_y, s->fullscan.y_res);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* adf with specified paper size requires padding on top (~1/2in) */
|
/* adf with specified paper size requires padding on top of page_height (~1/2in) */
|
||||||
s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + s->tl_y + ADF_HEIGHT_PADDING), s->resolution_y);
|
s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + s->tl_y + s->adf_height_padding), s->fullscan.y_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill in front settings */
|
/*=============================================================*/
|
||||||
s->front.width_pix = SCANNER_UNIT_TO_PIX(s->page_width, s->resolution_x * img_heads);
|
/* set up the output image structs */
|
||||||
|
/* output image might be different from scan due to interpolation */
|
||||||
|
s->front.x_res = s->resolution;
|
||||||
|
s->front.y_res = s->resolution;
|
||||||
|
if(s->source == SOURCE_FLATBED)
|
||||||
|
{
|
||||||
|
/* flatbed ignores the tly */
|
||||||
|
s->front.height = SCANNER_UNIT_TO_PIX(s->max_y - s->tl_y, s->front.y_res);
|
||||||
|
}
|
||||||
|
else if(!s->page_height)
|
||||||
|
{
|
||||||
|
/* adf in autodetect always asks for all */
|
||||||
|
s->front.height = SCANNER_UNIT_TO_PIX(s->max_y, s->front.y_res);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* adf with specified paper size */
|
||||||
|
s->front.height = SCANNER_UNIT_TO_PIX(s->page_height, s->front.y_res);
|
||||||
|
}
|
||||||
|
s->front.width_pix = s->block_img.width_pix;
|
||||||
s->front.x_start_offset = (s->block_xfr.image->width_pix - s->front.width_pix)/2;
|
s->front.x_start_offset = (s->block_xfr.image->width_pix - s->front.width_pix)/2;
|
||||||
switch (s->mode) {
|
switch (s->mode) {
|
||||||
case MODE_COLOR:
|
case MODE_COLOR:
|
||||||
|
@ -2138,22 +2148,19 @@ change_params(struct scanner *s)
|
||||||
default: /*binary*/
|
default: /*binary*/
|
||||||
s->front.width_bytes = s->front.width_pix/8;
|
s->front.width_bytes = s->front.width_pix/8;
|
||||||
s->front.width_pix = s->front.width_bytes * 8;
|
s->front.width_pix = s->front.width_bytes * 8;
|
||||||
s->page_width = PIX_TO_SCANNER_UNIT(s->front.width_pix, (img_heads * s->resolution_x));
|
/*s->page_width = PIX_TO_SCANNER_UNIT(s->front.width_pix, (img_heads * s->resolution_x));*/
|
||||||
s->front.x_offset_bytes = s->front.x_start_offset/8;
|
s->front.x_offset_bytes = s->front.x_start_offset/8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*output image might be taller than scan due to interpolation*/
|
|
||||||
s->front.height = SCANNER_UNIT_TO_PIX(s->page_height, s->resolution_x);
|
|
||||||
/* SCANNER_UNIT_TO_PIX(s->page_height, s->resolution_y) * (s->resolution_x / s->resolution_y) */
|
|
||||||
|
|
||||||
/* ADF front need to remove padding header */
|
/* ADF front need to remove padding header */
|
||||||
if (s->source != SOURCE_FLATBED)
|
if (s->source != SOURCE_FLATBED)
|
||||||
{
|
{
|
||||||
s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y+ADF_HEIGHT_PADDING, s->resolution_y);
|
s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y+s->adf_height_padding, s->fullscan.y_res);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->resolution_y);
|
s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->fullscan.y_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
s->front.pages = 1;
|
s->front.pages = 1;
|
||||||
|
@ -2162,16 +2169,20 @@ change_params(struct scanner *s)
|
||||||
/* back settings always same as front settings */
|
/* back settings always same as front settings */
|
||||||
s->back.width_pix = s->front.width_pix;
|
s->back.width_pix = s->front.width_pix;
|
||||||
s->back.width_bytes = s->front.width_bytes;
|
s->back.width_bytes = s->front.width_bytes;
|
||||||
|
s->back.x_res = s->front.x_res;
|
||||||
|
s->back.y_res = s->front.y_res;
|
||||||
s->back.height = s->front.height;
|
s->back.height = s->front.height;
|
||||||
s->back.x_start_offset = s->front.x_start_offset;
|
s->back.x_start_offset = s->front.x_start_offset;
|
||||||
s->back.x_offset_bytes = s->front.x_offset_bytes;
|
s->back.x_offset_bytes = s->front.x_offset_bytes;
|
||||||
s->back.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->resolution_y);
|
s->back.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->fullscan.y_res);
|
||||||
s->back.pages = 1;
|
s->back.pages = 1;
|
||||||
s->back.buffer = NULL;
|
s->back.buffer = NULL;
|
||||||
|
|
||||||
/* dynamic threshold temp buffer, in gray */
|
/* dynamic threshold temp buffer, in gray */
|
||||||
s->dt.width_pix = s->front.width_pix;
|
s->dt.width_pix = s->front.width_pix;
|
||||||
s->dt.width_bytes = s->front.width_pix;
|
s->dt.width_bytes = s->front.width_pix;
|
||||||
|
s->dt.x_res = s->front.x_res;
|
||||||
|
s->dt.y_res = s->front.y_res;
|
||||||
s->dt.height = 1;
|
s->dt.height = 1;
|
||||||
s->dt.pages = 1;
|
s->dt.pages = 1;
|
||||||
s->dt.buffer = NULL;
|
s->dt.buffer = NULL;
|
||||||
|
@ -2845,7 +2856,7 @@ coarsecal_light(struct scanner *s, unsigned char *pay)
|
||||||
/* apply the color correction factors to the averages */
|
/* apply the color correction factors to the averages */
|
||||||
for (i = 0; i < s->coarsecal.pages; i++)
|
for (i = 0; i < s->coarsecal.pages; i++)
|
||||||
for (j = 0; j < 3; j++)
|
for (j = 0; j < 3; j++)
|
||||||
rgb_avg[i][j] *= white_factor[j];
|
rgb_avg[i][j] *= s->white_factor[j];
|
||||||
/* set the gain so that none of the color channels are clipping, ie take the highest channel values */
|
/* set the gain so that none of the color channels are clipping, ie take the highest channel values */
|
||||||
for (i = 0; i < s->coarsecal.pages; i++)
|
for (i = 0; i < s->coarsecal.pages; i++)
|
||||||
{
|
{
|
||||||
|
@ -3304,7 +3315,7 @@ finecal(struct scanner *s)
|
||||||
for (k = 0; k < 3; k++)
|
for (k = 0; k < 3; k++)
|
||||||
{
|
{
|
||||||
int pixvalue = s->lightcal.buffer[idx];
|
int pixvalue = s->lightcal.buffer[idx];
|
||||||
float pixerror = (fine_gain_target[i] * white_factor[k] - pixvalue);
|
float pixerror = (fine_gain_target[i] * s->white_factor[k] - pixvalue);
|
||||||
int oldgain = s->sendcal.buffer[idx * 2 + 1];
|
int oldgain = s->sendcal.buffer[idx * 2 + 1];
|
||||||
int newgain;
|
int newgain;
|
||||||
/* if we overshot the last correction, reduce the gain_slope */
|
/* if we overshot the last correction, reduce the gain_slope */
|
||||||
|
@ -4079,49 +4090,142 @@ six5 (struct scanner *s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* de-scrambles the raw data from the scanner into the image buffer */
|
/* de-scrambles the raw data from the scanner into the image buffer */
|
||||||
|
/* the output image might be lower dpi than input image, so we scale horizontally */
|
||||||
static SANE_Status
|
static SANE_Status
|
||||||
descramble_raw(struct scanner *s, struct transfer * tp)
|
descramble_raw(struct scanner *s, struct transfer * tp)
|
||||||
{
|
{
|
||||||
SANE_Status ret = SANE_STATUS_GOOD;
|
SANE_Status ret = SANE_STATUS_GOOD;
|
||||||
unsigned char *p_in, *p_out = tp->image->buffer;
|
unsigned char *p_out = tp->image->buffer;
|
||||||
int height = tp->total_bytes / tp->line_stride;
|
int height = tp->total_bytes / tp->line_stride;
|
||||||
int i, j, k, l;
|
int i, j, k;
|
||||||
|
|
||||||
if (s->model == MODEL_S300 || s->model == MODEL_S1300i)
|
if (s->model == MODEL_S300 || s->model == MODEL_S1300i) {
|
||||||
{
|
for (i = 0; i < 2; i++){ /* page, front/back */
|
||||||
for (i = 0; i < 2; i++) /* page, front/back */
|
for (j = 0; j < height; j++){ /* row (y)*/
|
||||||
for (j = 0; j < height; j++) /* row (y)*/
|
int curr_col = 0;
|
||||||
for (k = 0; k < tp->plane_width; k++) /* column (x) */
|
int r=0, g=0, b=0, ppc=0;
|
||||||
for (l = 0; l < 3; l++) /* color component */
|
|
||||||
{
|
for (k = 0; k <= tp->plane_width; k++){ /* column (x) */
|
||||||
p_in = (unsigned char *) tp->raw_data + (j * tp->line_stride) + (l * tp->plane_stride) + k * 3 + i;
|
int this_col = k*tp->image->x_res/tp->x_res;
|
||||||
*p_out++ = *p_in;
|
|
||||||
|
/* going to change output pixel, dump rgb and reset */
|
||||||
|
if(ppc && curr_col != this_col){
|
||||||
|
*p_out = r/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
*p_out = g/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
*p_out = b/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
r = g = b = ppc = 0;
|
||||||
|
|
||||||
|
curr_col = this_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(k == tp->plane_width || this_col >= tp->image->width_pix){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*red is first*/
|
||||||
|
r += tp->raw_data[j*tp->line_stride + k*3 + i];
|
||||||
|
|
||||||
|
/*green is second*/
|
||||||
|
g += tp->raw_data[j*tp->line_stride + tp->plane_stride + k*3 + i];
|
||||||
|
|
||||||
|
/*blue is third*/
|
||||||
|
b += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k*3 + i];
|
||||||
|
|
||||||
|
ppc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (s->model == MODEL_S1100){
|
else if (s->model == MODEL_S1100){
|
||||||
for (j = 0; j < height; j++){ /* row (y)*/
|
for (j = 0; j < height; j++){ /* row (y)*/
|
||||||
for (k = 0; k < tp->plane_width; k++){ /* column (x) */
|
int curr_col = 0;
|
||||||
|
int r=0, g=0, b=0, ppc=0;
|
||||||
|
|
||||||
|
for (k = 0; k <= tp->plane_width; k++){ /* column (x) */
|
||||||
|
int this_col = k*tp->image->x_res/tp->x_res;
|
||||||
|
|
||||||
|
/* going to change output pixel, dump rgb and reset */
|
||||||
|
if(ppc && curr_col != this_col){
|
||||||
|
*p_out = r/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
*p_out = g/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
*p_out = b/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
r = g = b = ppc = 0;
|
||||||
|
|
||||||
|
curr_col = this_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(k == tp->plane_width || this_col >= tp->image->width_pix){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*red is second*/
|
/*red is second*/
|
||||||
p_in = (unsigned char *) tp->raw_data + (j*tp->line_stride) + (tp->plane_stride) + k;
|
r += tp->raw_data[j*tp->line_stride + tp->plane_stride + k];
|
||||||
*p_out++ = *p_in;
|
|
||||||
/*green is third*/
|
/*green is third*/
|
||||||
p_in = (unsigned char *) tp->raw_data + (j*tp->line_stride) + (2*tp->plane_stride) + k;
|
g += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k];
|
||||||
*p_out++ = *p_in;
|
|
||||||
/*blue is first*/
|
/*blue is first*/
|
||||||
p_in = (unsigned char *) tp->raw_data + (j*tp->line_stride) + k;
|
b += tp->raw_data[j*tp->line_stride + k];
|
||||||
*p_out++ = *p_in;
|
|
||||||
|
ppc++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else /* MODEL_FI60F or MODEL_FI65F */
|
else { /* MODEL_FI60F or MODEL_FI65F */
|
||||||
{
|
|
||||||
for (i = 0; i < height; i++) /* row (y)*/
|
for (j = 0; j < height; j++){ /* row (y)*/
|
||||||
for (j = 0; j < 3; j++) /* read head */
|
int curr_col = 0;
|
||||||
for (k = 0; k < tp->plane_width; k++) /* column within the read head */
|
|
||||||
for (l = 0; l < 3; l++) /* color component */
|
for (i = 0; i < 3; i++){ /* read head */
|
||||||
{
|
int r=0, g=0, b=0, ppc=0;
|
||||||
p_in = (unsigned char *) tp->raw_data + (i * tp->line_stride) + (l * tp->plane_stride) + k * 3 + j;
|
|
||||||
*p_out++ = *p_in;
|
for (k = 0; k <= tp->plane_width; k++){ /* column (x) within the read head */
|
||||||
|
int this_col = (k+i*tp->plane_width)*tp->image->x_res/tp->x_res;
|
||||||
|
|
||||||
|
/* going to change output pixel, dump rgb and reset */
|
||||||
|
if(ppc && curr_col != this_col){
|
||||||
|
*p_out = r/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
*p_out = g/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
*p_out = b/ppc;
|
||||||
|
p_out++;
|
||||||
|
|
||||||
|
r = g = b = ppc = 0;
|
||||||
|
|
||||||
|
curr_col = this_col;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(k == tp->plane_width || this_col >= tp->image->width_pix){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*red is first*/
|
||||||
|
r += tp->raw_data[j*tp->line_stride + k*3 + i];
|
||||||
|
|
||||||
|
/*green is second*/
|
||||||
|
g += tp->raw_data[j*tp->line_stride + tp->plane_stride + k*3 + i];
|
||||||
|
|
||||||
|
/*blue is third*/
|
||||||
|
b += tp->raw_data[j*tp->line_stride + 2*tp->plane_stride + k*3 + i];
|
||||||
|
|
||||||
|
ppc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4204,37 +4308,9 @@ read_from_scanner(struct scanner *s, struct transfer * tp)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_GCD(int x, int y)
|
|
||||||
{
|
|
||||||
int z;
|
|
||||||
|
|
||||||
while (y > 0) {
|
|
||||||
if (y > x) {
|
|
||||||
z = x;x = y;y = z;
|
|
||||||
}
|
|
||||||
z = y;
|
|
||||||
y = x % y;
|
|
||||||
x = z;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* test if we need to insert row because of non-square pixels */
|
|
||||||
/* generally for 225x200, where we copy 1 row after every 8 */
|
|
||||||
static inline int
|
|
||||||
need_insert_row(int res_x, int res_y, int offset_y)
|
|
||||||
{
|
|
||||||
if (res_x > res_y)
|
|
||||||
{
|
|
||||||
int gcd = get_GCD(res_x, res_y);
|
|
||||||
int y_r = res_y / gcd;
|
|
||||||
return ((offset_y % y_r) == (y_r-1));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* copies block buffer into front or back image buffer */
|
/* copies block buffer into front or back image buffer */
|
||||||
/* converts pixel data from RGB Color to the output format */
|
/* converts pixel data from RGB Color to the output format */
|
||||||
|
/* the output image might be lower dpi than input image, so we scale vertically */
|
||||||
static SANE_Status
|
static SANE_Status
|
||||||
copy_block_to_page(struct scanner *s,int side)
|
copy_block_to_page(struct scanner *s,int side)
|
||||||
{
|
{
|
||||||
|
@ -4242,12 +4318,15 @@ copy_block_to_page(struct scanner *s,int side)
|
||||||
struct transfer * block = &s->block_xfr;
|
struct transfer * block = &s->block_xfr;
|
||||||
struct page * page = &s->pages[side];
|
struct page * page = &s->pages[side];
|
||||||
int image_height = block->total_bytes / block->line_stride;
|
int image_height = block->total_bytes / block->line_stride;
|
||||||
int page_height = SCANNER_UNIT_TO_PIX(s->page_height, s->resolution_x);
|
int page_height = SCANNER_UNIT_TO_PIX(s->page_height, s->resolution);
|
||||||
int page_width = page->image->width_pix;
|
int page_width = page->image->width_pix;
|
||||||
int block_page_stride = block->image->width_bytes * block->image->height;
|
int block_page_stride = block->image->width_bytes * block->image->height;
|
||||||
int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F) || (s->model == MODEL_FI65F);
|
int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F) || (s->model == MODEL_FI65F);
|
||||||
int i,j,k=0,l=0;
|
int i,j,k=0,l=0;
|
||||||
|
|
||||||
|
int curr_in_row = s->fullscan.rx_bytes/s->fullscan.width_bytes;
|
||||||
|
int last_out_row = (page->bytes_scanned / page->image->width_bytes) - 1;
|
||||||
|
|
||||||
DBG (10, "copy_block_to_page: start\n");
|
DBG (10, "copy_block_to_page: start\n");
|
||||||
|
|
||||||
/* skip padding and tl_y */
|
/* skip padding and tl_y */
|
||||||
|
@ -4259,11 +4338,13 @@ copy_block_to_page(struct scanner *s,int side)
|
||||||
else if (s->fullscan.rx_bytes < block->line_stride * page->image->y_skip_offset)
|
else if (s->fullscan.rx_bytes < block->line_stride * page->image->y_skip_offset)
|
||||||
{
|
{
|
||||||
k = page->image->y_skip_offset - s->fullscan.rx_bytes / block->line_stride;
|
k = page->image->y_skip_offset - s->fullscan.rx_bytes / block->line_stride;
|
||||||
|
DBG (10, "copy_block_to_page: k start? %d\n", k);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* skip trailer */
|
/* skip trailer */
|
||||||
if (s->page_height)
|
if (s->page_height)
|
||||||
{
|
{
|
||||||
|
DBG (10, "copy_block_to_page: ph %d\n", s->page_height);
|
||||||
if (s->fullscan.rx_bytes > block->line_stride * page->image->y_skip_offset + page_height * block->line_stride)
|
if (s->fullscan.rx_bytes > block->line_stride * page->image->y_skip_offset + page_height * block->line_stride)
|
||||||
{
|
{
|
||||||
DBG (10, "copy_block_to_page: off the end? %d\n", side);
|
DBG (10, "copy_block_to_page: off the end? %d\n", side);
|
||||||
|
@ -4278,20 +4359,32 @@ copy_block_to_page(struct scanner *s,int side)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* loop over all the lines in the block */
|
/* loop over all the lines in the block */
|
||||||
for (i = 0; i < image_height-k-l; i++)
|
for (i = k; i < image_height-l; i++)
|
||||||
{
|
{
|
||||||
unsigned char * p_in = block->image->buffer + (side * block_page_stride)
|
/* determine source and dest rows (dpi scaling) */
|
||||||
+ ((i+k) * block->image->width_bytes) + page->image->x_start_offset * 3;
|
int this_in_row = curr_in_row + i;
|
||||||
unsigned char * p_out = page->image->buffer + page->lines_tx * page->image->width_bytes;
|
int this_out_row = (this_in_row - page->image->y_skip_offset) * page->image->y_res / s->fullscan.y_res;
|
||||||
unsigned char * lineStart = p_out;
|
DBG (15, "copy_block_to_page: in %d out %d lastout %d\n", this_in_row, this_out_row, last_out_row);
|
||||||
|
DBG (15, "copy_block_to_page: bs %d wb %d\n", page->bytes_scanned, page->image->width_bytes);
|
||||||
|
|
||||||
if(page->bytes_scanned + page->image->width_bytes > page->bytes_total){
|
/* don't walk off the end of the output buffer */
|
||||||
|
if(this_out_row >= page->image->height || this_out_row < 0){
|
||||||
DBG (10, "copy_block_to_page: out of space? %d\n", side);
|
DBG (10, "copy_block_to_page: out of space? %d\n", side);
|
||||||
DBG (10, "copy_block_to_page: rx:%d tx:%d tot:%d line:%d\n",
|
DBG (10, "copy_block_to_page: rx:%d tx:%d tot:%d line:%d\n",
|
||||||
page->bytes_scanned, page->bytes_read, page->bytes_total,page->image->width_bytes);
|
page->bytes_scanned, page->bytes_read, page->bytes_total,page->image->width_bytes);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ok, different output row, so we do the math */
|
||||||
|
if(this_out_row > last_out_row){
|
||||||
|
|
||||||
|
unsigned char * p_in = block->image->buffer + (side * block_page_stride)
|
||||||
|
+ (i * block->image->width_bytes) + page->image->x_start_offset * 3;
|
||||||
|
unsigned char * p_out = page->image->buffer + this_out_row * page->image->width_bytes;
|
||||||
|
unsigned char * lineStart = p_out;
|
||||||
|
|
||||||
|
last_out_row = this_out_row;
|
||||||
|
|
||||||
/* reverse order for back side or FI-60F scanner */
|
/* reverse order for back side or FI-60F scanner */
|
||||||
if (line_reverse)
|
if (line_reverse)
|
||||||
p_in += (page_width - 1) * 3;
|
p_in += (page_width - 1) * 3;
|
||||||
|
@ -4302,7 +4395,7 @@ copy_block_to_page(struct scanner *s,int side)
|
||||||
unsigned char r, g, b;
|
unsigned char r, g, b;
|
||||||
if (s->model == MODEL_S300 || s->model == MODEL_S1300i)
|
if (s->model == MODEL_S300 || s->model == MODEL_S1300i)
|
||||||
{ r = p_in[1]; g = p_in[2]; b = p_in[0]; }
|
{ r = p_in[1]; g = p_in[2]; b = p_in[0]; }
|
||||||
else /* MODEL_FI60F or MODEL_FI65F */
|
else /* MODEL_FI60F or MODEL_FI65F or MODEL_S1100 */
|
||||||
{ r = p_in[0]; g = p_in[1]; b = p_in[2]; }
|
{ r = p_in[0]; g = p_in[1]; b = p_in[2]; }
|
||||||
if (s->mode == MODE_COLOR)
|
if (s->mode == MODE_COLOR)
|
||||||
{
|
{
|
||||||
|
@ -4335,19 +4428,7 @@ copy_block_to_page(struct scanner *s,int side)
|
||||||
if (s->mode == MODE_LINEART)
|
if (s->mode == MODE_LINEART)
|
||||||
binarize_line(s, lineStart, page_width);
|
binarize_line(s, lineStart, page_width);
|
||||||
|
|
||||||
/* update the page counters with this row */
|
|
||||||
page->bytes_scanned += page->image->width_bytes;
|
page->bytes_scanned += page->image->width_bytes;
|
||||||
page->lines_rx++;
|
|
||||||
page->lines_pass++;
|
|
||||||
page->lines_tx++;
|
|
||||||
|
|
||||||
/* add a periodic row when scanning non-square pixels, unless you are at the end */
|
|
||||||
if ( page->bytes_scanned + page->image->width_bytes <= page->bytes_total
|
|
||||||
&& need_insert_row(s->resolution_x, s->resolution_y, page->lines_pass)
|
|
||||||
){
|
|
||||||
memcpy(lineStart + page->image->width_bytes, lineStart, page->image->width_bytes);
|
|
||||||
page->bytes_scanned += page->image->width_bytes;
|
|
||||||
page->lines_tx++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4364,7 +4445,7 @@ binarize_line(struct scanner *s, unsigned char *lineOut, int width)
|
||||||
int j, windowX, sum = 0;
|
int j, windowX, sum = 0;
|
||||||
|
|
||||||
/* ~1mm works best, but the window needs to have odd # of pixels */
|
/* ~1mm works best, but the window needs to have odd # of pixels */
|
||||||
windowX = 6 * s->resolution_x / 150;
|
windowX = 6 * s->resolution / 150;
|
||||||
if (!(windowX % 2)) windowX++;
|
if (!(windowX % 2)) windowX++;
|
||||||
|
|
||||||
/*second, prefill the sliding sum*/
|
/*second, prefill the sliding sum*/
|
||||||
|
|
|
@ -18,8 +18,7 @@ enum scanner_Option
|
||||||
OPT_MODE_GROUP,
|
OPT_MODE_GROUP,
|
||||||
OPT_SOURCE, /*adffront/adfback/adfduplex/fb*/
|
OPT_SOURCE, /*adffront/adfback/adfduplex/fb*/
|
||||||
OPT_MODE, /*mono/gray/color*/
|
OPT_MODE, /*mono/gray/color*/
|
||||||
OPT_X_RES,
|
OPT_RES,
|
||||||
OPT_Y_RES,
|
|
||||||
|
|
||||||
OPT_GEOMETRY_GROUP,
|
OPT_GEOMETRY_GROUP,
|
||||||
OPT_TL_X,
|
OPT_TL_X,
|
||||||
|
@ -56,6 +55,8 @@ struct image {
|
||||||
int width_bytes;
|
int width_bytes;
|
||||||
int height;
|
int height;
|
||||||
int pages;
|
int pages;
|
||||||
|
int x_res;
|
||||||
|
int y_res;
|
||||||
int x_start_offset;
|
int x_start_offset;
|
||||||
int x_offset_bytes;
|
int x_offset_bytes;
|
||||||
int y_skip_offset;
|
int y_skip_offset;
|
||||||
|
@ -70,6 +71,8 @@ struct transfer {
|
||||||
int total_bytes;
|
int total_bytes;
|
||||||
int rx_bytes;
|
int rx_bytes;
|
||||||
int done;
|
int done;
|
||||||
|
int x_res;
|
||||||
|
int y_res;
|
||||||
|
|
||||||
unsigned char * raw_data;
|
unsigned char * raw_data;
|
||||||
struct image * image;
|
struct image * image;
|
||||||
|
@ -100,15 +103,12 @@ struct scanner
|
||||||
int has_fb;
|
int has_fb;
|
||||||
int has_adf;
|
int has_adf;
|
||||||
int has_adf_duplex;
|
int has_adf_duplex;
|
||||||
int x_res_150;
|
|
||||||
int x_res_225;
|
|
||||||
int x_res_300;
|
|
||||||
int x_res_600;
|
|
||||||
|
|
||||||
int y_res_150;
|
int min_res;
|
||||||
int y_res_225;
|
int max_res;
|
||||||
int y_res_300;
|
|
||||||
int y_res_600;
|
float white_factor[3];
|
||||||
|
int adf_height_padding;
|
||||||
|
|
||||||
/* the scan size in 1/1200th inches, NOT basic_units or sane units */
|
/* the scan size in 1/1200th inches, NOT basic_units or sane units */
|
||||||
int max_x;
|
int max_x;
|
||||||
|
@ -133,8 +133,7 @@ struct scanner
|
||||||
/*mode group, room for lineart, gray, color, null */
|
/*mode group, room for lineart, gray, color, null */
|
||||||
SANE_String_Const source_list[5];
|
SANE_String_Const source_list[5];
|
||||||
SANE_String_Const mode_list[4];
|
SANE_String_Const mode_list[4];
|
||||||
SANE_Int x_res_list[4];
|
SANE_Range res_range;
|
||||||
SANE_Int y_res_list[4];
|
|
||||||
|
|
||||||
/*geometry group*/
|
/*geometry group*/
|
||||||
SANE_Range tl_x_range;
|
SANE_Range tl_x_range;
|
||||||
|
@ -157,9 +156,7 @@ struct scanner
|
||||||
/*mode group*/
|
/*mode group*/
|
||||||
int source; /* adf or fb */
|
int source; /* adf or fb */
|
||||||
int mode; /* color,lineart,etc */
|
int mode; /* color,lineart,etc */
|
||||||
int res; /* from a limited list, x and y same */
|
int resolution; /* dpi */
|
||||||
int resolution_x; /* unused dummy */
|
|
||||||
int resolution_y; /* unused dummy */
|
|
||||||
|
|
||||||
/*geometry group*/
|
/*geometry group*/
|
||||||
/* The desired size of the scan, all in 1/1200 inch */
|
/* The desired size of the scan, all in 1/1200 inch */
|
||||||
|
@ -219,6 +216,8 @@ struct scanner
|
||||||
/* the scan struct holds these larger numbers, but image buffer is unused */
|
/* the scan struct holds these larger numbers, but image buffer is unused */
|
||||||
struct {
|
struct {
|
||||||
int done;
|
int done;
|
||||||
|
int x_res;
|
||||||
|
int y_res;
|
||||||
int height;
|
int height;
|
||||||
int rx_bytes;
|
int rx_bytes;
|
||||||
int width_bytes;
|
int width_bytes;
|
||||||
|
|
Ładowanie…
Reference in New Issue