summaryrefslogtreecommitdiff
path: root/backend/gt68xx_mid.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/gt68xx_mid.c')
-rw-r--r--backend/gt68xx_mid.c1185
1 files changed, 1185 insertions, 0 deletions
diff --git a/backend/gt68xx_mid.c b/backend/gt68xx_mid.c
new file mode 100644
index 0000000..1301139
--- /dev/null
+++ b/backend/gt68xx_mid.c
@@ -0,0 +1,1185 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2002 Sergey Vlasov <vsu@altlinux.ru>
+ Copyright (C) 2002-2007 Henning Geinitz <sane@geinitz.org>
+
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice.
+*/
+
+#include "gt68xx_mid.h"
+#include "gt68xx_low.c"
+
+/** @file
+ * @brief Image data unpacking.
+ */
+
+static SANE_Status
+gt68xx_delay_buffer_init (GT68xx_Delay_Buffer * delay,
+ SANE_Int pixels_per_line, SANE_Int delay_count)
+{
+ SANE_Int bytes_per_line;
+ SANE_Int line_count, i;
+
+ if (pixels_per_line <= 0)
+ {
+ DBG (3, "gt68xx_delay_buffer_init: BUG: pixels_per_line=%d\n",
+ pixels_per_line);
+ return SANE_STATUS_INVAL;
+ }
+
+ if (delay_count < 0)
+ {
+ DBG (3, "gt68xx_delay_buffer_init: BUG: delay_count=%d\n", delay_count);
+ return SANE_STATUS_INVAL;
+ }
+
+ bytes_per_line = pixels_per_line * sizeof (unsigned int);
+
+ delay->line_count = line_count = delay_count + 1;
+ delay->read_index = 0;
+ delay->write_index = delay_count;
+
+ delay->mem_block = (SANE_Byte *) malloc (bytes_per_line * line_count);
+ if (!delay->mem_block)
+ {
+ DBG (3, "gt68xx_delay_buffer_init: no memory for delay block\n");
+ return SANE_STATUS_NO_MEM;
+ }
+ /* make sure that we will see if one of the unitialized lines get displayed */
+ for (i = 0; i < bytes_per_line * line_count; i++)
+ delay->mem_block[i] = i % 256;
+
+ delay->lines =
+ (unsigned int **) malloc (sizeof (unsigned int *) * line_count);
+ if (!delay->lines)
+ {
+ free (delay->mem_block);
+ DBG (3,
+ "gt68xx_delay_buffer_init: no memory for delay line pointers\n");
+ return SANE_STATUS_NO_MEM;
+ }
+
+ for (i = 0; i < line_count; ++i)
+ delay->lines[i] =
+ (unsigned int *) (delay->mem_block + i * bytes_per_line);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+gt68xx_delay_buffer_done (GT68xx_Delay_Buffer * delay)
+{
+ if (delay->lines)
+ {
+ free (delay->lines);
+ delay->lines = NULL;
+ }
+
+ if (delay->mem_block)
+ {
+ free (delay->mem_block);
+ delay->mem_block = NULL;
+ }
+
+ return SANE_STATUS_GOOD;
+}
+
+#define DELAY_BUFFER_WRITE_PTR(delay) ( (delay)->lines[(delay)->write_index] )
+
+#define DELAY_BUFFER_SELECT_PTR(delay,dist) \
+ ((delay)->lines[((delay)->read_index + (dist)) % (delay)->line_count])
+
+#define DELAY_BUFFER_READ_PTR(delay) ( (delay)->lines[(delay)->read_index ] )
+
+#define DELAY_BUFFER_STEP(delay) \
+ do \
+ { \
+ (delay)->read_index = ((delay)->read_index + 1) % (delay)->line_count; \
+ (delay)->write_index = ((delay)->write_index + 1) % (delay)->line_count; \
+ } \
+ while (SANE_FALSE)
+
+
+static inline void
+unpack_8_mono (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line)
+{
+ for (; pixels_per_line > 0; ++src, ++dst, --pixels_per_line)
+ {
+ *dst = (((unsigned int) *src) << 8) | *src;
+ }
+}
+
+static inline void
+unpack_8_rgb (SANE_Byte * src, unsigned int *dst, SANE_Int pixels_per_line)
+{
+ for (; pixels_per_line > 0; src += 3, ++dst, --pixels_per_line)
+ {
+ *dst = (((unsigned int) *src) << 8) | *src;
+ }
+}
+
+/* 12-bit routines use the fact that pixels_per_line is aligned */
+
+static inline void
+unpack_12_le_mono (SANE_Byte * src, unsigned int *dst,
+ SANE_Int pixels_per_line)
+{
+ for (; pixels_per_line > 0; src += 3, dst += 2, pixels_per_line -= 2)
+ {
+ dst[0] = ((((unsigned int) (src[1] & 0x0f)) << 12)
+ | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f));
+ dst[1] = ((((unsigned int) src[2]) << 8)
+ | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04));
+ }
+}
+
+static inline void
+unpack_12_le_rgb (SANE_Byte * src,
+ unsigned int *dst1,
+ unsigned int *dst2,
+ unsigned int *dst3, SANE_Int pixels_per_line)
+{
+ for (; pixels_per_line > 0; pixels_per_line -= 2)
+ {
+ *dst1++ = ((((unsigned int) (src[1] & 0x0f)) << 12)
+ | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f));
+ *dst2++ = ((((unsigned int) src[2]) << 8)
+ | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04));
+ src += 3;
+
+ *dst3++ = ((((unsigned int) (src[1] & 0x0f)) << 12)
+ | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f));
+ *dst1++ = ((((unsigned int) src[2]) << 8)
+ | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04));
+ src += 3;
+
+ *dst2++ = ((((unsigned int) (src[1] & 0x0f)) << 12)
+ | (((unsigned int) src[0]) << 4) | (src[1] & 0x0f));
+ *dst3++ = ((((unsigned int) src[2]) << 8)
+ | (src[1] & 0xf0) | (((unsigned int) src[2]) >> 0x04));
+ src += 3;
+ }
+}
+
+static inline void
+unpack_16_le_mono (SANE_Byte * src, unsigned int *dst,
+ SANE_Int pixels_per_line)
+{
+ for (; pixels_per_line > 0; src += 2, dst++, --pixels_per_line)
+ {
+ *dst = (((unsigned int) src[1]) << 8) | src[0];
+ }
+}
+
+static inline void
+unpack_16_le_rgb (SANE_Byte * src, unsigned int *dst,
+ SANE_Int pixels_per_line)
+{
+ for (; pixels_per_line > 0; src += 6, ++dst, --pixels_per_line)
+ {
+ *dst = (((unsigned int) src[1]) << 8) | src[0];
+ }
+}
+
+
+static SANE_Status
+line_read_gray_8 (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ unsigned int *buffer;
+
+ size = reader->params.scan_bpl;
+
+ RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size));
+
+ buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[0] = buffer;
+ unpack_8_mono (reader->pixel_buffer, buffer, reader->pixels_per_line);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_gray_double_8 (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ unsigned int *buffer;
+ int i;
+
+ size = reader->params.scan_bpl;
+
+ RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size));
+ unpack_8_mono (reader->pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ reader->pixels_per_line);
+
+ buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+
+ for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2)
+ buffer[i] = DELAY_BUFFER_WRITE_PTR (&reader->g_delay)[i];
+
+ buffer_pointers_return[0] = buffer;
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_gray_12 (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ unsigned int *buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size));
+
+ buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[0] = buffer;
+ unpack_12_le_mono (reader->pixel_buffer, buffer, reader->pixels_per_line);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_gray_double_12 (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ unsigned int *buffer;
+ int i;
+
+ size = reader->params.scan_bpl;
+
+ RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size));
+ unpack_12_le_mono (reader->pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ reader->pixels_per_line);
+
+ buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+
+ for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2)
+ buffer[i] = DELAY_BUFFER_WRITE_PTR (&reader->g_delay)[i];
+
+ buffer_pointers_return[0] = buffer;
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_gray_16 (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ unsigned int *buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size));
+
+ buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[0] = buffer;
+ unpack_16_le_mono (reader->pixel_buffer, buffer, reader->pixels_per_line);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_gray_double_16 (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ unsigned int *buffer;
+ int i;
+
+ size = reader->params.scan_bpl;
+
+ RIE (gt68xx_device_read (reader->dev, reader->pixel_buffer, &size));
+ unpack_16_le_mono (reader->pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ reader->pixels_per_line);
+
+ buffer = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+
+ for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2)
+ buffer[i] = DELAY_BUFFER_WRITE_PTR (&reader->g_delay)[i];
+
+ buffer_pointers_return[0] = buffer;
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ return SANE_STATUS_GOOD;
+
+}
+
+static SANE_Status
+line_read_rgb_8_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl * 3;
+
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_double_8_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+ int i;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2)
+ {
+ DELAY_BUFFER_READ_PTR (&reader->r_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->r_delay,
+ reader->params.ld_shift_double)[i];
+ DELAY_BUFFER_READ_PTR (&reader->g_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->g_delay,
+ reader->params.ld_shift_double)[i];
+ DELAY_BUFFER_READ_PTR (&reader->b_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->b_delay,
+ reader->params.ld_shift_double)[i];
+ }
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_bgr_8_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_8_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_12_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_double_12_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+ int i;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2)
+ {
+ DELAY_BUFFER_READ_PTR (&reader->r_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->r_delay,
+ reader->params.ld_shift_double)[i];
+ DELAY_BUFFER_READ_PTR (&reader->g_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->g_delay,
+ reader->params.ld_shift_double)[i];
+ DELAY_BUFFER_READ_PTR (&reader->b_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->b_delay,
+ reader->params.ld_shift_double)[i];
+ }
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_16_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_double_16_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+ int i;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ for (i = reader->params.double_column; i < reader->pixels_per_line; i += 2)
+ {
+ DELAY_BUFFER_READ_PTR (&reader->r_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->r_delay,
+ reader->params.ld_shift_double)[i];
+ DELAY_BUFFER_READ_PTR (&reader->g_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->g_delay,
+ reader->params.ld_shift_double)[i];
+ DELAY_BUFFER_READ_PTR (&reader->b_delay)[i] =
+ DELAY_BUFFER_SELECT_PTR (&reader->b_delay,
+ reader->params.ld_shift_double)[i];
+ }
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_bgr_12_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_12_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_bgr_16_line_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl * 3;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += reader->params.scan_bpl;
+ unpack_16_le_mono (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_8_pixel_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_8_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line);
+ ++pixel_buffer;
+ unpack_8_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line);
+ ++pixel_buffer;
+ unpack_8_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+
+static SANE_Status
+line_read_rgb_12_pixel_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ unpack_12_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ reader->pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_rgb_16_pixel_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_16_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+ pixel_buffer += 2;
+ unpack_16_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += 2;
+ unpack_16_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_bgr_8_pixel_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_8_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay), pixels_per_line);
+ ++pixel_buffer;
+ unpack_8_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay), pixels_per_line);
+ ++pixel_buffer;
+ unpack_8_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay), pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+
+static SANE_Status
+line_read_bgr_12_pixel_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ unpack_12_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ reader->pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+line_read_bgr_16_pixel_mode (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+ size_t size;
+ SANE_Int pixels_per_line;
+ SANE_Byte *pixel_buffer = reader->pixel_buffer;
+
+ size = reader->params.scan_bpl;
+ RIE (gt68xx_device_read (reader->dev, pixel_buffer, &size));
+
+ pixels_per_line = reader->pixels_per_line;
+ unpack_16_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->b_delay),
+ pixels_per_line);
+ pixel_buffer += 2;
+ unpack_16_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->g_delay),
+ pixels_per_line);
+ pixel_buffer += 2;
+ unpack_16_le_rgb (pixel_buffer,
+ DELAY_BUFFER_WRITE_PTR (&reader->r_delay),
+ pixels_per_line);
+
+ buffer_pointers_return[0] = DELAY_BUFFER_READ_PTR (&reader->r_delay);
+ buffer_pointers_return[1] = DELAY_BUFFER_READ_PTR (&reader->g_delay);
+ buffer_pointers_return[2] = DELAY_BUFFER_READ_PTR (&reader->b_delay);
+
+ DELAY_BUFFER_STEP (&reader->r_delay);
+ DELAY_BUFFER_STEP (&reader->g_delay);
+ DELAY_BUFFER_STEP (&reader->b_delay);
+
+ return SANE_STATUS_GOOD;
+}
+
+static SANE_Status
+gt68xx_line_reader_init_delays (GT68xx_Line_Reader * reader)
+{
+ SANE_Status status;
+
+ if (reader->params.color)
+ {
+ status = gt68xx_delay_buffer_init (&reader->r_delay,
+ reader->params.scan_xs,
+ reader->params.ld_shift_r +
+ reader->params.ld_shift_double);
+ if (status != SANE_STATUS_GOOD)
+ return status;
+
+ status = gt68xx_delay_buffer_init (&reader->g_delay,
+ reader->params.scan_xs,
+ reader->params.ld_shift_g +
+ reader->params.ld_shift_double);
+ if (status != SANE_STATUS_GOOD)
+ {
+ gt68xx_delay_buffer_done (&reader->r_delay);
+ return status;
+ }
+
+ status = gt68xx_delay_buffer_init (&reader->b_delay,
+ reader->params.scan_xs,
+ reader->params.ld_shift_b +
+ reader->params.ld_shift_double);
+ if (status != SANE_STATUS_GOOD)
+ {
+ gt68xx_delay_buffer_done (&reader->g_delay);
+ gt68xx_delay_buffer_done (&reader->r_delay);
+ return status;
+ }
+ }
+ else
+ {
+ status = gt68xx_delay_buffer_init (&reader->g_delay,
+ reader->params.scan_xs,
+ reader->params.ld_shift_double);
+ if (status != SANE_STATUS_GOOD)
+ return status;
+ }
+ reader->delays_initialized = SANE_TRUE;
+
+ return SANE_STATUS_GOOD;
+}
+
+static void
+gt68xx_line_reader_free_delays (GT68xx_Line_Reader * reader)
+{
+ if (reader->delays_initialized)
+ {
+ if (reader->params.color)
+ {
+ gt68xx_delay_buffer_done (&reader->b_delay);
+ gt68xx_delay_buffer_done (&reader->g_delay);
+ gt68xx_delay_buffer_done (&reader->r_delay);
+ }
+ else
+ {
+ gt68xx_delay_buffer_done (&reader->g_delay);
+ }
+ reader->delays_initialized = SANE_FALSE;
+ }
+}
+
+SANE_Status
+gt68xx_line_reader_new (GT68xx_Device * dev,
+ GT68xx_Scan_Parameters * params,
+ SANE_Bool final_scan,
+ GT68xx_Line_Reader ** reader_return)
+{
+ SANE_Status status;
+ GT68xx_Line_Reader *reader;
+ SANE_Int image_size;
+ SANE_Int scan_bpl_full;
+
+ DBG (6, "gt68xx_line_reader_new: enter\n");
+
+ *reader_return = NULL;
+
+ reader = (GT68xx_Line_Reader *) malloc (sizeof (GT68xx_Line_Reader));
+ if (!reader)
+ {
+ DBG (3, "gt68xx_line_reader_new: cannot allocate GT68xx_Line_Reader\n");
+ return SANE_STATUS_NO_MEM;
+ }
+ memset (reader, 0, sizeof (GT68xx_Line_Reader));
+
+ reader->dev = dev;
+ memcpy (&reader->params, params, sizeof (GT68xx_Scan_Parameters));
+ reader->pixel_buffer = 0;
+ reader->delays_initialized = SANE_FALSE;
+
+ reader->read = NULL;
+
+ status = gt68xx_line_reader_init_delays (reader);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (3, "gt68xx_line_reader_new: cannot allocate line buffers: %s\n",
+ sane_strstatus (status));
+ free (reader);
+ return status;
+ }
+
+ reader->pixels_per_line = reader->params.pixel_xs;
+
+ if (!reader->params.color)
+ {
+ if (reader->params.depth == 8)
+ {
+ if (reader->params.ld_shift_double > 0)
+ reader->read = line_read_gray_double_8;
+ else
+ reader->read = line_read_gray_8;
+ }
+ else if (reader->params.depth == 12)
+ {
+ if (reader->params.ld_shift_double > 0)
+ reader->read = line_read_gray_double_12;
+ else
+ reader->read = line_read_gray_12;
+ }
+ else if (reader->params.depth == 16)
+ {
+ if (reader->params.ld_shift_double > 0)
+ reader->read = line_read_gray_double_16;
+ else
+ reader->read = line_read_gray_16;
+ }
+ }
+ else if (reader->params.line_mode)
+ {
+ if (reader->params.depth == 8)
+ {
+ if (dev->model->line_mode_color_order == COLOR_ORDER_RGB)
+ {
+ if (reader->params.ld_shift_double > 0)
+ reader->read = line_read_rgb_double_8_line_mode;
+ else
+ reader->read = line_read_rgb_8_line_mode;
+ }
+ else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR)
+ reader->read = line_read_bgr_8_line_mode;
+ }
+ else if (reader->params.depth == 12)
+ {
+ if (dev->model->line_mode_color_order == COLOR_ORDER_RGB)
+ {
+ if (reader->params.ld_shift_double > 0)
+ reader->read = line_read_rgb_double_12_line_mode;
+ else
+ reader->read = line_read_rgb_12_line_mode;
+ }
+ else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR)
+ reader->read = line_read_bgr_12_line_mode;
+ }
+ else if (reader->params.depth == 16)
+ {
+ if (dev->model->line_mode_color_order == COLOR_ORDER_RGB)
+ {
+ if (reader->params.ld_shift_double > 0)
+ reader->read = line_read_rgb_double_16_line_mode;
+ else
+ reader->read = line_read_rgb_16_line_mode;
+ }
+ else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR)
+ reader->read = line_read_bgr_16_line_mode;
+ }
+ }
+ else
+ {
+ if (reader->params.depth == 8)
+ {
+ if (dev->model->line_mode_color_order == COLOR_ORDER_RGB)
+ reader->read = line_read_rgb_8_pixel_mode;
+ else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR)
+ reader->read = line_read_bgr_8_pixel_mode;
+ }
+ else if (reader->params.depth == 12)
+ {
+ if (dev->model->line_mode_color_order == COLOR_ORDER_RGB)
+ reader->read = line_read_rgb_12_pixel_mode;
+ else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR)
+ reader->read = line_read_bgr_12_pixel_mode;
+ }
+ else if (reader->params.depth == 16)
+ {
+ if (dev->model->line_mode_color_order == COLOR_ORDER_RGB)
+ reader->read = line_read_rgb_16_pixel_mode;
+ else if (dev->model->line_mode_color_order == COLOR_ORDER_BGR)
+ reader->read = line_read_bgr_16_pixel_mode;
+ }
+ }
+
+ if (reader->read == NULL)
+ {
+ DBG (3, "gt68xx_line_reader_new: unsupported bit depth (%d)\n",
+ reader->params.depth);
+ gt68xx_line_reader_free_delays (reader);
+ free (reader);
+ return SANE_STATUS_UNSUPPORTED;
+ }
+
+ scan_bpl_full = reader->params.scan_bpl;
+
+ if (reader->params.color && reader->params.line_mode)
+ scan_bpl_full *= 3;
+
+ reader->pixel_buffer = malloc (scan_bpl_full);
+ if (!reader->pixel_buffer)
+ {
+ DBG (3, "gt68xx_line_reader_new: cannot allocate pixel buffer\n");
+ gt68xx_line_reader_free_delays (reader);
+ free (reader);
+ return SANE_STATUS_NO_MEM;
+ }
+
+ gt68xx_device_set_read_buffer_size (reader->dev,
+ scan_bpl_full /* * 200 */ );
+
+ image_size = reader->params.scan_bpl * reader->params.scan_ys;
+ status = gt68xx_device_read_prepare (reader->dev, image_size, final_scan);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (3,
+ "gt68xx_line_reader_new: gt68xx_device_read_prepare failed: %s\n",
+ sane_strstatus (status));
+ free (reader->pixel_buffer);
+ gt68xx_line_reader_free_delays (reader);
+ free (reader);
+ return status;
+ }
+
+ DBG (6, "gt68xx_line_reader_new: leave: ok\n");
+ *reader_return = reader;
+ return SANE_STATUS_GOOD;
+}
+
+SANE_Status
+gt68xx_line_reader_free (GT68xx_Line_Reader * reader)
+{
+ SANE_Status status;
+
+ DBG (6, "gt68xx_line_reader_free: enter\n");
+
+ gt68xx_line_reader_free_delays (reader);
+
+ if (reader->pixel_buffer)
+ {
+ free (reader->pixel_buffer);
+ reader->pixel_buffer = NULL;
+ }
+
+ status = gt68xx_device_read_finish (reader->dev);
+ if (status != SANE_STATUS_GOOD)
+ {
+ DBG (3,
+ "gt68xx_line_reader_free: gt68xx_device_read_finish failed: %s\n",
+ sane_strstatus (status));
+ }
+
+ free (reader);
+
+ DBG (6, "gt68xx_line_reader_free: leave\n");
+ return status;
+}
+
+SANE_Status
+gt68xx_line_reader_read (GT68xx_Line_Reader * reader,
+ unsigned int **buffer_pointers_return)
+{
+ SANE_Status status;
+
+ status = (*reader->read) (reader, buffer_pointers_return);
+ return status;
+}
+
+/* vim: set sw=2 cino=>2se-1sn-1s{s^-1st0(0u0 smarttab expandtab: */