492 lines
16 KiB
Diff
492 lines
16 KiB
Diff
|
From 9282aef3c04c50d198e54225dc1db26d5cf70d4d Mon Sep 17 00:00:00 2001
|
||
|
From: Nils Philippsen <nils@redhat.com>
|
||
|
Date: Fri, 1 Feb 2013 16:50:29 +0100
|
||
|
Subject: [PATCH] patch: coolscan-multiscan
|
||
|
|
||
|
Squashed commit of the following:
|
||
|
|
||
|
commit 8c83fd9274e41cc44e84c62eb4294e07e6651584
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Fri Dec 14 19:00:42 2012 +0100
|
||
|
|
||
|
coolscan3: average multiple samples
|
||
|
|
||
|
(ported from coolscan2, commit 4126b6796dfc79152408e387e923a73e96814191)
|
||
|
(cherry picked from commit a1273d1c6500ff9c8bf68946dda910da02834b01)
|
||
|
|
||
|
commit 9856fd6b83eef5d5dde48b8627716bca48dde36f
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Fri Dec 14 18:20:08 2012 +0100
|
||
|
|
||
|
coolscan3: set multi-sampling on scanner
|
||
|
|
||
|
(ported from coolscan2, commit 238565790449b5257c34ef4cb69edd789e884b7d)
|
||
|
(cherry picked from commit 2bc59796cad213d9a40b2eb0d4ecbf80e4e9b351)
|
||
|
|
||
|
commit 946511ce3508c96cd749021a249d28b3b79e7daa
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Fri Dec 14 18:12:01 2012 +0100
|
||
|
|
||
|
coolscan3: only offer samples-per-scan for devices supporting it
|
||
|
|
||
|
(ported from coolscan2, commit ed9ac6f15df070767f1532b24aad4b5b8e92156f)
|
||
|
(cherry picked from commit 6589dbd5c027fb008383ff5d748c1b9ec209d2b1)
|
||
|
|
||
|
commit a75d020371e81e179b87050ed014fa36bac03d9a
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Fri Dec 14 18:09:28 2012 +0100
|
||
|
|
||
|
coolscan3: add samples-per-scan option
|
||
|
|
||
|
(ported from coolscan2, commit 121afa695b94af64821a75adee919637ef5a1b73)
|
||
|
(cherry picked from commit 82139b08239f87d329c4f216655926bd7d9d6581)
|
||
|
|
||
|
commit b9bf83802012646c9d40e1dab9843025fba0cc21
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Sun Apr 1 05:01:09 2012 +0200
|
||
|
|
||
|
coolscan2: average multiple samples
|
||
|
(cherry picked from commit 4126b6796dfc79152408e387e923a73e96814191)
|
||
|
|
||
|
commit bc12adabf430cae57bf195ef228b64e3d493b265
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Sat Mar 31 20:48:37 2012 +0200
|
||
|
|
||
|
coolscan2: set multi-sampling on scanner
|
||
|
(cherry picked from commit 238565790449b5257c34ef4cb69edd789e884b7d)
|
||
|
|
||
|
commit 924fd319a339fa48e2efe40ba2b8292336c33e7c
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Sat Mar 31 21:39:01 2012 +0200
|
||
|
|
||
|
coolscan2: only offer samples-per-scan for devices supporting it
|
||
|
(cherry picked from commit ed9ac6f15df070767f1532b24aad4b5b8e92156f)
|
||
|
|
||
|
commit bdcb3aec8501d25560253a937ef1e5ddc06432cb
|
||
|
Author: Nils Philippsen <nils@tiptoe.de>
|
||
|
Date: Sat Mar 31 20:48:16 2012 +0200
|
||
|
|
||
|
coolscan2: add samples-per-scan option
|
||
|
(cherry picked from commit 121afa695b94af64821a75adee919637ef5a1b73)
|
||
|
---
|
||
|
backend/coolscan2.c | 103 +++++++++++++++++++++++++++++++++++++++++++-------
|
||
|
backend/coolscan3.c | 106 ++++++++++++++++++++++++++++++++++++++++++++--------
|
||
|
2 files changed, 179 insertions(+), 30 deletions(-)
|
||
|
|
||
|
diff --git a/backend/coolscan2.c b/backend/coolscan2.c
|
||
|
index 43d6c55..9f9efde 100644
|
||
|
--- a/backend/coolscan2.c
|
||
|
+++ b/backend/coolscan2.c
|
||
|
@@ -181,6 +181,8 @@ typedef enum
|
||
|
|
||
|
CS2_OPTION_INFRARED,
|
||
|
|
||
|
+ CS2_OPTION_SAMPLES_PER_SCAN,
|
||
|
+
|
||
|
CS2_OPTION_DEPTH,
|
||
|
|
||
|
CS2_OPTION_EXPOSURE,
|
||
|
@@ -249,8 +251,8 @@ typedef struct
|
||
|
|
||
|
/* settings */
|
||
|
SANE_Bool preview, negative, infrared;
|
||
|
- int depth, real_depth, bytes_per_pixel, shift_bits, n_colour_in,
|
||
|
- n_colour_out;
|
||
|
+ int samples_per_scan, depth, real_depth, bytes_per_pixel, shift_bits,
|
||
|
+ n_colour_in, n_colour_out;
|
||
|
cs2_pixel_t n_lut;
|
||
|
cs2_pixel_t *lut_r, *lut_g, *lut_b, *lut_neutral;
|
||
|
unsigned long resx, resy, res, res_independent, res_preview;
|
||
|
@@ -508,6 +510,29 @@ sane_open (SANE_String_Const name, SANE_Handle * h)
|
||
|
o.size = WSIZE;
|
||
|
o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||
|
break;
|
||
|
+ case CS2_OPTION_SAMPLES_PER_SCAN:
|
||
|
+ o.name = "samples-per-scan";
|
||
|
+ o.title = "Samples per Scan";
|
||
|
+ o.desc = "Number of samples per scan";
|
||
|
+ o.type = SANE_TYPE_INT;
|
||
|
+ o.unit = SANE_UNIT_NONE;
|
||
|
+ o.size = WSIZE;
|
||
|
+ o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||
|
+ if (s->type != CS2_TYPE_LS2000 && s->type != CS2_TYPE_LS4000
|
||
|
+ && s->type != CS2_TYPE_LS5000 && s->type != CS2_TYPE_LS8000)
|
||
|
+ o.cap |= SANE_CAP_INACTIVE;
|
||
|
+ o.constraint_type = SANE_CONSTRAINT_RANGE;
|
||
|
+ range = (SANE_Range *) cs2_xmalloc (sizeof (SANE_Range));
|
||
|
+ if (! range)
|
||
|
+ alloc_failed = 1;
|
||
|
+ else
|
||
|
+ {
|
||
|
+ range->min = 1;
|
||
|
+ range->max = 16;
|
||
|
+ range->quant = 1;
|
||
|
+ o.constraint.range = range;
|
||
|
+ }
|
||
|
+ break;
|
||
|
case CS2_OPTION_DEPTH:
|
||
|
o.name = "depth";
|
||
|
o.title = "Bit depth per channel";
|
||
|
@@ -994,6 +1019,7 @@ sane_open (SANE_String_Const name, SANE_Handle * h)
|
||
|
s->negative = SANE_FALSE;
|
||
|
s->depth = 8;
|
||
|
s->infrared = 0;
|
||
|
+ s->samples_per_scan = 1;
|
||
|
s->i_frame = 1;
|
||
|
s->subframe = 0.;
|
||
|
s->res = s->resx = s->resx_max;
|
||
|
@@ -1080,6 +1106,9 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v,
|
||
|
case CS2_OPTION_INFRARED:
|
||
|
*(SANE_Word *) v = s->infrared;
|
||
|
break;
|
||
|
+ case CS2_OPTION_SAMPLES_PER_SCAN:
|
||
|
+ *(SANE_Word *) v = s->samples_per_scan;
|
||
|
+ break;
|
||
|
case CS2_OPTION_DEPTH:
|
||
|
*(SANE_Word *) v = s->depth;
|
||
|
break;
|
||
|
@@ -1231,6 +1260,9 @@ sane_control_option (SANE_Handle h, SANE_Int n, SANE_Action a, void *v,
|
||
|
s->infrared = *(SANE_Word *) v;
|
||
|
/* flags |= SANE_INFO_RELOAD_PARAMS; XXXXXXXXXXXXXXXXX */
|
||
|
break;
|
||
|
+ case CS2_OPTION_SAMPLES_PER_SCAN:
|
||
|
+ s->samples_per_scan = *(SANE_Word *) v;
|
||
|
+ break;
|
||
|
case CS2_OPTION_DEPTH:
|
||
|
s->depth = *(SANE_Word *) v;
|
||
|
flags |= SANE_INFO_RELOAD_PARAMS;
|
||
|
@@ -1462,9 +1494,10 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
SANE_Status status;
|
||
|
ssize_t xfer_len_in, xfer_len_line, xfer_len_out;
|
||
|
unsigned long index;
|
||
|
- int colour;
|
||
|
+ int colour, n_colours, sample_pass;
|
||
|
uint8_t *s8 = NULL;
|
||
|
uint16_t *s16 = NULL;
|
||
|
+ double m_avg_sum;
|
||
|
SANE_Byte *line_buf_new;
|
||
|
|
||
|
DBG (10, "sane_read() called, maxlen = %i.\n", maxlen);
|
||
|
@@ -1554,6 +1587,9 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
s->n_line_buf = xfer_len_line;
|
||
|
}
|
||
|
|
||
|
+ /* adapt for multi-sampling */
|
||
|
+ xfer_len_in *= s->samples_per_scan;
|
||
|
+
|
||
|
cs2_scanner_ready (s, CS2_STATUS_READY);
|
||
|
cs2_init_buffer (s);
|
||
|
cs2_parse_cmd (s, "28 00 00 00 00 00");
|
||
|
@@ -1570,24 +1606,44 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
+ n_colours = s->n_colour_out +
|
||
|
+ (s->infrared_stage == CS2_INFRARED_IN ? 1 : 0);
|
||
|
+
|
||
|
for (index = 0; index < s->logical_width; index++)
|
||
|
- for (colour = 0;
|
||
|
- colour < s->n_colour_out + (s->infrared_stage ==
|
||
|
- CS2_INFRARED_IN ? 1 : 0); colour++)
|
||
|
+ for (colour = 0; colour < n_colours; colour++) {
|
||
|
+ m_avg_sum = 0.0;
|
||
|
switch (s->bytes_per_pixel)
|
||
|
{
|
||
|
case 1:
|
||
|
+ /* calculate target address */
|
||
|
if ((s->infrared_stage == CS2_INFRARED_IN)
|
||
|
&& (colour == s->n_colour_out))
|
||
|
s8 = (uint8_t *) & (s->infrared_buf[s->infrared_index++]);
|
||
|
else
|
||
|
s8 =
|
||
|
(uint8_t *) & (s->line_buf[s->n_colour_out * index + colour]);
|
||
|
- *s8 =
|
||
|
- s->recv_buf[colour * s->logical_width +
|
||
|
- (colour + 1) * s->odd_padding + index];
|
||
|
+
|
||
|
+ if (s->samples_per_scan > 1)
|
||
|
+ {
|
||
|
+ /* calculate average of multi samples */
|
||
|
+ for (sample_pass = 0;
|
||
|
+ sample_pass < s->samples_per_scan;
|
||
|
+ sample_pass++)
|
||
|
+ m_avg_sum += (double)
|
||
|
+ s->recv_buf[s->logical_width *
|
||
|
+ (sample_pass * n_colours + colour) +
|
||
|
+ (colour + 1) * s->odd_padding + index];
|
||
|
+
|
||
|
+ *s8 = (uint8_t) (m_avg_sum / s->samples_per_scan + 0.5);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ /* shortcut for single sample */
|
||
|
+ *s8 =
|
||
|
+ s->recv_buf[colour * s->logical_width +
|
||
|
+ (colour + 1) * s->odd_padding + index];
|
||
|
break;
|
||
|
case 2:
|
||
|
+ /* calculate target address */
|
||
|
if ((s->infrared_stage == CS2_INFRARED_IN)
|
||
|
&& (colour == s->n_colour_out))
|
||
|
s16 =
|
||
|
@@ -1597,9 +1653,24 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
(uint16_t *) & (s->
|
||
|
line_buf[2 *
|
||
|
(s->n_colour_out * index + colour)]);
|
||
|
- *s16 =
|
||
|
- s->recv_buf[2 * (colour * s->logical_width + index)] * 256 +
|
||
|
- s->recv_buf[2 * (colour * s->logical_width + index) + 1];
|
||
|
+
|
||
|
+ if (s->samples_per_scan > 1)
|
||
|
+ {
|
||
|
+ /* calculate average of multi samples */
|
||
|
+ for (sample_pass = 0;
|
||
|
+ s->samples_per_scan > 1 && sample_pass < s->samples_per_scan;
|
||
|
+ sample_pass++)
|
||
|
+ m_avg_sum += (double)
|
||
|
+ (s->recv_buf[2 * (s->logical_width * (sample_pass * n_colours + colour) + index)] * 256 +
|
||
|
+ s->recv_buf[2 * (s->logical_width * (sample_pass * n_colours + colour) + index) + 1]);
|
||
|
+
|
||
|
+ *s16 = (uint16_t) (m_avg_sum / s->samples_per_scan + 0.5);
|
||
|
+ }
|
||
|
+ else
|
||
|
+ /* shortcut for single sample */
|
||
|
+ *s16 =
|
||
|
+ s->recv_buf[2 * (colour * s->logical_width + index)] * 256 +
|
||
|
+ s->recv_buf[2 * (colour * s->logical_width + index) + 1];
|
||
|
*s16 <<= s->shift_bits;
|
||
|
break;
|
||
|
default:
|
||
|
@@ -1608,6 +1679,7 @@ sane_read (SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
return SANE_STATUS_INVAL;
|
||
|
break;
|
||
|
}
|
||
|
+ }
|
||
|
s->xfer_position += xfer_len_line;
|
||
|
|
||
|
xfer_len_out = xfer_len_line;
|
||
|
@@ -2870,7 +2942,7 @@ cs2_scan (cs2_t * s, cs2_scan_t type)
|
||
|
cs2_pack_byte (s, 0x05); /* image composition CCCCCCC */
|
||
|
cs2_pack_byte (s, s->real_depth); /* pixel composition */
|
||
|
cs2_parse_cmd (s, "00 00 00 00 00 00 00 00 00 00 00 00 00");
|
||
|
- cs2_pack_byte (s, 0x00); /* multiread, ordering */
|
||
|
+ cs2_pack_byte (s, ((s->samples_per_scan - 1) << 4) + 0x00); /* multiread, ordering */
|
||
|
/* No need to use an undocumented bit in LS50 */
|
||
|
if ((s->type == CS2_TYPE_LS50) || (s->type == CS2_TYPE_LS5000))
|
||
|
cs2_pack_byte (s, 0x00 + (s->negative ? 0 : 1)); /* averaging, pos/neg */
|
||
|
@@ -2892,7 +2964,10 @@ cs2_scan (cs2_t * s, cs2_scan_t type)
|
||
|
DBG (1, "BUG: cs2_scan(): Unknown scanning type.\n");
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
- cs2_pack_byte (s, 0x02); /* scanning mode */
|
||
|
+ if (s->samples_per_scan == 1)
|
||
|
+ cs2_pack_byte (s, 0x02); /* scanning mode single */
|
||
|
+ else
|
||
|
+ cs2_pack_byte (s, 0x10); /* scanning mode multi */
|
||
|
cs2_pack_byte (s, 0x02); /* colour interleaving */
|
||
|
cs2_pack_byte (s, 0xff); /* (ae) */
|
||
|
if (i_colour == 3) /* infrared */
|
||
|
diff --git a/backend/coolscan3.c b/backend/coolscan3.c
|
||
|
index eca357c..a1d6fe6 100644
|
||
|
--- a/backend/coolscan3.c
|
||
|
+++ b/backend/coolscan3.c
|
||
|
@@ -115,6 +115,8 @@ typedef enum
|
||
|
|
||
|
CS3_OPTION_INFRARED,
|
||
|
|
||
|
+ CS3_OPTION_SAMPLES_PER_SCAN,
|
||
|
+
|
||
|
CS3_OPTION_DEPTH,
|
||
|
|
||
|
CS3_OPTION_EXPOSURE,
|
||
|
@@ -212,7 +214,8 @@ typedef struct
|
||
|
|
||
|
/* settings */
|
||
|
SANE_Bool preview, negative, infrared, autoload, autofocus, ae, aewb;
|
||
|
- int depth, real_depth, bytes_per_pixel, shift_bits, n_colors;
|
||
|
+ int samples_per_scan, depth, real_depth, bytes_per_pixel, shift_bits,
|
||
|
+ n_colors;
|
||
|
cs3_pixel_t n_lut;
|
||
|
cs3_pixel_t *lut_r, *lut_g, *lut_b, *lut_neutral;
|
||
|
unsigned long resx, resy, res, res_independent, res_preview;
|
||
|
@@ -463,6 +466,30 @@ sane_open(SANE_String_Const name, SANE_Handle * h)
|
||
|
#endif
|
||
|
break;
|
||
|
|
||
|
+ case CS3_OPTION_SAMPLES_PER_SCAN:
|
||
|
+ o.name = "samples-per-scan";
|
||
|
+ o.title = "Samples per Scan";
|
||
|
+ o.desc = "Number of samples per scan";
|
||
|
+ o.type = SANE_TYPE_INT;
|
||
|
+ o.unit = SANE_UNIT_NONE;
|
||
|
+ o.size = WSIZE;
|
||
|
+ o.cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
|
||
|
+ if (s->type != CS3_TYPE_LS2000 && s->type != CS3_TYPE_LS4000
|
||
|
+ && s->type != CS3_TYPE_LS5000 && s->type != CS3_TYPE_LS8000)
|
||
|
+ o.cap |= SANE_CAP_INACTIVE;
|
||
|
+ o.constraint_type = SANE_CONSTRAINT_RANGE;
|
||
|
+ range = (SANE_Range *) cs3_xmalloc (sizeof (SANE_Range));
|
||
|
+ if (! range)
|
||
|
+ alloc_failed = 1;
|
||
|
+ else
|
||
|
+ {
|
||
|
+ range->min = 1;
|
||
|
+ range->max = 16;
|
||
|
+ range->quant = 1;
|
||
|
+ o.constraint.range = range;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
case CS3_OPTION_DEPTH:
|
||
|
o.name = "depth";
|
||
|
o.title = "Bit depth per channel";
|
||
|
@@ -983,6 +1010,7 @@ sane_open(SANE_String_Const name, SANE_Handle * h)
|
||
|
s->infrared = SANE_FALSE;
|
||
|
s->ae = SANE_FALSE;
|
||
|
s->aewb = SANE_FALSE;
|
||
|
+ s->samples_per_scan = 1;
|
||
|
s->depth = 8;
|
||
|
s->i_frame = 1;
|
||
|
s->frame_count = 1;
|
||
|
@@ -1064,6 +1092,9 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v,
|
||
|
case CS3_OPTION_INFRARED:
|
||
|
*(SANE_Word *) v = s->infrared;
|
||
|
break;
|
||
|
+ case CS3_OPTION_SAMPLES_PER_SCAN:
|
||
|
+ *(SANE_Word *) v = s->samples_per_scan;
|
||
|
+ break;
|
||
|
case CS3_OPTION_DEPTH:
|
||
|
*(SANE_Word *) v = s->depth;
|
||
|
break;
|
||
|
@@ -1222,6 +1253,9 @@ sane_control_option(SANE_Handle h, SANE_Int n, SANE_Action a, void *v,
|
||
|
s->infrared = *(SANE_Word *) v;
|
||
|
/* flags |= SANE_INFO_RELOAD_PARAMS; XXX */
|
||
|
break;
|
||
|
+ case CS3_OPTION_SAMPLES_PER_SCAN:
|
||
|
+ s->samples_per_scan = *(SANE_Word *) v;
|
||
|
+ break;
|
||
|
case CS3_OPTION_DEPTH:
|
||
|
if (*(SANE_Word *) v > s->maxbits)
|
||
|
return SANE_STATUS_INVAL;
|
||
|
@@ -1487,9 +1521,10 @@ sane_read(SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
SANE_Status status;
|
||
|
ssize_t xfer_len_in, xfer_len_line, xfer_len_out;
|
||
|
unsigned long index;
|
||
|
- int color;
|
||
|
+ int color, sample_pass;
|
||
|
uint8_t *s8 = NULL;
|
||
|
uint16_t *s16 = NULL;
|
||
|
+ double m_avg_sum;
|
||
|
SANE_Byte *line_buf_new;
|
||
|
|
||
|
DBG(32, "%s, maxlen = %i.\n", __func__, maxlen);
|
||
|
@@ -1567,6 +1602,9 @@ sane_read(SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
s->n_line_buf = xfer_len_line;
|
||
|
}
|
||
|
|
||
|
+ /* adapt for multi-sampling */
|
||
|
+ xfer_len_in *= s->samples_per_scan;
|
||
|
+
|
||
|
cs3_scanner_ready(s, CS3_STATUS_READY);
|
||
|
cs3_init_buffer(s);
|
||
|
cs3_parse_cmd(s, "28 00 00 00 00 00");
|
||
|
@@ -1584,30 +1622,63 @@ sane_read(SANE_Handle h, SANE_Byte * buf, SANE_Int maxlen, SANE_Int * len)
|
||
|
|
||
|
for (index = 0; index < s->logical_width; index++) {
|
||
|
for (color = 0; color < s->n_colors; color++) {
|
||
|
-
|
||
|
int where = s->bytes_per_pixel
|
||
|
* (s->n_colors * index + color);
|
||
|
|
||
|
+ m_avg_sum = 0.0;
|
||
|
+
|
||
|
switch (s->bytes_per_pixel) {
|
||
|
case 1:
|
||
|
{
|
||
|
- int p8 = color * s->logical_width
|
||
|
- + (color + 1) * s->odd_padding
|
||
|
- + index;
|
||
|
-
|
||
|
+ /* target address */
|
||
|
s8 = (uint8_t *) & (s->line_buf[where]);
|
||
|
- *s8 = s->recv_buf[p8];
|
||
|
+
|
||
|
+ if (s->samples_per_scan > 1) {
|
||
|
+ /* calculate average of multi samples */
|
||
|
+ for (sample_pass = 0;
|
||
|
+ sample_pass < s->samples_per_scan;
|
||
|
+ sample_pass++) {
|
||
|
+ /* source index */
|
||
|
+ int p8 = (sample_pass * s->n_colors + color)
|
||
|
+ * s->logical_width
|
||
|
+ + (color + 1) * s->odd_padding
|
||
|
+ + index;
|
||
|
+ m_avg_sum += (double) s->recv_buf[p8];
|
||
|
+ }
|
||
|
+ *s8 = (uint8_t) (m_avg_sum / s->samples_per_scan + 0.5);
|
||
|
+ } else {
|
||
|
+ /* shortcut for single sample */
|
||
|
+ int p8 = s->logical_width * color
|
||
|
+ + (color + 1) * s->odd_padding
|
||
|
+ + index;
|
||
|
+ *s8 = s->recv_buf[p8];
|
||
|
+ }
|
||
|
}
|
||
|
break;
|
||
|
case 2:
|
||
|
{
|
||
|
- int p16 =
|
||
|
- 2 * (color * s->logical_width +
|
||
|
- index);
|
||
|
-
|
||
|
+ /* target address */
|
||
|
s16 = (uint16_t *) & (s->line_buf[where]);
|
||
|
- *s16 = (s->recv_buf[p16] << 8)
|
||
|
- + s->recv_buf[p16 + 1];
|
||
|
+
|
||
|
+ if (s->samples_per_scan > 1) {
|
||
|
+ /* calculate average of multi samples */
|
||
|
+ for (sample_pass = 0;
|
||
|
+ sample_pass < s->samples_per_scan;
|
||
|
+ sample_pass++) {
|
||
|
+ /* source index */
|
||
|
+ int p16 = 2 * ((sample_pass * s->n_colors + color)
|
||
|
+ * s->logical_width + index);
|
||
|
+ m_avg_sum += (double) ((s->recv_buf[p16] << 8)
|
||
|
+ + s->recv_buf[p16 + 1]);
|
||
|
+ }
|
||
|
+ *s16 = (uint16_t) (m_avg_sum / s->samples_per_scan + 0.5);
|
||
|
+ } else {
|
||
|
+ /* shortcut for single sample */
|
||
|
+ int p16 = 2 * (color * s->logical_width + index);
|
||
|
+
|
||
|
+ *s16 = (s->recv_buf[p16] << 8)
|
||
|
+ + s->recv_buf[p16 + 1];
|
||
|
+ }
|
||
|
|
||
|
*s16 <<= s->shift_bits;
|
||
|
}
|
||
|
@@ -2955,7 +3026,7 @@ cs3_set_window(cs3_t * s, cs3_scan_t type)
|
||
|
cs3_pack_byte(s, 0x05); /* image composition CCCCCCC */
|
||
|
cs3_pack_byte(s, s->real_depth); /* pixel composition */
|
||
|
cs3_parse_cmd(s, "00 00 00 00 00 00 00 00 00 00 00 00 00");
|
||
|
- cs3_pack_byte(s, 0x00); /* multiread, ordering */
|
||
|
+ cs3_pack_byte(s, ((s->samples_per_scan - 1) << 4) | 0x00); /* multiread, ordering */
|
||
|
|
||
|
cs3_pack_byte(s, 0x80 | (s->negative ? 0 : 1)); /* averaging, pos/neg */
|
||
|
|
||
|
@@ -2973,7 +3044,10 @@ cs3_set_window(cs3_t * s, cs3_scan_t type)
|
||
|
DBG(1, "BUG: cs3_scan(): Unknown scanning type.\n");
|
||
|
return SANE_STATUS_INVAL;
|
||
|
}
|
||
|
- cs3_pack_byte(s, 0x02); /* scanning mode */
|
||
|
+ if (s->samples_per_scan == 1)
|
||
|
+ cs3_pack_byte(s, 0x02); /* scanning mode single */
|
||
|
+ else
|
||
|
+ cs3_pack_byte(s, 0x10); /* scanning mode multi */
|
||
|
cs3_pack_byte(s, 0x02); /* color interleaving */
|
||
|
cs3_pack_byte(s, 0xff); /* (ae) */
|
||
|
if (color == 3) /* infrared */
|
||
|
--
|
||
|
1.8.1
|
||
|
|