[sane-devel] [PATCH 00/10] epjitsu: imporove backend driver
Here is a series of patches to improve epjitsu backend driver. It is intended to; 1) fix a size treatment in driver. 1-1) TL_Y support, Width support 1-2) Cut unnecessary padding epjitsu: page width support epjitsu: skip top padding epjitsu: tl_y parameter support 2) merge S1100 driver proposal in http://ubuntuforums.org/showthread.php?t=1678335 epjitsu: introduce object_position() epjitsu: refactor coarsecal() epjitsu: ScanSnap S1100 support 3) General improvement Other patches. I tested on S1300. Hiroshi Miura (10): epjitsu: unit convert macro epjitsu: page width support epjitsu: optimize loop epjitsu: fix indent epjitsu: skip top padding epjitsu: tl_y parameter support epjitsu: x,y_resolution difference treatment epjitsu: introduce object_position() epjitsu: refactor coarsecal() epjitsu: ScanSnap S1100 support backend/epjitsu-cmd.h | 88 + backend/epjitsu.c | 816 +++-- backend/epjitsu.conf.in |4 + backend/epjitsu.h | 15 +- doc/descriptions/epjitsu.desc |4 +- 5 files changed, 652 insertions(+), 275 deletions(-) -- 1.7.9.5
[sane-devel] [PATCH 07/10] epjitsu: x, y_resolution difference treatment
ScanScanp has a resolution 225x200 in each model. The function which treat it should use a mathematic theory. Euclidean algorithm should be used to get GCD (Greatest Common Devisor) for this calculation. This patch make a separate function that should be get_GCD and simplified a logic in copy image function. TBD: this don't have Euclidean algorithm. Just prepare for it. Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 52 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index fd78e37..83d30d3 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -3832,6 +3832,36 @@ read_from_scanner(struct scanner *s, struct transfer * tp) return ret; } +static int get_GCD(int x, int y) +{ +/* Here should be implemented Euclidean algorithm */ +/* FIXME: only works with 225x200 */ +if (x == 225 && y == 200) +{ +return 25; +} +return 1; +} + +/* test it is nessesary to insert row because of non-square pixel */ +static inline int test_nessesary_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; +int x_r = res_x / gcd; +return ((offset_y % x_r) == y_r); +} +return 0; +} + +static inline int test_nessesary_skip_row(int res_x, int res_y, int offset_y) +{ +/* Reverse logic */ +return test_nessesary_insert_row(res_y, res_x, offset_y); +} + /* copies block buffer into front or back image buffer */ /* converts pixel data from RGB Color to the output format */ static SANE_Status @@ -3841,13 +3871,14 @@ copy_block_to_page(struct scanner *s,int side) struct transfer * block = &s->block_xfr; struct page * page = &s->pages[side]; int image_height = block->total_bytes / block->line_stride; -int image_width = block->image->width_pix; +/* int image_width = block->image->width_pix; */ int page_height = SCANNER_UNIT_TO_PIX(s->page_height, s->resolution_x); int page_width = page->image->width_pix; int block_page_stride = block->image->width_bytes * block->image->height; int page_y_offset = page->bytes_scanned / page->image->width_bytes; int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F); int i,j,k=0,l=0; +int page_y_skipped = 0; DBG (10, "copy_block_to_page: start\n"); @@ -3880,8 +3911,14 @@ copy_block_to_page(struct scanner *s,int side) for (i = 0; i < image_height-k-l; i++) { unsigned char * p_in = block->image->buffer + (side * block_page_stride) + ((i+k) * block->image->width_bytes) + page->image->x_start_offset * 3; -unsigned char * p_out = page->image->buffer + ((i + page_y_offset) * page->image->width_bytes); +unsigned char * p_out = page->image->buffer + ((i + page_y_offset - page_y_skipped) * page->image->width_bytes); unsigned char * lineStart = p_out; +/* skip a periodic row when non-square pixels */ +if (test_nessesary_skip_row(s->resolution_x, s->resolution_y, i + page_y_offset)) +{ +page_y_skipped++; +break; +} /* reverse order for back side or FI-60F scanner */ if (line_reverse) p_in += (page_width - 1) * 3; @@ -3924,18 +3961,17 @@ copy_block_to_page(struct scanner *s,int side) if (s->mode == MODE_LINEART) binarize_line(s, lineStart, page_width); -/*add a periodic row because of non-square pixels*/ -/*FIXME: only works with 225x200, but it need only when selecting 225x200 */ -if (s->resolution_x > s->resolution_y && (i + page_y_offset) % 9 == 8) +if (test_nessesary_insert_row(s->resolution_x, s->resolution_y, i + page_y_offset)) { +/* add a periodic row when non-square pixels */ memcpy(lineStart + page->image->width_bytes, lineStart, page->image->width_bytes); page_y_offset += 1; page->bytes_scanned += page->image->width_bytes; } -} -/* update the page counter of bytes scanned */ -page->bytes_scanned += page->image->width_bytes * (image_height - k - l); +/* update the page counter of bytes scanned */ +page->bytes_scanned += page->image->width_bytes; +} DBG (10, "copy_block_to_page: finish\n"); -- 1.7.9.5
[sane-devel] [PATCH 04/10] epjitsu: fix indent
Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 40 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 1be6447..a0ca532 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -1798,33 +1798,33 @@ change_params(struct scanner *s) i++; } while (settings[i].model); - /*pull in closest y resolution*/ - s->resolution_y = settings[i].y_res; +/*pull in closest y resolution*/ +s->resolution_y = settings[i].y_res; - /*1200 dpi*/ - s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, s->resolution_x ); - s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, s->resolution_x ); - s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, s->resolution_y ); - s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, s->resolution_y ); +/*1200 dpi*/ +s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, s->resolution_x ); +s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, s->resolution_x ); +s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, s->resolution_y ); +s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, s->resolution_y ); - /*current dpi*/ - s->setWindowCoarseCal = settings[i].sw_coarsecal; - s->setWindowCoarseCalLen = SET_WINDOW_LEN; +/*current dpi*/ +s->setWindowCoarseCal = settings[i].sw_coarsecal; +s->setWindowCoarseCalLen = SET_WINDOW_LEN; - s->setWindowFineCal = settings[i].sw_finecal; - s->setWindowFineCalLen = SET_WINDOW_LEN; +s->setWindowFineCal = settings[i].sw_finecal; +s->setWindowFineCalLen = SET_WINDOW_LEN; - s->setWindowSendCal = settings[i].sw_sendcal; - s->setWindowSendCalLen = SET_WINDOW_LEN; +s->setWindowSendCal = settings[i].sw_sendcal; +s->setWindowSendCalLen = SET_WINDOW_LEN; - s->sendCal1Header = settings[i].head_cal1; - s->sendCal1HeaderLen = 14; +s->sendCal1Header = settings[i].head_cal1; +s->sendCal1HeaderLen = 14; - s->sendCal2Header = settings[i].head_cal2; - s->sendCal2HeaderLen = 7; +s->sendCal2Header = settings[i].head_cal2; +s->sendCal2HeaderLen = 7; - s->setWindowScan = settings[i].sw_scan; - s->setWindowScanLen = SET_WINDOW_LEN; +s->setWindowScan = settings[i].sw_scan; +s->setWindowScanLen = SET_WINDOW_LEN; if (!settings[i].model) { -- 1.7.9.5
[sane-devel] [PATCH 09/10] epjitsu: refactor coarsecal()
Now refactoring coarsecal() for S1100 support. it is carefully changed not to break S300/1300/1500. the chunk come from http://ubuntuforums.org/showthread.php?t=1678335 Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 333 + 1 file changed, 160 insertions(+), 173 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 9bcd1eb..91b0d59 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -2399,43 +2399,123 @@ setup_buffers(struct scanner *s) */ static SANE_Status -coarsecal(struct scanner *s) +coarsecal_send_cal(struct scanner *s, unsigned char *pay) { SANE_Status ret = SANE_STATUS_GOOD; - -size_t cmdLen = 2; unsigned char cmd[2]; - -size_t statLen = 1; unsigned char stat[1]; +size_t cmdLen,statLen,payLen; + +DBG (5, "coarsecal_send_cal: start\n"); +/* send coarse cal (c6) */ +cmd[0] = 0x1b; +cmd[1] = 0xc6; +cmdLen = 2; +stat[0] = 0; +statLen = 1; + +ret = do_cmd( + s, 0, + cmd, cmdLen, + NULL, 0, + stat, &statLen +); +if(ret){ + DBG (5, "coarsecal_send_cal: error sending c6 cmd\n"); + return ret; +} +if(stat[0] != 6){ +DBG (5, "coarsecal_send_cal: cmd bad c6 status?\n"); +return SANE_STATUS_IO_ERROR; + } + +/*send coarse cal payload*/ +stat[0] = 0; +statLen = 1; +payLen = 28; -size_t payLen = 28; -unsigned char pay[28]; +ret = do_cmd( + s, 0, + pay, payLen, + NULL, 0, + stat, &statLen +); +if(ret){ +DBG (5, "coarsecal_send_cal: error sending c6 payload\n"); +return ret; +} +if(stat[0] != 6){ +DBG (5, "coarsecal_send_cal: c6 payload bad status?\n"); +return SANE_STATUS_IO_ERROR; +} -int try_count, cal_good[2], x, i, j; -int param[2], zcount[2], high_param[2], low_param[2], avg[2], maxval[2]; -int rgb_avg[2][3], rgb_hicount[2][3]; +DBG (5, "coarsecal_send_cal: finish\n"); +return ret; +} -DBG (10, "coarsecal: start\n"); +static SANE_Status +coarsecal_get_line(struct scanner *s, struct image *img) +{ +SANE_Status ret = SANE_STATUS_GOOD; +unsigned char cmd[2]; +unsigned char stat[1]; +size_t cmdLen,statLen; -if(s->model == MODEL_S300){ -memcpy(pay,coarseCalData_S300,payLen); -} -else{ -memcpy(pay,coarseCalData_FI60F,payLen); -} +DBG (5, "coarsecal_get_line: start\n"); -/* ask for 1 line */ -ret = set_window(s, WINDOW_COARSECAL); +/* send scan d2 command */ +cmd[0] = 0x1b; +cmd[1] = 0xd2; +cmdLen = 2; +stat[0] = 0; +statLen = 1; + +ret = do_cmd( + s, 0, + cmd, cmdLen, + NULL, 0, + stat, &statLen +); if(ret){ -DBG (5, "coarsecal: error sending setwindow\n"); +DBG (5, "coarsecal_get_line: error sending d2 cmd\n"); return ret; } +if(stat[0] != 6){ +DBG (5, "coarsecal_get_line: cmd bad d2 status?\n"); +return SANE_STATUS_IO_ERROR; +} + +s->cal_image.image = img; +update_transfer_totals(&s->cal_image); + +while(!s->cal_image.done){ +ret = read_from_scanner(s,&s->cal_image); +if(ret){ +DBG (5, "coarsecal_get_line: cant read from scanner\n"); +return ret; +} +} +/* convert the raw data into normal packed pixel data */ +descramble_raw(s, &s->cal_image); + +DBG (5, "coarsecal_get_line: finish\n"); +return ret; +} + +static SANE_Status +coarsecal_dark(struct scanner *s, unsigned char *pay) +{ +SANE_Status ret = SANE_STATUS_GOOD; + +int try_count, cal_good[2], x, j; +int param[2], zcount[2], high_param[2], low_param[2], avg[2], maxval[2]; + +DBG (5, "coarsecal_dark: start\n"); /* dark cal, lamp off */ ret = lamp(s,0); if(ret){ -DBG (5, "coarsecal: error lamp off\n"); +DBG (5, "coarsecal_dark: error lamp off\n"); return ret; } @@ -2462,81 +2542,11 @@ coarsecal(struct scanner *s) pay[9] = param[0]; } -/* send coarse cal (c6) */ -cmd[0] = 0x1b; -cmd[1] = 0xc6; -stat[0] = 0; -statLen = 1; - -ret = do_cmd( - s, 0, - cmd, cmdLen, - NULL, 0, - stat, &statLen -); -if(ret){ -DBG (5, "coarsecal: error sending c6 cmd\n"); -return ret; -} -if(stat[0] != 6){ -DBG (5, "coarsecal: cmd bad c6 status?\n"); -return SANE_STATUS_IO_ERROR; -} - -/*send coarse cal payload*/ -stat[0] = 0; -statLen = 1; - -ret = do_cmd( - s, 0, - pay, payLen, - NULL, 0, - stat, &statLen -); -if(ret){ -DBG (5, "coarsecal: error sending c6 payload\n"); -return ret; -} -
[sane-devel] [PATCH 08/10] epjitsu: introduce object_position()
Rename ingest() to object_position() now it can do both ingest and eject. This is required by S1100 support. chunk come from http://ubuntuforums.org/showthread.php?t=1678335 Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 28 ++-- backend/epjitsu.h |5 - 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 83d30d3..9bcd1eb 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -2176,7 +2176,7 @@ sane_start (SANE_Handle handle) /* ingest paper with adf */ if( s->source == SOURCE_ADF_BACK || s->source == SOURCE_ADF_FRONT || (s->source == SOURCE_ADF_DUPLEX && s->side == SIDE_FRONT) ){ -ret = ingest(s); +ret = object_position(s,EPJITSU_PAPER_INGEST); if (ret != SANE_STATUS_GOOD) { DBG (5, "sane_start: ERROR: failed to ingest\n"); sane_cancel((SANE_Handle)s); @@ -3442,11 +3442,10 @@ get_hardware_status (struct scanner *s) } static SANE_Status -ingest(struct scanner *s) +object_position(struct scanner *s, int ingest) { SANE_Status ret = SANE_STATUS_GOOD; int i; - unsigned char cmd[2]; size_t cmdLen = sizeof(cmd); unsigned char stat[1]; @@ -3454,10 +3453,11 @@ ingest(struct scanner *s) unsigned char pay[2]; size_t payLen = sizeof(pay); -DBG (10, "ingest: start\n"); +DBG (10, "object_position: start\n"); -for(i=0;i<5;i++){ - +i = (ingest)?5:1; + +while(i--){ /*send paper load cmd*/ cmd[0] = 0x1b; cmd[1] = 0xd4; @@ -3470,18 +3470,18 @@ ingest(struct scanner *s) stat, &statLen ); if(ret){ -DBG (5, "ingest: error sending cmd\n"); +DBG (5, "object_position: error sending cmd\n"); return ret; } if(stat[0] != 6){ -DBG (5, "ingest: cmd bad status? %d\n",stat[0]); +DBG (5, "object_position: cmd bad status? %d\n",stat[0]); continue; } /*send payload*/ statLen = 1; payLen = 1; -pay[0] = 1; +pay[0] = ingest; ret = do_cmd( s, 0, @@ -3490,25 +3490,25 @@ ingest(struct scanner *s) stat, &statLen ); if(ret){ -DBG (5, "ingest: error sending payload\n"); +DBG (5, "object_position: error sending payload\n"); return ret; } if(stat[0] == 6){ -DBG (5, "ingest: found paper?\n"); +DBG (5, "object_position: found paper?\n"); break; } else if(stat[0] == 0x15 || stat[0] == 0){ -DBG (5, "ingest: no paper?\n"); +DBG (5, "object_position: no paper?\n"); ret=SANE_STATUS_NO_DOCS; continue; } else{ -DBG (5, "ingest: payload bad status?\n"); +DBG (5, "object_position: payload bad status?\n"); return SANE_STATUS_IO_ERROR; } } -DBG (10, "ingest: finish\n"); +DBG (10, "object_position: finish\n"); return ret; } diff --git a/backend/epjitsu.h b/backend/epjitsu.h index 68a997b..3d70e73 100644 --- a/backend/epjitsu.h +++ b/backend/epjitsu.h @@ -280,6 +280,9 @@ struct scanner #define WINDOW_SENDCAL 2 #define WINDOW_SCAN 3 +#define EPJITSU_PAPER_INGEST 1 +#define EPJITSU_PAPER_EJECT 0 + /* - */ #define MM_PER_UNIT_UNFIX SANE_UNFIX(SANE_FIX(MM_PER_INCH / 1200.0)) @@ -359,7 +362,7 @@ static SANE_Status destroy(struct scanner *s); static SANE_Status teardown_buffers(struct scanner *s); static SANE_Status setup_buffers(struct scanner *s); -static SANE_Status ingest(struct scanner *s); +static SANE_Status object_position(struct scanner *s, int ingest); static SANE_Status coarsecal(struct scanner *s); static SANE_Status finecal(struct scanner *s); static SANE_Status send_lut(struct scanner *s); -- 1.7.9.5
[sane-devel] [PATCH 10/10] epjitsu: ScanSnap S1100 support
Add S1100 support The ideas and cmd data are comes from: http://ubuntuforums.org/showthread.php?t=1678335 TBD: test on S1100, I don't have a machine. Signed-off-by: Hiroshi Miura --- backend/epjitsu-cmd.h | 88 + backend/epjitsu.c | 217 +++-- backend/epjitsu.conf.in |4 + backend/epjitsu.h |3 + doc/descriptions/epjitsu.desc |4 +- 5 files changed, 285 insertions(+), 31 deletions(-) diff --git a/backend/epjitsu-cmd.h b/backend/epjitsu-cmd.h index 2e914d9..4bc8052 100644 --- a/backend/epjitsu-cmd.h +++ b/backend/epjitsu-cmd.h @@ -38,6 +38,10 @@ static unsigned char coarseCalData_S300[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x24, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static unsigned char coarseCalData_S1100[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x00, 0x25, 0x00, 0x00, 0x00, 0x26, 0x00, 0x26, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; /*** fi-60F 150dpi */ /* 1b d1 (set window) before coarse cal (read 1 line of 0x bytes) */ @@ -457,3 +461,87 @@ static unsigned char setWindowScan_S300_300_U[] = { }; /*** S300 600dpi USB is same as AC power */ + +/*** S1100 300dpi USB */ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x45a0 bytes) */ +static unsigned char setWindowCoarseCal_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 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, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x45a0 bytes) */ +static unsigned char setWindowFineCal_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 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, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before gain/offset tables (write 1 line of 0x45a0 bytes) */ +static unsigned char setWindowSendCal_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xd0, 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, 0x2c, 0x01, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b c3 (gain?) command header */ +static unsigned char sendCal1Header_S1100_300_U[] = { /* plus 0x45a0 data bytes */ +0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x1e, 0x10, 0x00, 0x03 +}; +/* 1b c4 (offset?) command header */ +static unsigned char sendCal2Header_S1100_300_U[] = { /* plus 0x45a0 data bytes */ +0x63, 0x86, 0x63, 0x86, 0x63, 0x86, 0x07 +}; +/* 1b d1 (set window) before scan */ +static unsigned char setWindowScan_S1100_300_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x01, 0x2c, 0x01, 0x2c, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x58, 0x00, 0x00, 0x1b, 0xe1, 0x00, 0x00, +0x00, 0x05, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x80, 0x80, 0x01, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/*** S1100 600dpi USB */ +/* 1b d1 (set window) before coarse cal (read 1 line of 0x3e20 bytes) */ +static unsigned char setWindowCoarseCal_S1100_600_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x02, 0x58, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 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, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +/* 1b d1 (set window) before fine cal (read 16 lines of 0x3e20 bytes) */ +static unsigned char setWindowFineCal_S1100_600_U[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x02, 0x58, 0x03, 0x20, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0xf0, 0
[sane-devel] [PATCH 06/10] epjitsu: tl_y parameter support
The driver can cut top of image for padding. We can also cut an ordered size at a top of image. It make tl_y parameter works. Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 45 + 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 624f532..fd78e37 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -1058,7 +1058,6 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) opt->constraint_type = SANE_CONSTRAINT_RANGE; opt->constraint.range = &(s->tl_y_range); opt->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT; -opt->cap = SANE_CAP_INACTIVE; } /* bottom-right x */ @@ -1599,7 +1598,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option, s->tl_y = FIXED_MM_TO_SCANNER_UNIT(val_c); *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; - return SANE_STATUS_GOOD; + return change_params(s); case OPT_BR_X: if (s->br_x == FIXED_MM_TO_SCANNER_UNIT(val_c)) @@ -1842,6 +1841,37 @@ change_params(struct scanner *s) img_pages = 1; } +/* height */ +if (s->model == MODEL_S300) +{ +if (s->tl_y > s->max_y - s->min_y) + s->tl_y = s->max_y - s->min_y - ADF_HEIGHT_PADDING; +if (s->tl_y + s->page_height > s->max_y - ADF_HEIGHT_PADDING) + s->page_height = s->max_y - ADF_HEIGHT_PADDING - 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 - ADF_HEIGHT_PADDING - s->page_height ; +} +else /* (s->model == MODEL_FI60F) */ +{ +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) { +s->br_y = s->tl_y + s->page_height; +} +else +{ +s->br_y = s->max_y; +} + /*width*/ if (s->page_width > s->max_x) s->page_width = s->max_x; @@ -1849,7 +1879,6 @@ change_params(struct scanner *s) s->page_width = s->min_x; s->tl_x = (s->max_x - s->page_width)/2; s->br_x = (s->max_x + s->page_width)/2; -s->br_y = s->max_y; /* set up the transfer structs */ s->cal_image.plane_width = settings[i].cal_headwidth; @@ -1905,7 +1934,7 @@ change_params(struct scanner *s) else { /* adf with specified paper size requires padding on top (~1/2in) */ - s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + ADF_HEIGHT_PADDING), s->resolution_y); + s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + s->tl_y + ADF_HEIGHT_PADDING), s->resolution_y); } /* fill in front settings */ @@ -1934,11 +1963,11 @@ change_params(struct scanner *s) /* ADF front need to remove padding header */ if (s->source != SOURCE_FLATBED) { -s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(ADF_HEIGHT_PADDING, s->resolution_y); +s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y+ADF_HEIGHT_PADDING, s->resolution_y); } else { -s->front.y_skip_offset = 0; +s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->resolution_y); } s->front.pages = 1; @@ -1950,7 +1979,7 @@ change_params(struct scanner *s) s->back.height = s->front.height; s->back.x_start_offset = s->front.x_start_offset; s->back.x_offset_bytes = s->front.x_offset_bytes; -s->back.y_skip_offset = 0; +s->back.y_skip_offset = SCANNER_UNIT_TO_PIX(s->tl_y, s->resolution_y); s->back.pages = 1; s->back.buffer = NULL; @@ -3822,7 +3851,7 @@ copy_block_to_page(struct scanner *s,int side) DBG (10, "copy_block_to_page: start\n"); -/* skip padding */ +/* skip padding and tl_y */ if (s->fullscan.rx_bytes + s->block_xfr.rx_bytes < block->line_stride * page->image->y_skip_offset) { return ret; -- 1.7.9.5
[sane-devel] [PATCH 05/10] epjitsu: skip top padding
The driver need a padding at top of page. Because scansnap don't treat empty image at the top of image that is generated when loading paper, the driver cut top of page in 1/2 inch. Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 52 +--- backend/epjitsu.h |1 + 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index a0ca532..624f532 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -1930,6 +1930,17 @@ change_params(struct scanner *s) /*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 */ +if (s->source != SOURCE_FLATBED) +{ +s->front.y_skip_offset = SCANNER_UNIT_TO_PIX(ADF_HEIGHT_PADDING, s->resolution_y); +} +else +{ +s->front.y_skip_offset = 0; +} + s->front.pages = 1; s->front.buffer = NULL; @@ -1939,6 +1950,7 @@ change_params(struct scanner *s) s->back.height = s->front.height; s->back.x_start_offset = s->front.x_start_offset; s->back.x_offset_bytes = s->front.x_offset_bytes; +s->back.y_skip_offset = 0; s->back.pages = 1; s->back.buffer = NULL; @@ -3540,7 +3552,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len page = &s->pages[s->side]; /* have sent all of current buffer */ -if(page->done){ +if(s->fullscan.done && page->done){ DBG (10, "sane_read: returning eof\n"); return SANE_STATUS_EOF; } @@ -3687,7 +3699,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len, SANE_Int * len page->bytes_read += *len; /* sent it all, return eof on next read */ -if(s->fullscan.done && page->bytes_read == page->bytes_scanned){ +if(page->bytes_read == page->bytes_scanned){ DBG (10, "sane_read: side done\n"); page->done = 1; } @@ -3799,20 +3811,46 @@ copy_block_to_page(struct scanner *s,int side) SANE_Status ret = SANE_STATUS_GOOD; struct transfer * block = &s->block_xfr; struct page * page = &s->pages[side]; -int height = block->total_bytes / block->line_stride; +int image_height = block->total_bytes / block->line_stride; int image_width = block->image->width_pix; +int page_height = SCANNER_UNIT_TO_PIX(s->page_height, s->resolution_x); int page_width = page->image->width_pix; int block_page_stride = block->image->width_bytes * block->image->height; int page_y_offset = page->bytes_scanned / page->image->width_bytes; int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F); -int i,j; +int i,j,k=0,l=0; DBG (10, "copy_block_to_page: start\n"); +/* skip padding */ +if (s->fullscan.rx_bytes + s->block_xfr.rx_bytes < block->line_stride * page->image->y_skip_offset) +{ +return ret; +} +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; +} + +/* skip trailer */ +if (s->page_height) +{ +if (s->fullscan.rx_bytes > block->line_stride * page->image->y_skip_offset + page_height * block->line_stride) +{ +return ret; +} +else if (s->fullscan.rx_bytes + s->block_xfr.rx_bytes + > block->line_stride * page->image->y_skip_offset + page_height * block->line_stride) +{ + l = (s->fullscan.rx_bytes + s->block_xfr.rx_bytes) / block->line_stride + - page_height - page->image->y_skip_offset; +} +} + /* loop over all the lines in the block */ -for (i = 0; i < height; i++) +for (i = 0; i < image_height-k-l; i++) { -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_in = block->image->buffer + (side * block_page_stride) + ((i+k) * block->image->width_bytes) + page->image->x_start_offset * 3; unsigned char * p_out = page->image->buffer + ((i + page_y_offset) * page->image->width_bytes); unsigned char * lineStart = p_out; /* reverse order for back side or FI-60F scanner */ @@ -3868,7 +3906,7 @@ copy_block_to_page(struct scanner *s,int side) } /* update the page counter of bytes scanned */ -page->bytes_scanned += page->image->width_bytes * height; +page->bytes_scanned += page->image->width_bytes * (image_height - k - l); DBG (10, "copy_block_to_page: finish\n"); diff --git a/backend/epjitsu.h b/backend/epjitsu.h index f6b7750..68a997b 100644 --- a/backend/epjitsu.h +++ b/backend/epjit
[sane-devel] [PATCH 02/10] epjitsu: page width support
ScanSnap itself don't have a feature to detect and scan area in demanded width. Otherwise driver need to cut into proper width. this introduce page_width parameter and facility to cut image into page width. Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 48 +++- backend/epjitsu.h |3 ++- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 0c129fc..3c791b7 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -1124,7 +1124,6 @@ sane_get_option_descriptor (SANE_Handle handle, SANE_Int option) else{ opt->cap = SANE_CAP_INACTIVE; } -opt->cap = SANE_CAP_INACTIVE; } /* page height */ @@ -1803,10 +1802,6 @@ change_params(struct scanner *s) s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, s->resolution_y ); s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, s->resolution_y ); - s->page_width = s->max_x; - s->br_x = s->max_x; - s->br_y = s->max_y; - /*current dpi*/ s->setWindowCoarseCal = settings[i].sw_coarsecal; s->setWindowCoarseCalLen = SET_WINDOW_LEN; @@ -1846,6 +1841,15 @@ change_params(struct scanner *s) img_heads = 3; /* image width is 3* the plane width on the FI-60F */ img_pages = 1; } + +/*width*/ +if (s->page_width > s->max_x) + s->page_width = s->max_x; +else if (s->page_width < s->min_x) + s->page_width = s->min_x; +s->tl_x = (s->max_x - s->page_width)/2; +s->br_x = (s->max_x + s->page_width)/2; +s->br_y = s->max_y; /* set up the transfer structs */ s->cal_image.plane_width = settings[i].cal_headwidth; @@ -1906,15 +1910,21 @@ change_params(struct scanner *s) /* fill in front settings */ s->front.width_pix = SCANNER_UNIT_TO_PIX(s->page_width, s->resolution_x * img_heads); +s->front.x_start_offset = (s->block_xfr.image->width_pix - s->front.width_pix)/2; switch (s->mode) { case MODE_COLOR: s->front.width_bytes = s->front.width_pix*3; +s->front.x_offset_bytes = s->front.x_start_offset *3; break; case MODE_GRAYSCALE: s->front.width_bytes = s->front.width_pix; +s->front.x_offset_bytes = s->front.x_start_offset; break; default: /*binary*/ s->front.width_bytes = s->front.width_pix/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->front.x_offset_bytes = s->front.x_start_offset/8; break; } /*output image might be taller than scan due to interpolation*/ @@ -1927,6 +1937,8 @@ change_params(struct scanner *s) s->back.width_pix = s->front.width_pix; s->back.width_bytes = s->front.width_bytes; s->back.height = s->front.height; +s->back.x_start_offset = s->front.x_start_offset; +s->back.x_offset_bytes = s->front.x_offset_bytes; s->back.pages = 1; s->back.buffer = NULL; @@ -3788,7 +3800,8 @@ copy_block_to_page(struct scanner *s,int side) struct transfer * block = &s->block_xfr; struct page * page = &s->pages[side]; int height = block->total_bytes / block->line_stride; -int width = block->image->width_pix; +int image_width = block->image->width_pix; +int page_width = page->image->width_pix; int block_page_stride = block->image->width_bytes * block->image->height; int page_y_offset = page->bytes_scanned / page->image->width_bytes; int line_reverse = (side == SIDE_BACK) || (s->model == MODEL_FI60F); @@ -3799,14 +3812,15 @@ copy_block_to_page(struct scanner *s,int side) /* loop over all the lines in the block */ for (i = 0; i < height; i++) { -unsigned char * p_in = block->image->buffer + (side * block_page_stride) + (i * block->image->width_bytes); +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 + ((i + page_y_offset) * page->image->width_bytes); unsigned char * lineStart = p_out; /* reverse order for back side or FI-60F scanner */ if (line_reverse) -p_in += (width - 1) * 3; +p_in += (page_width - 1) * 3; + /* convert all of the pixels in this row */ -for (j = 0; j < width; j++) +for (j = 0; j < page_width; j++) { unsigned char r, g, b; if (s->model == MODEL_S300) @@ -3825,18 +3839,26 @@ copy_block_to_page(struct scanner *s,int side) } else if (s->mode == MODE_LINEART) { -s->dt.buffer[j] = (r + g + b) / 3; +s->dt.buffer[j] = (r + g + b) / 3; /* stores dt temp image buffer and binalize afterword */ } if (line_revers
[sane-devel] [PATCH 03/10] epjitsu: optimize loop
Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 3c791b7..1be6447 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -1791,7 +1791,12 @@ change_params(struct scanner *s) do { if(settings[i].model == s->model && settings[i].x_res == s->resolution_x -&& settings[i].usb_power == s->usb_power){ +&& settings[i].usb_power == s->usb_power) + { + break; + } + i++; +} while (settings[i].model); /*pull in closest y resolution*/ s->resolution_y = settings[i].y_res; @@ -1821,11 +1826,6 @@ change_params(struct scanner *s) s->setWindowScan = settings[i].sw_scan; s->setWindowScanLen = SET_WINDOW_LEN; - break; - } - i++; -} while (settings[i].model); - if (!settings[i].model) { return SANE_STATUS_INVAL; -- 1.7.9.5
[sane-devel] [PATCH 01/10] epjitsu: unit convert macros
introducing macros converting between scanner unit and inches each other. Signed-off-by: Hiroshi Miura --- backend/epjitsu.c | 21 - backend/epjitsu.h |3 +++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/backend/epjitsu.c b/backend/epjitsu.c index 3e102da..0c129fc 100644 --- a/backend/epjitsu.c +++ b/backend/epjitsu.c @@ -209,6 +209,8 @@ static float white_factor[3] = {1.0, 0.93, 0.98}; /* Blue, Red, Green */ #define STRING_GRAYSCALE SANE_VALUE_SCAN_MODE_GRAY #define STRING_COLOR SANE_VALUE_SCAN_MODE_COLOR +#define ADF_HEIGHT_PADDING 600 + /* * used by attach* and sane_get_devices * a ptr to a null term array of ptrs to SANE_Device structs @@ -1796,10 +1798,10 @@ change_params(struct scanner *s) s->resolution_y = settings[i].y_res; /*1200 dpi*/ - s->max_x = settings[i].max_x * 1200/s->resolution_x; - s->min_x = settings[i].min_x * 1200/s->resolution_x; - s->max_y = settings[i].max_y * 1200/s->resolution_y; - s->min_y = settings[i].min_y * 1200/s->resolution_y; + s->max_x = PIX_TO_SCANNER_UNIT( settings[i].max_x, s->resolution_x ); + s->min_x = PIX_TO_SCANNER_UNIT( settings[i].min_x, s->resolution_x ); + s->max_y = PIX_TO_SCANNER_UNIT( settings[i].max_y, s->resolution_y ); + s->min_y = PIX_TO_SCANNER_UNIT( settings[i].min_y, s->resolution_y ); s->page_width = s->max_x; s->br_x = s->max_x; @@ -1894,16 +1896,16 @@ change_params(struct scanner *s) if(s->source == SOURCE_FLATBED || !s->page_height) { /* flatbed and adf in autodetect always ask for all*/ - s->fullscan.height = s->max_y * s->resolution_y / 1200; + s->fullscan.height = SCANNER_UNIT_TO_PIX(s->max_y, s->resolution_y); } else { - /* adf with specified paper size requires padding (~1/2in) */ - s->fullscan.height = (s->page_height+600) * s->resolution_y / 1200; + /* adf with specified paper size requires padding on top (~1/2in) */ + s->fullscan.height = SCANNER_UNIT_TO_PIX((s->page_height + ADF_HEIGHT_PADDING), s->resolution_y); } /* fill in front settings */ -s->front.width_pix = s->block_img.width_pix; +s->front.width_pix = SCANNER_UNIT_TO_PIX(s->page_width, s->resolution_x * img_heads); switch (s->mode) { case MODE_COLOR: s->front.width_bytes = s->front.width_pix*3; @@ -1916,7 +1918,8 @@ change_params(struct scanner *s) break; } /*output image might be taller than scan due to interpolation*/ -s->front.height = s->fullscan.height * s->resolution_x / s->resolution_y; +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) */ s->front.pages = 1; s->front.buffer = NULL; diff --git a/backend/epjitsu.h b/backend/epjitsu.h index ed63504..19b6c21 100644 --- a/backend/epjitsu.h +++ b/backend/epjitsu.h @@ -286,6 +286,9 @@ struct scanner #define SCANNER_UNIT_TO_FIXED_MM(number) SANE_FIX((number) * MM_PER_UNIT_UNFIX) #define FIXED_MM_TO_SCANNER_UNIT(number) SANE_UNFIX(number) / MM_PER_UNIT_UNFIX +#define PIX_TO_SCANNER_UNIT(number, dpi) SANE_UNFIX(SANE_FIX((number) * 1200 / dpi )) +#define SCANNER_UNIT_TO_PIX(number, dpi) SANE_UNFIX(SANE_FIX((number) * dpi / 1200 )) + #define CONFIG_FILE "epjitsu.conf" #ifndef PATH_MAX -- 1.7.9.5
[sane-devel] Problem with Epson Stylus SX525WD
On Fri, Nov 2, 2012 at 8:47 PM, Robin Krahl wrote: > Hi, > > I am experiencing problems with my Epson Stylus SX525WD. I connected via > USB and installed the Epson SANE drivers from epson.net (iscan-data and > iscan) on my 64-bit Ubuntu 12.04 system. The scanner is recognized by > `sane-find-scanner`. Did you try connecting it via wireless? Does it work better there? I have a BX525WD which works fine, but it has always beenj connected via wireless, I haven't tried usb. Details: tingo at kg-u35jc:~$ lsb_release -a LSB Version: core-2.0-amd64:core-2.0-noarch:core-3.0-amd64:core-3.0-noarch:core-3.1-amd64:core-3.1-noarch:core-3.2-amd64:core-3.2-noarch:core-4.0-amd64:core-4.0-noarch:cxx-3.0-amd64:cxx-3.0-noarch:cxx-3.1-amd64:cxx-3.1-noarch:cxx-3.2-amd64:cxx-3.2-noarch:cxx-4.0-amd64:cxx-4.0-noarch:desktop-3.1-amd64:desktop-3.1-noarch:desktop-3.2-amd64:desktop-3.2-noarch:desktop-4.0-amd64:desktop-4.0-noarch:graphics-2.0-amd64:graphics-2.0-noarch:graphics-3.0-amd64:graphics-3.0-noarch:graphics-3.1-amd64:graphics-3.1-noarch:graphics-3.2-amd64:graphics-3.2-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-3.2-amd64:printing-3.2-noarch:printing-4.0-amd64:printing-4.0-noarch:qt4-3.1-amd64:qt4-3.1-noarch Distributor ID: Ubuntu Description:Ubuntu 12.04.1 LTS Release:12.04 Codename: precise tingo at kg-u35jc:~$ uname -a Linux kg-u35jc 3.2.0-32-generic #51-Ubuntu SMP Wed Sep 26 21:33:09 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux sane-find-scanner doesn't find the scanner, but scanimage does: tingo at kg-u35jc:~$ scanimage -L device `epson2:net:10.1.161.8' is a Epson PID 085E flatbed scanner HTH -- Regards, Torfinn Ingolfsen