1 /* sane - Scanner Access Now Easy.
2
3 Copyright (C) 1997, 1998, 2002, 2013 Franck Schnefra, Michel Roelofs,
4 Emmanuel Blot, Mikko Tyolajarvi, David Mosberger-Tang, Wolfgang Goeller,
5 Petter Reinholdtsen, Gary Plewa, Sebastien Sable, Max Ushakov,
6 Andrew Goodbody, Oliver Schwartz and Kevin Charter
7
8 This file is part of the SANE package.
9
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2 of the
13 License, or (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <https://www.gnu.org/licenses/>.
22
23 As a special exception, the authors of SANE give permission for
24 additional uses of the libraries contained in this release of SANE.
25
26 The exception is that, if you link a SANE library with other files
27 to produce an executable, this does not by itself cause the
28 resulting executable to be covered by the GNU General Public
29 License. Your use of that executable is in no way restricted on
30 account of linking the SANE library code into it.
31
32 This exception does not, however, invalidate any other reasons why
33 the executable file might be covered by the GNU General Public
34 License.
35
36 If you submit changes to SANE to the maintainers to be included in
37 a subsequent release, you agree by submitting the changes that
38 those changes may be distributed with this exception intact.
39
40 If you write modifications of your own for SANE, it is your choice
41 whether to permit this exception to apply to your modifications.
42 If you do not wish that, delete this exception notice.
43
44 This file is a component of the implementation of a backend for many
45 of the AGFA SnapScan and Acer Vuego/Prisa flatbed scanners.
46 */
47
48 /*
49 SnapScan backend data sources (implementation)
50 */
51
52 /**************************************************************************************
53 If you get confused from all the structs (like I did when I first saw them),
54 think of it as "C++ in C". If you're accustomed to OO and UML maybe the
55 following diagram helps you to make sense of it:
56
57 ------------------------
58 ! Source !
59 ------------------------
60 !pss: SnapScan_Scanner*!
61 ------------------------ +psub
62 !init() = 0 !-----------------
63 !remaining() = 0 ! !
64 !bytesPerLine() ! !
65 !pixelsPerLine() ! !
66 !get() = 0 ! !{TransformerSource forwards
67 !done() = 0 ! ! function calls to corres-
68 ------------------------ ! ponding functions in psub}
69 ^ !
70 /_\ !
71 ! !
72 -------------------------------------------------- /\
73 ! ! ! ! \/
74 ------------- ------------- ------------- -------------------
75 !SCSISource ! ! FDSource ! !BufSource ! !TransformerSource!
76 ============= ============= ============= ===================
77 !remaining()! !remaining()! !remaining()! !init() !
78 !get() ! !get() ! !get() ! !remaining() !
79 !done() ! !done() ! !done() ! !bytesPerLine() !
80 !init() ! !init() ! !init() ! !pixelsPerLine() !
81 ------------- ------------- ------------- !get() !
82 !done() !
83 -------------------
84 ^
85 /_\
86 !
87 ------------------------------------
88 ! ! !
89 ---------------- ------------- -------------
90 ! Expander ! ! RGBRouter ! ! Inverter !
91 ================ ============= =============
92 !remaining() ! !remaining()! !remaining()!
93 !bytesPerLine()! !get() ! !get() !
94 !get() ! !done() ! !done() !
95 !done() ! !init() ! !init() !
96 !init() ! ------------- -------------
97 ----------------
98 All instances of the descendants of TransformerSource can be chained together. For
99 color scanning, a typical source chain would consist of an RGBRouter sitting on top
100 of a SCSISource. In the get() method, RGBRouter will then call the get() method of
101 the subsource, process the data and return it.
102
103 I hope this makes sense to you (and I got the right idea of the original author's
104 intention).
105 ***********************************************************************************/
106
Source_init(Source * pself,SnapScan_Scanner * pss,SourceRemaining remaining,SourceBytesPerLine bytesPerLine,SourcePixelsPerLine pixelsPerLine,SourceGet get,SourceDone done)107 static SANE_Status Source_init (Source *pself,
108 SnapScan_Scanner *pss,
109 SourceRemaining remaining,
110 SourceBytesPerLine bytesPerLine,
111 SourcePixelsPerLine pixelsPerLine,
112 SourceGet get,
113 SourceDone done)
114 {
115 pself->pss = pss;
116 pself->remaining = remaining;
117 pself->bytesPerLine = bytesPerLine;
118 pself->pixelsPerLine = pixelsPerLine;
119 pself->get = get;
120 pself->done = done;
121 return SANE_STATUS_GOOD;
122 }
123
124 /* these are defaults, normally used only by base sources */
125
Source_bytesPerLine(Source * pself)126 static SANE_Int Source_bytesPerLine (Source *pself)
127 {
128 return pself->pss->bytes_per_line;
129 }
130
Source_pixelsPerLine(Source * pself)131 static SANE_Int Source_pixelsPerLine (Source *pself)
132 {
133 return pself->pss->pixels_per_line;
134 }
135
136 /**********************************************************************/
137
138 /* the base sources */
139 typedef enum
140 {
141 SCSI_SRC,
142 FD_SRC,
143 BUF_SRC
144 } BaseSourceType;
145
146
147 typedef struct
148 {
149 SOURCE_GUTS;
150 SANE_Int scsi_buf_pos; /* current position in scsi buffer */
151 SANE_Int scsi_buf_max; /* data limit */
152 SANE_Int absolute_max; /* largest possible data read */
153 } SCSISource;
154
SCSISource_remaining(Source * pself)155 static SANE_Int SCSISource_remaining (Source *pself)
156 {
157 SCSISource *ps = (SCSISource *) pself;
158 return ps->pss->bytes_remaining + (ps->scsi_buf_max - ps->scsi_buf_pos);
159 }
160
SCSISource_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)161 static SANE_Status SCSISource_get (Source *pself,
162 SANE_Byte *pbuf,
163 SANE_Int *plen)
164 {
165 SCSISource *ps = (SCSISource *) pself;
166 SANE_Status status = SANE_STATUS_GOOD;
167 SANE_Int remaining = *plen;
168 char* me = "SCSISource_get";
169
170 DBG (DL_CALL_TRACE, "%s\n", me);
171 while (remaining > 0
172 && pself->remaining(pself) > 0
173 && status == SANE_STATUS_GOOD
174 && !cancelRead)
175 {
176 SANE_Int ndata = ps->scsi_buf_max - ps->scsi_buf_pos;
177 DBG (DL_DATA_TRACE, "%s: ndata %d; remaining %d\n", me, ndata, remaining);
178 if (ndata == 0)
179 {
180 ps->pss->expected_read_bytes = MIN((size_t)ps->absolute_max,
181 ps->pss->bytes_remaining);
182 ps->scsi_buf_pos = 0;
183 ps->scsi_buf_max = 0;
184 status = scsi_read (ps->pss, READ_IMAGE);
185 if (status != SANE_STATUS_GOOD)
186 break;
187 ps->scsi_buf_max = ps->pss->read_bytes;
188 ndata = ps->pss->read_bytes;
189 ps->pss->bytes_remaining -= ps->pss->read_bytes;
190 DBG (DL_DATA_TRACE, "%s: pos: %d; max: %d; expected: %lu; read: %lu\n",
191 me, ps->scsi_buf_pos, ps->scsi_buf_max, (u_long) ps->pss->expected_read_bytes,
192 (u_long) ps->pss->read_bytes);
193 }
194 ndata = MIN(ndata, remaining);
195 memcpy (pbuf, ps->pss->buf + ps->scsi_buf_pos, (size_t)ndata);
196 pbuf += ndata;
197 ps->scsi_buf_pos += ndata;
198 remaining -= ndata;
199 }
200 *plen -= remaining;
201 return status;
202 }
203
SCSISource_done(Source * pself)204 static SANE_Status SCSISource_done (Source *pself)
205 {
206 DBG(DL_MINOR_INFO, "SCSISource_done\n");
207 UNREFERENCED_PARAMETER(pself);
208 return SANE_STATUS_GOOD;
209 }
210
SCSISource_init(SCSISource * pself,SnapScan_Scanner * pss)211 static SANE_Status SCSISource_init (SCSISource *pself, SnapScan_Scanner *pss)
212 {
213 SANE_Status status = Source_init ((Source *) pself, pss,
214 SCSISource_remaining,
215 Source_bytesPerLine,
216 Source_pixelsPerLine,
217 SCSISource_get,
218 SCSISource_done);
219 if (status == SANE_STATUS_GOOD)
220 {
221 pself->scsi_buf_max = 0;
222 pself->scsi_buf_pos = 0;
223 pself->absolute_max =
224 (pss->phys_buf_sz/pss->bytes_per_line)*pss->bytes_per_line;
225 }
226 return status;
227 }
228
229 /* File sources */
230
231 typedef struct
232 {
233 SOURCE_GUTS;
234 int fd;
235 SANE_Int bytes_remaining;
236 } FDSource;
237
FDSource_remaining(Source * pself)238 static SANE_Int FDSource_remaining (Source *pself)
239 {
240 FDSource *ps = (FDSource *) pself;
241 return ps->bytes_remaining;
242 }
243
FDSource_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)244 static SANE_Status FDSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
245 {
246 SANE_Status status = SANE_STATUS_GOOD;
247 FDSource *ps = (FDSource *) pself;
248 SANE_Int remaining = *plen;
249
250 while (remaining > 0
251 && pself->remaining(pself) > 0
252 && status == SANE_STATUS_GOOD)
253 {
254 SANE_Int bytes_read = read (ps->fd, pbuf, remaining);
255 if (bytes_read == -1)
256 {
257 if (errno == EAGAIN)
258 {
259 /* No data currently available */
260 break;
261 }
262 /* It's an IO error */
263 DBG (DL_MAJOR_ERROR, "%s: read failed: %s\n",
264 __func__, strerror(errno));
265 status = SANE_STATUS_IO_ERROR;
266 }
267 else if (bytes_read == 0)
268 {
269 /* EOF of current reading */
270 DBG(DL_DATA_TRACE, "%s: EOF\n",__func__);
271 break;
272 }
273 ps->bytes_remaining -= bytes_read;
274 remaining -= bytes_read;
275 pbuf += bytes_read;
276 }
277 *plen -= remaining;
278 return status;
279 }
280
FDSource_done(Source * pself)281 static SANE_Status FDSource_done (Source *pself)
282 {
283 close(((FDSource *) pself)->fd);
284 return SANE_STATUS_GOOD;
285 }
286
FDSource_init(FDSource * pself,SnapScan_Scanner * pss,int fd)287 static SANE_Status FDSource_init (FDSource *pself,
288 SnapScan_Scanner *pss,
289 int fd)
290 {
291 SANE_Status status = Source_init ((Source *) pself,
292 pss,
293 FDSource_remaining,
294 Source_bytesPerLine,
295 Source_pixelsPerLine,
296 FDSource_get,
297 FDSource_done);
298 if (status == SANE_STATUS_GOOD)
299 {
300 pself->fd = fd;
301 pself->bytes_remaining = pss->bytes_per_line * (pss->lines + pss->chroma);
302 }
303 return status;
304 }
305
306
307 /* buffer sources simply read from a pre-filled buffer; we have these
308 so that we can include source chain processing overhead in the
309 measure_transfer_rate() function */
310
311 typedef struct
312 {
313 SOURCE_GUTS;
314 SANE_Byte *buf;
315 SANE_Int buf_size;
316 SANE_Int buf_pos;
317 } BufSource;
318
BufSource_remaining(Source * pself)319 static SANE_Int BufSource_remaining (Source *pself)
320 {
321 BufSource *ps = (BufSource *) pself;
322 return ps->buf_size - ps->buf_pos;
323 }
324
BufSource_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)325 static SANE_Status BufSource_get (Source *pself,
326 SANE_Byte *pbuf,
327 SANE_Int *plen)
328 {
329 BufSource *ps = (BufSource *) pself;
330 SANE_Status status = SANE_STATUS_GOOD;
331 SANE_Int to_move = MIN(*plen, pself->remaining(pself));
332 if (to_move == 0)
333 {
334 status = SANE_STATUS_EOF;
335 }
336 else
337 {
338 memcpy (pbuf, ps->buf + ps->buf_pos, to_move);
339 ps->buf_pos += to_move;
340 *plen = to_move;
341 }
342 return status;
343 }
344
BufSource_done(Source * pself)345 static SANE_Status BufSource_done (Source *pself)
346 {
347 UNREFERENCED_PARAMETER(pself);
348 return SANE_STATUS_GOOD;
349 }
350
BufSource_init(BufSource * pself,SnapScan_Scanner * pss,SANE_Byte * buf,SANE_Int buf_size)351 static SANE_Status BufSource_init (BufSource *pself,
352 SnapScan_Scanner *pss,
353 SANE_Byte *buf,
354 SANE_Int buf_size)
355 {
356 SANE_Status status = Source_init ((Source *) pself,
357 pss,
358 BufSource_remaining,
359 Source_bytesPerLine,
360 Source_pixelsPerLine,
361 BufSource_get,
362 BufSource_done);
363 DBG(DL_DATA_TRACE, "BufSource_init: buf_size=%d\n", buf_size);
364 if (status == SANE_STATUS_GOOD)
365 {
366 pself->buf = buf;
367 pself->buf_size = buf_size;
368 pself->buf_pos = 0;
369 }
370 return status;
371 }
372
373 /* base source creation */
374
create_base_source(SnapScan_Scanner * pss,BaseSourceType st,Source ** pps)375 static SANE_Status create_base_source (SnapScan_Scanner *pss,
376 BaseSourceType st,
377 Source **pps)
378 {
379 SANE_Status status = SANE_STATUS_GOOD;
380 *pps = NULL;
381 switch (st)
382 {
383 case SCSI_SRC:
384 *pps = (Source *) malloc(sizeof(SCSISource));
385 if (*pps == NULL)
386 {
387 DBG (DL_MAJOR_ERROR, "failed to allocate SCSISource");
388 status = SANE_STATUS_NO_MEM;
389 }
390 else
391 {
392 status = SCSISource_init ((SCSISource *) *pps, pss);
393 }
394 break;
395 case FD_SRC:
396 *pps = (Source *) malloc(sizeof(FDSource));
397 if (*pps == NULL)
398 {
399 DBG (DL_MAJOR_ERROR, "failed to allocate FDSource");
400 status = SANE_STATUS_NO_MEM;
401 }
402 else
403 {
404 status = FDSource_init ((FDSource *) *pps, pss, pss->rpipe[0]);
405 }
406 break;
407 case BUF_SRC:
408 *pps = (Source *) malloc(sizeof(BufSource));
409 if (*pps == NULL)
410 {
411 DBG (DL_MAJOR_ERROR, "failed to allocate BufSource");
412 status = SANE_STATUS_NO_MEM;
413 }
414 else
415 {
416 status = BufSource_init ((BufSource *) *pps,
417 pss,
418 pss->buf,
419 pss->read_bytes);
420 }
421 break;
422 default:
423 DBG (DL_MAJOR_ERROR, "illegal base source type %d", st);
424 break;
425 }
426 return status;
427 }
428
429 /**********************************************************************/
430
431 /* The transformer sources */
432
433 #define TX_SOURCE_GUTS \
434 SOURCE_GUTS;\
435 Source *psub /* sub-source */
436
437 typedef struct
438 {
439 TX_SOURCE_GUTS;
440 } TxSource;
441
TxSource_remaining(Source * pself)442 static SANE_Int TxSource_remaining (Source *pself)
443 {
444 TxSource *ps = (TxSource *) pself;
445 return ps->psub->remaining(ps->psub);
446 }
447
TxSource_bytesPerLine(Source * pself)448 static SANE_Int TxSource_bytesPerLine (Source *pself)
449 {
450 TxSource *ps = (TxSource *) pself;
451 return ps->psub->bytesPerLine(ps->psub);
452 }
453
TxSource_pixelsPerLine(Source * pself)454 static SANE_Int TxSource_pixelsPerLine (Source *pself)
455 {
456 TxSource *ps = (TxSource *) pself;
457 return ps->psub->pixelsPerLine(ps->psub);
458 }
459
TxSource_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)460 static SANE_Status TxSource_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
461 {
462 TxSource *ps = (TxSource *) pself;
463 return ps->psub->get(ps->psub, pbuf, plen);
464 }
465
TxSource_done(Source * pself)466 static SANE_Status TxSource_done (Source *pself)
467 {
468 TxSource *ps = (TxSource *) pself;
469 SANE_Status status = ps->psub->done(ps->psub);
470 free(ps->psub);
471 ps->psub = NULL;
472 return status;
473 }
474
TxSource_init(TxSource * pself,SnapScan_Scanner * pss,SourceRemaining remaining,SourceBytesPerLine bytesPerLine,SourcePixelsPerLine pixelsPerLine,SourceGet get,SourceDone done,Source * psub)475 static SANE_Status TxSource_init (TxSource *pself,
476 SnapScan_Scanner *pss,
477 SourceRemaining remaining,
478 SourceBytesPerLine bytesPerLine,
479 SourcePixelsPerLine pixelsPerLine,
480 SourceGet get,
481 SourceDone done,
482 Source *psub)
483 {
484 SANE_Status status = Source_init((Source *) pself,
485 pss,
486 remaining,
487 bytesPerLine,
488 pixelsPerLine,
489 get,
490 done);
491 if (status == SANE_STATUS_GOOD)
492 pself->psub = psub;
493 return status;
494 }
495
496 /* The expander makes three-channel, one-bit, raw scanner data into
497 8-bit data. It is used to support the bilevel colour scanning mode */
498
499 typedef struct
500 {
501 TX_SOURCE_GUTS;
502 SANE_Byte *ch_buf; /* channel buffer */
503 SANE_Int ch_size; /* channel buffer size = #bytes in a channel */
504 SANE_Int ch_ndata; /* actual #bytes in channel buffer */
505 SANE_Int ch_pos; /* position in buffer */
506 SANE_Int bit; /* current bit */
507 SANE_Int last_bit; /* current last bit (counting down) */
508 SANE_Int last_last_bit; /* last bit in the last byte of the channel */
509 } Expander;
510
Expander_remaining(Source * pself)511 static SANE_Int Expander_remaining (Source *pself)
512 {
513 Expander *ps = (Expander *) pself;
514 SANE_Int sub_remaining = TxSource_remaining(pself);
515 SANE_Int sub_bits_per_channel = TxSource_pixelsPerLine(pself);
516 SANE_Int whole_channels = sub_remaining/ps->ch_size;
517 SANE_Int result = whole_channels*sub_bits_per_channel;
518
519 if (ps->ch_pos < ps->ch_size)
520 {
521 SANE_Int bits_covered = MAX((ps->ch_pos - 1)*8, 0) + 7 - ps->bit;
522 result += sub_bits_per_channel - bits_covered;
523 }
524
525 return result;
526 }
527
Expander_bytesPerLine(Source * pself)528 static SANE_Int Expander_bytesPerLine (Source *pself)
529 {
530 return TxSource_pixelsPerLine(pself)*3;
531 }
532
Expander_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)533 static SANE_Status Expander_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
534 {
535 Expander *ps = (Expander *) pself;
536 SANE_Status status = SANE_STATUS_GOOD;
537 SANE_Int remaining = *plen;
538
539 while (remaining > 0
540 &&
541 pself->remaining(pself) > 0 &&
542 !cancelRead)
543 {
544 if (ps->ch_pos == ps->ch_ndata)
545 {
546 /* we need more data; try to get the remainder of the current
547 channel, or else the next channel */
548 SANE_Int ndata = ps->ch_size - ps->ch_ndata;
549 if (ndata == 0)
550 {
551 ps->ch_ndata = 0;
552 ps->ch_pos = 0;
553 ndata = ps->ch_size;
554 }
555 status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata);
556 if (status != SANE_STATUS_GOOD)
557 break;
558 if (ndata == 0)
559 break;
560 ps->ch_ndata += ndata;
561 if (ps->ch_pos == (ps->ch_size - 1))
562 ps->last_bit = ps->last_last_bit;
563 else
564 ps->last_bit = 0;
565 ps->bit = 7;
566 }
567 *pbuf = ((ps->ch_buf[ps->ch_pos] >> ps->bit) & 0x01) ? 0xFF : 0x00;
568 pbuf++;
569 remaining--;
570
571 if (ps->bit == ps->last_bit)
572 {
573 ps->bit = 7;
574 ps->ch_pos++;
575 if (ps->ch_pos == (ps->ch_size - 1))
576 ps->last_bit = ps->last_last_bit;
577 else
578 ps->last_bit = 0;
579 }
580 else
581 {
582 ps->bit--;
583 }
584 }
585
586 *plen -= remaining;
587 return status;
588 }
589
Expander_done(Source * pself)590 static SANE_Status Expander_done (Source *pself)
591 {
592 Expander *ps = (Expander *) pself;
593 SANE_Status status = TxSource_done(pself);
594 free(ps->ch_buf);
595 ps->ch_buf = NULL;
596 ps->ch_size = 0;
597 ps->ch_pos = 0;
598 return status;
599 }
600
Expander_init(Expander * pself,SnapScan_Scanner * pss,Source * psub)601 static SANE_Status Expander_init (Expander *pself,
602 SnapScan_Scanner *pss,
603 Source *psub)
604 {
605 SANE_Status status = TxSource_init((TxSource *) pself,
606 pss,
607 Expander_remaining,
608 Expander_bytesPerLine,
609 TxSource_pixelsPerLine,
610 Expander_get,
611 Expander_done,
612 psub);
613 if (status == SANE_STATUS_GOOD)
614 {
615 pself->ch_size = TxSource_bytesPerLine((Source *) pself)/3;
616 pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size);
617 if (pself->ch_buf == NULL)
618 {
619 DBG (DL_MAJOR_ERROR,
620 "%s: couldn't allocate channel buffer.\n",
621 __func__);
622 status = SANE_STATUS_NO_MEM;
623 }
624 else
625 {
626 pself->ch_ndata = 0;
627 pself->ch_pos = 0;
628 pself->last_last_bit = pself->pixelsPerLine((Source *) pself)%8;
629 if (pself->last_last_bit == 0)
630 pself->last_last_bit = 7;
631 pself->last_last_bit = 7 - pself->last_last_bit;
632 pself->bit = 7;
633 if (pself->ch_size > 1)
634 pself->last_bit = 0;
635 else
636 pself->last_bit = pself->last_last_bit;
637 }
638 }
639 return status;
640 }
641
create_Expander(SnapScan_Scanner * pss,Source * psub,Source ** pps)642 static SANE_Status create_Expander (SnapScan_Scanner *pss,
643 Source *psub,
644 Source **pps)
645 {
646 SANE_Status status = SANE_STATUS_GOOD;
647 *pps = (Source *) malloc(sizeof(Expander));
648 if (*pps == NULL)
649 {
650 DBG (DL_MAJOR_ERROR,
651 "%s: failed to allocate Expander.\n",
652 __func__);
653 status = SANE_STATUS_NO_MEM;
654 }
655 else
656 {
657 status = Expander_init ((Expander *) *pps, pss, psub);
658 }
659 return status;
660 }
661
662 /*
663 This filter implements a fix for scanners that have some columns
664 of pixels offset. Currently it only shifts every other column
665 starting with the first one down ch_offset pixels.
666
667 The Deinterlacer detects if data is in SANE RGB frame format (3 bytes/pixel)
668 or in Grayscale (1 byte/pixel).
669
670 The first ch_offset lines of data in the output are fudged so that even indexed
671 add odd indexed pixels will have the same value. This is necessary because
672 the real pixel values of the columns that are shifted down are not
673 in the data for the first ch_offset lines. A better way to handle this would be to
674 scan in ch_offset extra lines of data, but I haven't figured out how to do this
675 yet.
676
677 */
678
679 typedef struct
680 {
681 TX_SOURCE_GUTS;
682 SANE_Byte *ch_buf; /* channel buffer */
683 SANE_Int ch_size; /* channel buffer size */
684 SANE_Int ch_line_size; /* size of one line */
685 SANE_Int ch_ndata; /* actual #bytes in channel buffer */
686 SANE_Int ch_pos; /* position in buffer */
687 SANE_Int ch_bytes_per_pixel;
688 SANE_Bool ch_lineart;
689 SANE_Int ch_offset; /* The number of lines to be shifted */
690 SANE_Bool ch_past_init; /* flag indicating if we have enough data to shift pixels down */
691 SANE_Bool ch_shift_even; /* flag indicating whether even or odd pixels are shifted */
692 } Deinterlacer;
693
Deinterlacer_remaining(Source * pself)694 static SANE_Int Deinterlacer_remaining (Source *pself)
695 {
696 Deinterlacer *ps = (Deinterlacer *) pself;
697 SANE_Int result = TxSource_remaining(pself);
698 result += ps->ch_ndata - ps->ch_pos;
699 return result;
700 }
701
Deinterlacer_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)702 static SANE_Status Deinterlacer_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
703 {
704 Deinterlacer *ps = (Deinterlacer *) pself;
705 SANE_Status status = SANE_STATUS_GOOD;
706 SANE_Int remaining = *plen;
707 SANE_Int org_len = *plen;
708 char *me = "Deinterlacer_get";
709
710 DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, ch_ndata=%d, ch_pos=%d\n",
711 me, remaining, pself->remaining(pself), ps->ch_ndata, ps->ch_pos);
712
713 while (remaining > 0
714 &&
715 pself->remaining(pself) > 0 &&
716 !cancelRead)
717 {
718 if (ps->ch_pos % (ps->ch_line_size) == ps->ch_ndata % (ps->ch_line_size) )
719 {
720 /* we need more data; try to get the remainder of the current
721 line, or else the next line */
722 SANE_Int ndata = (ps->ch_line_size) - ps->ch_ndata % (ps->ch_line_size);
723 if (ps->ch_pos >= ps->ch_size)
724 {
725 /* wrap to the beginning of the buffer if we need to */
726 ps->ch_ndata = 0;
727 ps->ch_pos = 0;
728 ndata = ps->ch_line_size;
729 }
730 status = TxSource_get(pself, ps->ch_buf + ps->ch_pos, &ndata);
731 if (status != SANE_STATUS_GOOD)
732 break;
733 if (ndata == 0)
734 break;
735 ps->ch_ndata += ndata;
736 }
737 /* Handle special lineart mode: Valid pixels need to be masked */
738 if (ps->ch_lineart)
739 {
740 if (ps->ch_past_init)
741 {
742 if (ps->ch_shift_even)
743 {
744 /* Even columns need to be shifted, i.e. bits 1,3,5,7 -> 0xaa */
745 /* use valid pixels from this line and shifted pixels from ch_size lines back */
746 *pbuf = (ps->ch_buf[ps->ch_pos] & 0x55) |
747 (ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size] & 0xaa);
748 }
749 else
750 {
751 /* Odd columns need to be shifted, i.e. bits 0,2,4,6 -> 0x55 */
752 *pbuf = (ps->ch_buf[ps->ch_pos] & 0xaa) |
753 (ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size] & 0x55);
754 }
755 }
756 else
757 {
758 /* not enough data. duplicate pixel values from previous column */
759 if (ps->ch_shift_even)
760 {
761 /* bits 0,2,4,6 contain valid data -> 0x55 */
762 SANE_Byte valid_pixel = ps->ch_buf[ps->ch_pos] & 0x55;
763 *pbuf = valid_pixel | (valid_pixel >> 1);
764 }
765 else
766 {
767
768 /* bits 1,3,5,7 contain valid data -> 0xaa */
769 SANE_Byte valid_pixel = ps->ch_buf[ps->ch_pos] & 0xaa;
770 *pbuf = valid_pixel | (valid_pixel << 1);
771 }
772 }
773 }
774 else /* colour / grayscale mode */
775 {
776 if ((ps->ch_shift_even && ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 0)) ||
777 (!ps->ch_shift_even && ((ps->ch_pos/ps->ch_bytes_per_pixel) % 2 == 1)))
778 {
779 /* the even indexed pixels need to be shifted down */
780 if (ps->ch_past_init){
781 /* We need to use data 4 lines back */
782 /* So we just go one forward and it will wrap around to 4 back. */
783 *pbuf = ps->ch_buf[(ps->ch_pos + (ps->ch_line_size)) % ps->ch_size];
784 }else{
785 /* Use data from the next pixel for even indexed pixels
786 if we are on the first few lines.
787 TODO: also we will overread the buffer if the buffer read ended
788 on the first pixel. */
789 if (ps->ch_pos % (ps->ch_line_size) == 0 )
790 *pbuf = ps->ch_buf[ps->ch_pos+ps->ch_bytes_per_pixel];
791 else
792 *pbuf = ps->ch_buf[ps->ch_pos-ps->ch_bytes_per_pixel];
793 }
794 }else{
795 /* odd indexed pixels are okay */
796 *pbuf = ps->ch_buf[ps->ch_pos];
797 }
798 }
799 /* set the flag so we know we have enough data to start shifting columns */
800 if (ps->ch_pos >= ps->ch_line_size * ps->ch_offset)
801 ps->ch_past_init = SANE_TRUE;
802
803 pbuf++;
804 remaining--;
805 ps->ch_pos++;
806 }
807
808 *plen -= remaining;
809
810 DBG(DL_DATA_TRACE,
811 "%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n",
812 me,
813 org_len,
814 pself->remaining(pself),
815 *plen,
816 TxSource_remaining(pself),
817 (u_long) ps->pss->bytes_remaining);
818 return status;
819 }
820
Deinterlacer_done(Source * pself)821 static SANE_Status Deinterlacer_done (Source *pself)
822 {
823 Deinterlacer *ps = (Deinterlacer *) pself;
824 SANE_Status status = TxSource_done(pself);
825 free(ps->ch_buf);
826 ps->ch_buf = NULL;
827 ps->ch_size = 0;
828 ps->ch_line_size = 0;
829 ps->ch_pos = 0;
830 return status;
831 }
832
Deinterlacer_init(Deinterlacer * pself,SnapScan_Scanner * pss,Source * psub)833 static SANE_Status Deinterlacer_init (Deinterlacer *pself,
834 SnapScan_Scanner *pss,
835 Source *psub)
836 {
837 SANE_Status status = TxSource_init((TxSource *) pself,
838 pss,
839 Deinterlacer_remaining,
840 TxSource_bytesPerLine,
841 TxSource_pixelsPerLine,
842 Deinterlacer_get,
843 Deinterlacer_done,
844 psub);
845 if (status == SANE_STATUS_GOOD)
846 {
847 pself->ch_shift_even = SANE_TRUE;
848 switch (pss->pdev->model)
849 {
850 case PERFECTION3490:
851 pself->ch_offset = 8;
852 if ((actual_mode(pss) == MD_GREYSCALE) || (actual_mode(pss) == MD_LINEART))
853 pself->ch_shift_even = SANE_FALSE;
854 break;
855 case PERFECTION2480:
856 default:
857 pself->ch_offset = 4;
858 break;
859 }
860 pself->ch_line_size = TxSource_bytesPerLine((Source *) pself);
861 /* We need at least ch_offset+1 lines of buffer in order
862 to shift up ch_offset pixels. */
863 pself->ch_size = pself->ch_line_size * (pself->ch_offset + 1);
864 pself->ch_buf = (SANE_Byte *) malloc(pself->ch_size);
865 if (pself->ch_buf == NULL)
866 {
867 DBG (DL_MAJOR_ERROR,
868 "%s: couldn't allocate channel buffer.\n",
869 __func__);
870 status = SANE_STATUS_NO_MEM;
871 }
872 else
873 {
874 pself->ch_ndata = 0;
875 pself->ch_pos = 0;
876 pself->ch_past_init = SANE_FALSE;
877 if ((actual_mode(pss) == MD_GREYSCALE) || (actual_mode(pss) == MD_LINEART))
878 pself->ch_bytes_per_pixel = 1;
879 else
880 pself->ch_bytes_per_pixel = 3;
881 if (pss->bpp_scan == 16)
882 pself->ch_bytes_per_pixel *= 2;
883 }
884 pself->ch_lineart = (actual_mode(pss) == MD_LINEART);
885 }
886 return status;
887 }
888
create_Deinterlacer(SnapScan_Scanner * pss,Source * psub,Source ** pps)889 static SANE_Status create_Deinterlacer (SnapScan_Scanner *pss,
890 Source *psub,
891 Source **pps)
892 {
893 SANE_Status status = SANE_STATUS_GOOD;
894 *pps = (Source *) malloc(sizeof(Deinterlacer));
895 if (*pps == NULL)
896 {
897 DBG (DL_MAJOR_ERROR,
898 "%s: failed to allocate Deinterlacer.\n",
899 __func__);
900 status = SANE_STATUS_NO_MEM;
901 }
902 else
903 {
904 status = Deinterlacer_init ((Deinterlacer *) *pps, pss, psub);
905 }
906 return status;
907 }
908
909 /* ----------------------------------------------------- */
910
911 /* the RGB router assumes 8-bit RGB data arranged in contiguous
912 channels, possibly with R-G and R-B offsets, and rearranges the
913 data into SANE RGB frame format */
914
915 typedef struct
916 {
917 TX_SOURCE_GUTS;
918 SANE_Byte *cbuf; /* circular line buffer */
919 SANE_Byte *xbuf; /* single line buffer */
920 SANE_Int pos; /* current position in xbuf */
921 SANE_Int cb_size; /* size of the circular buffer */
922 SANE_Int cb_line_size;/* size of a line in the circular buffer */
923 SANE_Int cb_start; /* start of valid data in the circular buffer */
924 SANE_Int cb_finish; /* finish of valid data, for next read */
925 SANE_Int ch_offset[3];/* offset in cbuf */
926 SANE_Int round_req;
927 SANE_Int round_read;
928 } RGBRouter;
929
put_int16r(int n,u_char * p)930 static void put_int16r (int n, u_char *p)
931 {
932 p[0] = (n & 0x00ff);
933 p[1] = (n & 0xff00) >> 8;
934 }
935
936
RGBRouter_remaining(Source * pself)937 static SANE_Int RGBRouter_remaining (Source *pself)
938 {
939 RGBRouter *ps = (RGBRouter *) pself;
940 SANE_Int remaining;
941 if (ps->round_req == ps->cb_size)
942 remaining = TxSource_remaining(pself) - ps->cb_size + ps->cb_line_size;
943 else
944 remaining = TxSource_remaining(pself) + ps->cb_line_size - ps->pos;
945 return (remaining);
946 }
947
RGBRouter_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)948 static SANE_Status RGBRouter_get (Source *pself,
949 SANE_Byte *pbuf,
950 SANE_Int *plen)
951 {
952 RGBRouter *ps = (RGBRouter *) pself;
953 SANE_Status status = SANE_STATUS_GOOD;
954 SANE_Int remaining = *plen;
955 SANE_Byte *s;
956 SANE_Int i, t;
957 SANE_Int r, g, b;
958 SANE_Int run_req;
959 SANE_Int org_len = *plen;
960 char *me = "RGBRouter_get";
961
962 while (remaining > 0 && pself->remaining(pself) > 0 && !cancelRead)
963 {
964 DBG(DL_DATA_TRACE, "%s: remaining=%d, pself->remaining=%d, round_req=%d, cb_size=%d\n",
965 me, remaining, pself->remaining(pself), ps->round_req, ps->cb_size);
966 /* Check if there is no valid data left from previous get */
967 if (ps->pos >= ps->cb_line_size)
968 {
969 /* Try to get more data. either one line or
970 full buffer (first time) */
971 do
972 {
973 run_req = ps->round_req - ps->round_read;
974 status = TxSource_get (pself,
975 ps->cbuf + ps->cb_start + ps->round_read,
976 &run_req);
977 if (status != SANE_STATUS_GOOD || run_req==0)
978 {
979 *plen -= remaining;
980 if ( *plen > 0 )
981 DBG(DL_DATA_TRACE, "%s: request=%d, read=%d\n",
982 me, org_len, *plen);
983 return status;
984 }
985 ps->round_read += run_req;
986 }
987 while ((ps->round_req > ps->round_read) && !cancelRead);
988
989 /* route RGB */
990 ps->cb_start = (ps->cb_start + ps->round_read)%ps->cb_size;
991 s = ps->xbuf;
992 r = (ps->cb_start + ps->ch_offset[0])%ps->cb_size;
993 g = (ps->cb_start + ps->ch_offset[1])%ps->cb_size;
994 b = (ps->cb_start + ps->ch_offset[2])%ps->cb_size;
995 for (i = 0; i < ps->cb_line_size/3; i++)
996 {
997 if (pself->pss->bpp_scan == 8)
998 {
999 *s++ = ps->cbuf[r++];
1000 *s++ = ps->cbuf[g++];
1001 *s++ = ps->cbuf[b++];
1002 }
1003 else if (pself->pss->pdev->model == SCANWIT2720S)
1004 {
1005 t = (((ps->cbuf[r+1] << 8) | ps->cbuf[r]) & 0xfff) << 4;
1006 put_int16r (t, s);
1007 s += 2;
1008 r += 2;
1009 t = (((ps->cbuf[g+1] << 8) | ps->cbuf[g]) & 0xfff) << 4;
1010 put_int16r (t, s);
1011 s += 2;
1012 g += 2;
1013 t = (((ps->cbuf[b+1] << 8) | ps->cbuf[b]) & 0xfff) << 4;
1014 put_int16r (t, s);
1015 s += 2;
1016 b += 2;
1017 i++;
1018 }
1019 else
1020 {
1021 *s++ = ps->cbuf[r++];
1022 *s++ = ps->cbuf[r++];
1023 *s++ = ps->cbuf[g++];
1024 *s++ = ps->cbuf[g++];
1025 *s++ = ps->cbuf[b++];
1026 *s++ = ps->cbuf[b++];
1027 i++;
1028 }
1029 }
1030
1031 /* end of reading & offsetiing whole line data;
1032 reset valid position */
1033 ps->pos = 0;
1034
1035 /* prepare for next round */
1036 ps->round_req = ps->cb_line_size;
1037 ps->round_read =0;
1038 }
1039
1040 /* Repack the whole scan line and copy to caller's buffer */
1041 while (remaining > 0 && ps->pos < ps->cb_line_size)
1042 {
1043 *pbuf++ = ps->xbuf[ps->pos++];
1044 remaining--;
1045 }
1046 }
1047 *plen -= remaining;
1048 DBG(DL_DATA_TRACE,
1049 "%s: Request=%d, remaining=%d, read=%d, TXSource_rem=%d, bytes_rem=%lu\n",
1050 me,
1051 org_len,
1052 pself->remaining(pself),
1053 *plen,
1054 TxSource_remaining(pself),
1055 (u_long) ps->pss->bytes_remaining);
1056 return status;
1057 }
1058
RGBRouter_done(Source * pself)1059 static SANE_Status RGBRouter_done (Source *pself)
1060 {
1061 RGBRouter *ps = (RGBRouter *) pself;
1062 SANE_Status status = TxSource_done(pself);
1063
1064 free(ps->cbuf);
1065 free(ps->xbuf);
1066 ps->cbuf = NULL;
1067 ps->cb_start = -1;
1068 ps->pos = 0;
1069 return status;
1070 }
1071
RGBRouter_init(RGBRouter * pself,SnapScan_Scanner * pss,Source * psub)1072 static SANE_Status RGBRouter_init (RGBRouter *pself,
1073 SnapScan_Scanner *pss,
1074 Source *psub)
1075 {
1076 SANE_Status status = TxSource_init((TxSource *) pself,
1077 pss,
1078 RGBRouter_remaining,
1079 TxSource_bytesPerLine,
1080 TxSource_pixelsPerLine,
1081 RGBRouter_get,
1082 RGBRouter_done,
1083 psub);
1084 if (status == SANE_STATUS_GOOD)
1085 {
1086 SANE_Int lines_in_buffer = 0;
1087
1088 /* Size the buffer to accommodate the necessary number of scan
1089 lines to cater for the offset between R, G and B */
1090 lines_in_buffer = pss->chroma + 1;
1091 pself->cb_line_size = pself->bytesPerLine((Source *) pself);
1092 pself->cb_size = pself->cb_line_size*lines_in_buffer;
1093 pself->pos = pself->cb_line_size;
1094
1095 pself->round_req = pself->cb_size;
1096 pself->round_read = 0;
1097
1098 pself->cbuf = (SANE_Byte *) malloc(pself->cb_size);
1099 pself->xbuf = (SANE_Byte *) malloc(pself->cb_line_size);
1100 if (pself->cbuf == NULL || pself->xbuf == NULL)
1101 {
1102 DBG (DL_MAJOR_ERROR,
1103 "%s: failed to allocate circular buffer.\n",
1104 __func__);
1105 status = SANE_STATUS_NO_MEM;
1106 }
1107 else
1108 {
1109 SANE_Int ch;
1110
1111 pself->cb_start = 0;
1112 for (ch = 0; ch < 3; ch++)
1113 {
1114 pself->ch_offset[ch] =
1115 pss->chroma_offset[ch] * pself->cb_line_size
1116 + ch * (pself->cb_line_size / 3);
1117 }
1118 }
1119 DBG(DL_MINOR_INFO, "RGBRouter_init: buf_size: %d x %d = %d\n",
1120 pself->cb_line_size, lines_in_buffer, pself->cb_size);
1121 DBG(DL_MINOR_INFO, "RGBRouter_init: buf offset R:%d G:%d B:%d\n",
1122 pself->ch_offset[0], pself->ch_offset[1],pself->ch_offset[2]);
1123 }
1124 return status;
1125 }
1126
create_RGBRouter(SnapScan_Scanner * pss,Source * psub,Source ** pps)1127 static SANE_Status create_RGBRouter (SnapScan_Scanner *pss,
1128 Source *psub,
1129 Source **pps)
1130 {
1131 static char me[] = "create_RGBRouter";
1132 SANE_Status status = SANE_STATUS_GOOD;
1133
1134 DBG (DL_CALL_TRACE, "%s\n", me);
1135 *pps = (Source *) malloc(sizeof(RGBRouter));
1136 if (*pps == NULL)
1137 {
1138 DBG (DL_MAJOR_ERROR, "%s: failed to allocate RGBRouter.\n",
1139 __func__);
1140 status = SANE_STATUS_NO_MEM;
1141 }
1142 else
1143 {
1144 status = RGBRouter_init ((RGBRouter *) *pps, pss, psub);
1145 }
1146 return status;
1147 }
1148
1149 /* An Inverter is used to invert the bits in a lineart image */
1150
1151 typedef struct
1152 {
1153 TX_SOURCE_GUTS;
1154 } Inverter;
1155
Inverter_get(Source * pself,SANE_Byte * pbuf,SANE_Int * plen)1156 static SANE_Status Inverter_get (Source *pself, SANE_Byte *pbuf, SANE_Int *plen)
1157 {
1158 SANE_Status status = TxSource_get (pself, pbuf, plen);
1159 if (status == SANE_STATUS_GOOD)
1160 {
1161 int i;
1162 for (i = 0; i < *plen; i++)
1163 pbuf[i] ^= 0xFF;
1164 }
1165 return status;
1166 }
1167
Inverter_init(Inverter * pself,SnapScan_Scanner * pss,Source * psub)1168 static SANE_Status Inverter_init (Inverter *pself,
1169 SnapScan_Scanner *pss,
1170 Source *psub)
1171 {
1172 return TxSource_init ((TxSource *) pself,
1173 pss,
1174 TxSource_remaining,
1175 TxSource_bytesPerLine,
1176 TxSource_pixelsPerLine,
1177 Inverter_get,
1178 TxSource_done,
1179 psub);
1180 }
1181
create_Inverter(SnapScan_Scanner * pss,Source * psub,Source ** pps)1182 static SANE_Status create_Inverter (SnapScan_Scanner *pss,
1183 Source *psub,
1184 Source **pps)
1185 {
1186 SANE_Status status = SANE_STATUS_GOOD;
1187 *pps = (Source *) malloc(sizeof(Inverter));
1188 if (*pps == NULL)
1189 {
1190 DBG (DL_MAJOR_ERROR, "%s: failed to allocate Inverter.\n",
1191 __func__);
1192 status = SANE_STATUS_NO_MEM;
1193 }
1194 else
1195 {
1196 status = Inverter_init ((Inverter *) *pps, pss, psub);
1197 }
1198 return status;
1199 }
1200
1201 /* Source chain creation */
1202
create_source_chain(SnapScan_Scanner * pss,BaseSourceType bst,Source ** pps)1203 static SANE_Status create_source_chain (SnapScan_Scanner *pss,
1204 BaseSourceType bst,
1205 Source **pps)
1206 {
1207 static char me[] = "create_source_chain";
1208 SANE_Status status = create_base_source (pss, bst, pps);
1209
1210 DBG (DL_CALL_TRACE, "%s\n", me);
1211 if (status == SANE_STATUS_GOOD)
1212 {
1213 SnapScan_Mode mode = actual_mode(pss);
1214 switch (mode)
1215 {
1216 case MD_COLOUR:
1217 status = create_RGBRouter (pss, *pps, pps);
1218 /* We only have the interlace problems on
1219 some scanners like the Epson Perfection 2480/2580
1220 at 2400 dpi. */
1221 if (status == SANE_STATUS_GOOD &&
1222 ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) ||
1223 (pss->pdev->model == PERFECTION3490 && pss->res == 3200) ||
1224 (pss->pdev->model == PRISA5000E && pss->res == 1200)))
1225 status = create_Deinterlacer (pss, *pps, pps);
1226 break;
1227 case MD_BILEVELCOLOUR:
1228 status = create_Expander (pss, *pps, pps);
1229 if (status == SANE_STATUS_GOOD)
1230 status = create_RGBRouter (pss, *pps, pps);
1231 if (status == SANE_STATUS_GOOD &&
1232 ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) ||
1233 (pss->pdev->model == PERFECTION3490 && pss->res == 3200) ||
1234 (pss->pdev->model == PRISA5000E && pss->res == 1200)))
1235 status = create_Deinterlacer (pss, *pps, pps);
1236 break;
1237 case MD_GREYSCALE:
1238 if ((pss->pdev->model == PERFECTION2480 && pss->res == 2400) ||
1239 (pss->pdev->model == PERFECTION3490 && pss->res == 3200) ||
1240 (pss->pdev->model == PRISA5000E && pss->res == 1200))
1241 status = create_Deinterlacer (pss, *pps, pps);
1242 break;
1243 case MD_LINEART:
1244 /* The SnapScan creates a negative image by
1245 default... so for the user interface to make sense,
1246 the internal meaning of "negative" is reversed */
1247 if (pss->negative == SANE_FALSE)
1248 status = create_Inverter (pss, *pps, pps);
1249 if (pss->pdev->model == PERFECTION3490 && pss->res == 3200)
1250 status = create_Deinterlacer (pss, *pps, pps);
1251 break;
1252 default:
1253 DBG (DL_MAJOR_ERROR, "%s: bad mode value %d (internal error)\n",
1254 __func__, mode);
1255 status = SANE_STATUS_INVAL;
1256 break;
1257 }
1258 }
1259 return status;
1260 }
1261
1262 /*
1263 * Revision 1.21 2005/12/02 19:12:54 oliver-guest
1264 * Another fix for lineart mode for the Epson 3490 @ 3200 DPI
1265 *
1266 * Revision 1.20 2005/11/28 19:28:29 oliver-guest
1267 * Fix for lineart mode of Epson 3490 @ 3200 DPI
1268 *
1269 * Revision 1.19 2005/11/25 17:24:48 oliver-guest
1270 * Fix for Epson 3490 @ 3200 DPI for grayscale and lineart mode
1271 *
1272 * Revision 1.18 2005/11/17 23:47:11 oliver-guest
1273 * Revert previous 'fix', disable 2400 dpi for Epson 3490, use 1600 dpi instead
1274 *
1275 * Revision 1.17 2005/11/17 23:32:23 oliver-guest
1276 * Fixes for Epson 3490 @ 2400 DPI
1277 *
1278 * Revision 1.16 2005/11/10 19:42:02 oliver-guest
1279 * Added deinterlacing for Epson 3490
1280 *
1281 * Revision 1.15 2005/10/31 21:08:47 oliver-guest
1282 * Distinguish between Benq 5000/5000E/5000U
1283 *
1284 * Revision 1.14 2005/10/13 22:43:30 oliver-guest
1285 * Fixes for 16 bit scan mode from Simon Munton
1286 *
1287 * Revision 1.13 2005/10/11 18:47:07 oliver-guest
1288 * Fixes for Epson 3490 and 16 bit scan mode
1289 *
1290 * Revision 1.12 2004/11/14 19:26:38 oliver-guest
1291 * Applied patch from Julien Blache to change ch_past_init from SANE_Int to SANE_Bool
1292 *
1293 * Revision 1.11 2004/11/09 23:17:38 oliver-guest
1294 * First implementation of deinterlacer for Epson scanners at high resolutions (thanks to Brad Johnson)
1295 *
1296 * Revision 1.10 2004/10/03 17:34:36 hmg-guest
1297 * 64 bit platform fixes (bug #300799).
1298 *
1299 * Revision 1.9 2004/04/09 16:18:37 oliver-guest
1300 * Fix initialization of FDSource.bytes_remaining
1301 *
1302 * Revision 1.8 2004/04/09 11:59:02 oliver-guest
1303 * Fixes for pthread implementation
1304 *
1305 * Revision 1.7 2004/04/08 21:53:10 oliver-guest
1306 * Use sanei_thread in snapscan backend
1307 *
1308 * Revision 1.6 2001/12/17 22:51:49 oliverschwartz
1309 * Update to snapscan-20011212 (snapscan 1.4.3)
1310 *
1311 * Revision 1.18 2001/12/12 19:44:59 oliverschwartz
1312 * Clean up CVS log
1313 *
1314 * Revision 1.17 2001/11/27 23:16:17 oliverschwartz
1315 * - Fix color alignment for SnapScan 600
1316 * - Added documentation in snapscan-sources.c
1317 * - Guard against TL_X < BR_X and TL_Y < BR_Y
1318 *
1319 * Revision 1.16 2001/10/08 18:22:02 oliverschwartz
1320 * - Disable quality calibration for Acer Vuego 310F
1321 * - Use sanei_scsi_max_request_size as scanner buffer size
1322 * for SCSI devices
1323 * - Added new devices to snapscan.desc
1324 *
1325 * Revision 1.15 2001/09/28 15:56:51 oliverschwartz
1326 * - fix hanging for SNAPSCAN300 / VUEGO 310
1327 *
1328 * Revision 1.14 2001/09/28 13:39:16 oliverschwartz
1329 * - Added "Snapscan 300" ID string
1330 * - cleanup
1331 * - more debugging messages in snapscan-sources.c
1332 *
1333 * Revision 1.13 2001/09/18 15:01:07 oliverschwartz
1334 * - Read scanner id string again after firmware upload
1335 * to identify correct model
1336 * - Make firmware upload work for AGFA scanners
1337 * - Change copyright notice
1338 *
1339 * Revision 1.12 2001/09/09 18:06:32 oliverschwartz
1340 * add changes from Acer (new models; automatic firmware upload for USB scanners); fix distorted colour scans after greyscale scans (call set_window only in sane_start); code cleanup
1341 *
1342 * Revision 1.11 2001/04/13 13:12:18 oliverschwartz
1343 * use absolute_max as expected_read_bytes for PRISA620S
1344 *
1345 * Revision 1.10 2001/04/10 11:04:31 sable
1346 * Adding support for snapscan e40 an e50 thanks to Giuseppe Tanzilli
1347 *
1348 * Revision 1.9 2001/03/17 22:53:21 sable
1349 * Applying Mikael Magnusson patch concerning Gamma correction
1350 * Support for 1212U_2
1351 *
1352 * Revision 1.8 2000/11/28 03:55:07 cbagwell
1353 * Reverting a fix to RGBRouter_remaining to original fix. This allows
1354 * most scanners to scan at 600 dpi by ignoring insufficient data in
1355 * the RGB circular buffer and always returning size = 1 in those cases.
1356 * This should probably be fixed at a higher level.
1357 *
1358 * Revision 1.7 2000/11/20 01:02:42 cbagwell
1359 * Updates so that USB will continue reading when it receives an EAGAIN error.
1360 * Also, changed RGBRouter_remaining to not be able to return a negative
1361 * value.
1362 *
1363 * Revision 1.6 2000/11/04 01:53:58 cbagwell
1364 * Committing some needed USB updates. Added extra test logic to detect
1365 * bad bytes_expected values. Just to help debug faster on scanners
1366 * that tickle the bug.
1367 *
1368 * Revision 1.5 2000/10/30 22:32:20 sable
1369 * Support for vuego310s vuego610s and 1236s
1370 *
1371 * Revision 1.4 2000/10/28 14:16:10 sable
1372 * Bug correction for SnapScan310
1373 *
1374 * Revision 1.3 2000/10/28 14:06:35 sable
1375 * Add support for Acer300f
1376 *
1377 * Revision 1.2 2000/10/13 03:50:27 cbagwell
1378 * Updating to source from SANE 1.0.3. Calling this version 1.1
1379 * */
1380