diff --git a/backend/lexmark-x1100.c b/backend/lexmark-x1100.c index d1359c82b..bd99d72ca 100644 --- a/backend/lexmark-x1100.c +++ b/backend/lexmark-x1100.c @@ -51,6 +51,7 @@ #include "../include/sane/sane.h" #include "../include/sane/sanei.h" +#include "../include/sane/saneopts.h" #include "../include/sane/sanei_usb.h" @@ -147,6 +148,9 @@ static SANE_Status read_buffer_add_byte (Read_Buffer *rb, SANE_Byte * byte_pointer); static SANE_Status read_buffer_add_byte_gray (Read_Buffer *rb, SANE_Byte * byte_pointer); +static SANE_Status read_buffer_add_bit_lineart (Read_Buffer *rb, + SANE_Byte * byte_pointer, + SANE_Byte threshold); static size_t read_buffer_get_bytes (Read_Buffer *rb, SANE_Byte * buffer, size_t rqst_size); static SANE_Bool read_buffer_is_empty (Read_Buffer *rb); @@ -1421,10 +1425,10 @@ sanei_lexmark_x1100_set_scan_regs (Lexmark_Device * dev, SANE_Int offset) int i; /* resolution */ - yres = dev->val[OPT_Y_DPI].w; + yres = dev->val[OPT_RESOLUTION].w; /* colour mode */ - if (strcmp (dev->val[OPT_MODE].s, "Color") == 0) + if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) isColourScan = SANE_TRUE; else isColourScan = SANE_FALSE; @@ -2329,7 +2333,7 @@ sanei_lexmark_x1100_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Dev { SANE_Int devnum; - SANE_Bool isColourScan; + SANE_Bool isColourScan, isGrayScan; /* SANE_Byte temp_byte; */ static SANE_Byte command1_block[] = { 0x91, 0x00, 0xff, 0xc0 }; size_t xfer_size, cmd_size, xfer_request, remainder; @@ -2340,10 +2344,16 @@ sanei_lexmark_x1100_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Dev DBG (2, "sanei_lexmark_x1100_read_scan_data:\n"); /* colour mode */ - if (strcmp (dev->val[OPT_MODE].s, "Color") == 0) + isGrayScan = SANE_FALSE; + if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) isColourScan = SANE_TRUE; else - isColourScan = SANE_FALSE; + { + isColourScan = SANE_FALSE; + /* grayscale mode */ + if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_GRAY) == 0) + isGrayScan = SANE_TRUE; + } devnum = dev->devnum; @@ -2393,7 +2403,7 @@ sanei_lexmark_x1100_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Dev } } - DBG (5, "\nREAD BUFFER INFO: \n"); + DBG (5, "READ BUFFER INFO: \n"); DBG (5, " write ptr: %p\n", dev->read_buffer->writeptr); DBG (5, " read ptr: %p\n", dev->read_buffer->readptr); DBG (5, " max write ptr: %p\n", dev->read_buffer->max_writeptr); @@ -2419,13 +2429,30 @@ sanei_lexmark_x1100_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Dev read_buffer_add_byte (dev->read_buffer, dev->read_pointer-1); even_byte = ! even_byte; } - /* Gray or Black&White Scan */ + /* Gray Scan */ + else if (isGrayScan) + { + if (even_byte) + read_buffer_add_byte_gray (dev->read_buffer, + dev->read_pointer+1); + else + read_buffer_add_byte_gray (dev->read_buffer, + dev->read_pointer-1); + even_byte = ! even_byte; + } + /* Lineart Scan */ else { - /* read_buffer_add_byte_gray(dev->read_pointer); */ - read_buffer_add_byte_gray (dev->read_buffer, dev->read_pointer); + if (even_byte) + read_buffer_add_bit_lineart (dev->read_buffer, + dev->read_pointer+1, + dev->threshold); + else + read_buffer_add_bit_lineart (dev->read_buffer, + dev->read_pointer-1, + dev->threshold); + even_byte = ! even_byte; } - dev->read_pointer = dev->read_pointer + sizeof (SANE_Byte); dev->bytes_in_buffer--; } @@ -2434,6 +2461,15 @@ sanei_lexmark_x1100_read_scan_data (SANE_Byte * data, SANE_Int size, Lexmark_Dev dev->transfer_buffer = NULL; } + DBG (5, "READ BUFFER INFO: \n"); + DBG (5, " write ptr: %p\n", dev->read_buffer->writeptr); + DBG (5, " read ptr: %p\n", dev->read_buffer->readptr); + DBG (5, " max write ptr: %p\n", dev->read_buffer->max_writeptr); + DBG (5, " buffer size: %lu\n", (u_long)dev->read_buffer->size); + DBG (5, " line size: %lu\n", (u_long)dev->read_buffer->linesize); + DBG (5, " empty: %d\n", dev->read_buffer->empty); + DBG (5, " line no: %d\n", dev->read_buffer->image_line_no); + /* Read blocks out of read buffer */ bytes_read = read_buffer_get_bytes (dev->read_buffer, data, size); @@ -2487,10 +2523,10 @@ x1100_rewind (Lexmark_Device * dev) and grayscale scans at the same resolution. */ /* Scan resolution */ - scan_resolution = dev->val[OPT_Y_DPI].w; + scan_resolution = dev->val[OPT_RESOLUTION].w; /* Colour mode */ - if (strcmp (dev->val[OPT_MODE].s, "Color") == 0) + if (strcmp (dev->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) == 0) colour_scan = SANE_TRUE; else colour_scan = SANE_FALSE; @@ -2632,7 +2668,8 @@ read_buffer_init (Lexmark_Device *dev, int bytesperline) (no_lines_in_buffer - 1) * bytesperline; dev->read_buffer->empty = SANE_TRUE; dev->read_buffer->image_line_no = 0; - + dev->read_buffer->bit_counter = 0; + dev->read_buffer->max_lineart_offset = dev->params.pixels_per_line - 1; return SANE_STATUS_GOOD; } @@ -2720,18 +2757,9 @@ read_buffer_add_byte_gray (Read_Buffer *rb, SANE_Byte * byte_pointer) { /* DBG(2, "read_buffer_add_byte_gray:\n"); */ - - /* Fix the endian byte ordering here */ - if ((rb->gray_offset & 0x01) == 0) - { - /*Even byte number */ - *(rb->writeptr + rb->gray_offset + 1) = *byte_pointer; - } - else - { - /*Odd byte number */ - *(rb->writeptr + rb->gray_offset - 1) = *byte_pointer; - } + + *(rb->writeptr + rb->gray_offset) = *byte_pointer; + if (rb->gray_offset == rb->max_gray_offset) { rb->image_line_no++; @@ -2749,6 +2777,80 @@ read_buffer_add_byte_gray (Read_Buffer *rb, SANE_Byte * byte_pointer) return SANE_STATUS_GOOD; } +SANE_Status +read_buffer_add_bit_lineart (Read_Buffer *rb, SANE_Byte * byte_pointer, + SANE_Byte threshold) +{ + SANE_Byte tmpByte; + SANE_Byte *currentBytePtr; + SANE_Int bitIndex; + + /* DBG(2, "read_buffer_add_bit_lineart:\n"); */ + + /* threshold = 0x80; */ + tmpByte = 0; + /* Create a bit by comparing incoming byte to threshold */ + if (*byte_pointer >= threshold) + { + tmpByte = 128; + } + + /* Calculate the bit index in the current byte */ + bitIndex = rb->bit_counter % 8; + /* Move the bit to its correct position in the temporary byte */ + tmpByte = tmpByte >> bitIndex; + /* Get the pointer to the current byte */ + currentBytePtr = rb->writeptr + rb->gray_offset; + + /* If this is the first write to this byte, clear the byte */ + if ( bitIndex == 0 ) + *currentBytePtr = 0; + /* Set the value of the bit in the current byte */ + *currentBytePtr = *currentBytePtr | tmpByte; + + + + /* last bit in the line? */ + if (rb->bit_counter == rb->max_lineart_offset) + { + /* Check if we're at the last byte of the line - error if not */ + if (rb->gray_offset != rb->max_gray_offset) + { + DBG(5, "read_buffer_add_bit_lineart:\n"); + DBG(5, " Last bit of line is not last byte.\n"); + DBG(5, " Bit Index: %d, Byte Index: %d. \n", rb->bit_counter, + rb->max_gray_offset); + return SANE_STATUS_INVAL; + } + rb->image_line_no++; + /* line finished read_buffer no longer empty */ + rb->empty = SANE_FALSE; + rb->gray_offset = 0; + /* are we at the last line in the read buffer ? */ + if (rb->writeptr == rb->max_writeptr) + rb->writeptr = rb->data; /* back to beginning of buffer */ + else + rb->writeptr = rb->writeptr + rb->linesize; /* next line */ + /* clear the bit counter */ + rb->bit_counter = 0; + } + /* last bit in the byte? */ + else if ( bitIndex == 7 ) + { + /* Not at the end of the line, but byte done. Increment byte offset */ + rb->gray_offset = rb->gray_offset + (1 * sizeof (SANE_Byte)); + /* increment bit counter */ + rb->bit_counter++; + } + else + { + /* else increment bit counter */ + rb->bit_counter++; + } + + return SANE_STATUS_GOOD; +} + size_t read_buffer_get_bytes (Read_Buffer *rb, SANE_Byte * buffer, size_t rqst_size) diff --git a/backend/lexmark.c b/backend/lexmark.c index 7013dac2e..7dee3680e 100644 --- a/backend/lexmark.c +++ b/backend/lexmark.c @@ -82,33 +82,30 @@ static const SANE_Device **sane_device_list = NULL; /* Program globals F.O - Should this be per device?*/ static SANE_Bool initialized = SANE_FALSE; -/* F.O. Per device globals - moved to lexmark.h as part of Lexmark_Device */ -/* static int eof = 0; */ -/* static SANE_Int x_dpi = 75; */ -/* static SANE_Int y_dpi = 75; */ -/* static long data_ctr = 0; */ -/* static SANE_Bool device_cancelled = SANE_FALSE; */ -/* static int cancel_ctr = 0; */ - static SANE_String_Const mode_list[] = { - "Color", "Gray", "Lineart", NULL + SANE_VALUE_SCAN_MODE_COLOR, + SANE_VALUE_SCAN_MODE_GRAY, + SANE_VALUE_SCAN_MODE_LINEART, + NULL }; /* possible resolutions are: 75x75, 150x150, 300x300, 600X600, 600X1200 */ -static SANE_Int x_dpi_list[] = { - 4, 75, 150, 300, 600 -}; - -static SANE_Int y_dpi_list[] = { - 5, 75, 150, 300, 600, - 1200 +static SANE_Int dpi_list[] = { + 5, 75, 150, 300, 600, 1200 }; static SANE_String_Const size_list[] = { "Wallet", "3x5", "4x6", "5x7", "8x10", "Letter", NULL }; +static SANE_Range threshold_range = { + SANE_FIX(0.0), /* minimum */ + SANE_FIX(100.0), /* maximum */ + SANE_FIX(1.0) /* quantization */ +}; + + /* static functions */ static SANE_Status init_options (Lexmark_Device * lexmark_device); static SANE_Status attachLexmark (SANE_String_Const devname); @@ -148,33 +145,20 @@ init_options (Lexmark_Device * lexmark_device) lexmark_device->val[OPT_MODE].s = malloc (od->size); if (!lexmark_device->val[OPT_MODE].s) return SANE_STATUS_NO_MEM; - strcpy (lexmark_device->val[OPT_MODE].s, "Color"); + strcpy (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR); - /* X dots per inch */ - od = &(lexmark_device->opt[OPT_X_DPI]); - od->name = SANE_NAME_SCAN_X_RESOLUTION; - od->title = SANE_TITLE_SCAN_X_RESOLUTION; - od->desc = SANE_DESC_SCAN_X_RESOLUTION; + /* resolution */ + od = &(lexmark_device->opt[OPT_RESOLUTION]); + od->name = SANE_NAME_SCAN_RESOLUTION; + od->title = SANE_TITLE_SCAN_RESOLUTION; + od->desc = SANE_DESC_SCAN_RESOLUTION; od->type = SANE_TYPE_INT; od->unit = SANE_UNIT_DPI; od->size = sizeof (SANE_Word); od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; od->constraint_type = SANE_CONSTRAINT_WORD_LIST; - od->constraint.word_list = x_dpi_list; - lexmark_device->val[OPT_X_DPI].w = 150; - - /* Y dots per inch */ - od = &(lexmark_device->opt[OPT_Y_DPI]); - od->name = SANE_NAME_SCAN_Y_RESOLUTION; - od->title = SANE_TITLE_SCAN_Y_RESOLUTION; - od->desc = SANE_DESC_SCAN_Y_RESOLUTION; - od->type = SANE_TYPE_INT; - od->unit = SANE_UNIT_DPI; - od->size = sizeof (SANE_Word); - od->cap = SANE_CAP_SOFT_DETECT | SANE_CAP_SOFT_SELECT; - od->constraint_type = SANE_CONSTRAINT_WORD_LIST; - od->constraint.word_list = y_dpi_list; - lexmark_device->val[OPT_Y_DPI].w = 150; + od->constraint.word_list = dpi_list; + lexmark_device->val[OPT_RESOLUTION].w = 150; /* preview mode */ od = &(lexmark_device->opt[OPT_PREVIEW]); @@ -189,9 +173,6 @@ init_options (Lexmark_Device * lexmark_device) /* scan size */ od = &(lexmark_device->opt[OPT_SCAN_SIZE]); -/* od->name = "scan-size"; */ -/* od->title = SANE_I18N ("Scan size"); */; -/* od->desc = SANE_I18N ("Selects the size of the scan."); */ od->name = SANE_NAME_PAPER_SIZE; od->title = SANE_TITLE_PAPER_SIZE; od->desc = SANE_DESC_PAPER_SIZE; @@ -206,6 +187,18 @@ init_options (Lexmark_Device * lexmark_device) return SANE_STATUS_NO_MEM; strcpy (lexmark_device->val[OPT_SCAN_SIZE].s, "3x5"); + /* threshold */ + od = &(lexmark_device->opt[OPT_THRESHOLD]); + od->name = SANE_NAME_THRESHOLD; + od->title = SANE_TITLE_THRESHOLD; + od->desc = SANE_DESC_THRESHOLD; + od->type = SANE_TYPE_FIXED; + od->unit = SANE_UNIT_PERCENT; + od->size = sizeof (SANE_Fixed); + od->cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT | SANE_CAP_INACTIVE; + od->constraint_type = SANE_CONSTRAINT_RANGE; + od->constraint.range = &threshold_range; + lexmark_device->val[OPT_THRESHOLD].w = SANE_FIX(50.0); return SANE_STATUS_GOOD; } @@ -243,6 +236,9 @@ attachLexmark (SANE_String_Const devname) /* Make the pointer to the read buffer null here */ lexmark_device->read_buffer = NULL; + /* Set the default threshold for lineart mode here */ + lexmark_device->threshold = 0x80; + lexmark_device->next = first_lexmark_device; first_lexmark_device = lexmark_device; @@ -560,33 +556,23 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, sanei_constrain_value (&(lexmark_device->opt[option]), value, info); if (status != SANE_STATUS_GOOD) - return SANE_STATUS_INVAL; + { + DBG(2, "SANE_CONTROL_OPTION: Bad value for range\n"); + return SANE_STATUS_INVAL; + } } switch (option) { case OPT_NUM_OPTS: - case OPT_X_DPI: + case OPT_RESOLUTION: lexmark_device->val[option].w = *(SANE_Int *) value; - lexmark_device->val[OPT_Y_DPI].w = *(SANE_Int *) value; - if (info) - *info |= SANE_INFO_RELOAD_OPTIONS; sane_get_parameters (handle, 0); - if (info) - *info |= SANE_INFO_RELOAD_OPTIONS; - return SANE_STATUS_GOOD; - case OPT_Y_DPI: - lexmark_device->val[option].w = *(SANE_Int *) value; - if (*(SANE_Int *) value == 1200) - lexmark_device->val[OPT_X_DPI].w = 600; - else - lexmark_device->val[OPT_X_DPI].w = *(SANE_Int *) value; - if (info) - *info |= SANE_INFO_RELOAD_OPTIONS; - sane_get_parameters (handle, 0); - if (info) - *info |= SANE_INFO_RELOAD_OPTIONS; - return SANE_STATUS_GOOD; + break; + case OPT_THRESHOLD: + lexmark_device->val[option].w = *(SANE_Fixed *) value; + lexmark_device->threshold = 0xFF * (lexmark_device->val[option].w/100); + break; case OPT_SCAN_SIZE: strcpy (lexmark_device->val[option].s, value); break; @@ -594,15 +580,12 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, lexmark_device->val[option].w = *(SANE_Int *) value; if (*(SANE_Word *) value) { - lexmark_device->x_dpi = lexmark_device->val[OPT_X_DPI].w; - lexmark_device->y_dpi = lexmark_device->val[OPT_Y_DPI].w; - lexmark_device->val[OPT_X_DPI].w = 75; - lexmark_device->val[OPT_Y_DPI].w = 75; + lexmark_device->y_dpi = lexmark_device->val[OPT_RESOLUTION].w; + lexmark_device->val[OPT_RESOLUTION].w = 75; } else { - lexmark_device->val[OPT_X_DPI].w = lexmark_device->x_dpi; - lexmark_device->val[OPT_Y_DPI].w = lexmark_device->y_dpi; + lexmark_device->val[OPT_RESOLUTION].w = lexmark_device->y_dpi; } if (info) *info |= SANE_INFO_RELOAD_OPTIONS; @@ -613,7 +596,18 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, lexmark_device->val[option].w = *(SANE_Int *) value; break; case OPT_MODE: - strcpy (lexmark_device->val[option].s, value); + strcpy (lexmark_device->val[option].s, value); + if (strcmp (lexmark_device->val[option].s, + SANE_VALUE_SCAN_MODE_LINEART) == 0) + { + lexmark_device->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; + } + else + { + lexmark_device->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; + } + if (info) + *info |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; break; } @@ -627,10 +621,14 @@ sane_control_option (SANE_Handle handle, SANE_Int option, SANE_Action action, switch (option) { case OPT_NUM_OPTS: - case OPT_X_DPI: - case OPT_Y_DPI: + case OPT_RESOLUTION: case OPT_PREVIEW: *(SANE_Int *) value = lexmark_device->val[option].w; + DBG(2,"Option value = %d\n", *(SANE_Int *) value); + break; + case OPT_THRESHOLD: + *(SANE_Fixed *) value = lexmark_device->val[option].w; + DBG(2,"Option value = %f\n", SANE_UNFIX(*(SANE_Fixed *) value)); break; case OPT_MODE: case OPT_SCAN_SIZE: @@ -676,16 +674,20 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) if (!lexmark_device) return SANE_STATUS_INVAL; - xres = lexmark_device->val[OPT_X_DPI].w; - yres = lexmark_device->val[OPT_Y_DPI].w; + yres = lexmark_device->val[OPT_RESOLUTION].w; + if (yres == 1200) + xres = 600; + else + xres = yres; /* 24 bit colour = 8 bits/channel for each of the RGB channels */ channels = 3; bitsperchannel = 8; isColourScan = SANE_TRUE; - /* If grayscale there is only 1 channel */ - if (strcmp (lexmark_device->val[OPT_MODE].s, "Gray") == 0) + /* If not color there is only 1 channel */ + if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_COLOR) + != 0) { channels = 1; bitsperchannel = 8; @@ -742,12 +744,22 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) lexmark_device->pixel_width = width_px; lexmark_device->pixel_height = height_px; - + /* data_size is the size transferred from the scanner to the backend */ + /* therefor bitsperchannel is the same for gray and lineart */ lexmark_device->data_size = width_px * height_px * channels * (bitsperchannel / 8); DBG (2, "sane_get_parameters: Data size determined as %lx\n", lexmark_device->data_size); + /* we must tell the front end the bitsperchannel for lineart is really */ + /* only 1, so it can calculate the correct image size */ + /* If not color there is only 1 channel */ + if (strcmp (lexmark_device->val[OPT_MODE].s, SANE_VALUE_SCAN_MODE_LINEART) + == 0) + { + bitsperchannel = 1; + } + device_params = &(lexmark_device->params); device_params->format = SANE_FRAME_RGB; if (channels == 1) @@ -759,7 +771,16 @@ sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) device_params->bytes_per_line = (SANE_Int) (channels * device_params->pixels_per_line * (bitsperchannel / 8)); - /* bytesperchannel = bitsperchannel/8 */ + if ( bitsperchannel == 1 ) + { + device_params->bytes_per_line = + (SANE_Int) (device_params->pixels_per_line / 8); + if ((device_params->pixels_per_line % 8) != 0) + device_params->bytes_per_line++; + } + + + DBG (2, "sane_get_parameters: \n"); if (device_params->format == SANE_FRAME_GRAY) DBG (2, " format: SANE_FRAME_GRAY\n"); diff --git a/backend/lexmark.h b/backend/lexmark.h index d3e05be30..3bca2b778 100644 --- a/backend/lexmark.h +++ b/backend/lexmark.h @@ -61,10 +61,12 @@ typedef enum { OPT_NUM_OPTS = 0, OPT_MODE, - OPT_X_DPI, - OPT_Y_DPI, +/* OPT_X_DPI, */ +/* OPT_Y_DPI, */ + OPT_RESOLUTION, OPT_PREVIEW, OPT_SCAN_SIZE, + OPT_THRESHOLD, /* must come last: */ NUM_OPTIONS } @@ -114,6 +116,8 @@ typedef struct Read_Buffer size_t linesize; SANE_Bool empty; SANE_Int image_line_no; + SANE_Int bit_counter; + SANE_Int max_lineart_offset; } Read_Buffer; @@ -141,6 +145,7 @@ typedef struct Lexmark_Device size_t bytes_in_buffer; SANE_Byte *read_pointer; Read_Buffer *read_buffer; + SANE_Byte threshold; } Lexmark_Device;