Extensive changes to reduce the amount of global variables in mustek_usb2_high.c.

Might have made MustScanner_SetupScan less readable, though.
merge-requests/1/head
Jan Hauffa 2011-04-20 23:10:53 +02:00 zatwierdzone przez m. allan noah
rodzic 9444bf1156
commit c1dc16d709
4 zmienionych plików z 343 dodań i 398 usunięć

Wyświetl plik

@ -117,10 +117,123 @@ static const Scanner_Model mustek_A2nu2_model = {
SANE_FIX (1.46 * MM_PER_INCH), /* size of scan area in TA mode in mm (x) */ SANE_FIX (1.46 * MM_PER_INCH), /* size of scan area in TA mode in mm (x) */
SANE_FIX (6.45 * MM_PER_INCH), /* size of scan area in TA mode in mm (y) */ SANE_FIX (6.45 * MM_PER_INCH), /* size of scan area in TA mode in mm (y) */
RO_RGB /* order of the CCD/CIS colors */ SANE_FALSE /* invert order of the CCD/CIS colors? */
}; };
static void
get_target_image (Mustek_Scanner * s, TARGETIMAGE * pTarget)
{
SANE_String val, val_source;
float x1, y1, x2, y2;
DBG (DBG_FUNC, "get_target_image: start\n");
if (s->val[OPT_PREVIEW].w)
pTarget->wXDpi = 75;
else
pTarget->wXDpi = s->val[OPT_RESOLUTION].w;
pTarget->wYDpi = pTarget->wXDpi;
x1 = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH;
y1 = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH;
x2 = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH;
y2 = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH;
pTarget->wX = (unsigned short) ((x1 * pTarget->wXDpi) + 0.5);
pTarget->wY = (unsigned short) ((y1 * pTarget->wYDpi) + 0.5);
pTarget->wWidth = (unsigned short) (((x2 - x1) * pTarget->wXDpi) + 0.5);
pTarget->wHeight = (unsigned short) (((y2 - y1) * pTarget->wYDpi) + 0.5);
pTarget->wLineartThreshold = s->val[OPT_THRESHOLD].w;
val_source = s->val[OPT_SOURCE].s;
DBG (DBG_DET, "get_target_image: scan source = %s\n", val_source);
if (strcmp (val_source, source_list[SS_POSITIVE]) == 0)
pTarget->ssScanSource = SS_POSITIVE;
else if (strcmp (val_source, source_list[SS_NEGATIVE]) == 0)
pTarget->ssScanSource = SS_NEGATIVE;
else
pTarget->ssScanSource = SS_REFLECTIVE;
val = s->val[OPT_MODE].s;
if (strcmp (val, mode_list[CM_RGB48]) == 0)
{
if (s->val[OPT_PREVIEW].w)
{
DBG (DBG_DET, "get_target_image: preview, set ColorMode CM_RGB24\n");
pTarget->cmColorMode = CM_RGB24;
}
else
pTarget->cmColorMode = CM_RGB48;
}
else if (strcmp (val, mode_list[CM_RGB24]) == 0)
{
pTarget->cmColorMode = CM_RGB24;
}
else if (strcmp (val, mode_list[CM_GRAY16]) == 0)
{
if (s->val[OPT_PREVIEW].w)
{
DBG (DBG_DET, "get_target_image: preview, set ColorMode CM_GRAY8\n");
pTarget->cmColorMode = CM_GRAY8;
}
else
pTarget->cmColorMode = CM_GRAY16;
}
else if (strcmp (val, mode_list[CM_GRAY8]) == 0)
{
pTarget->cmColorMode = CM_GRAY8;
}
else
{
pTarget->cmColorMode = CM_TEXT;
}
DBG (DBG_FUNC, "get_target_image: exit\n");
}
static void
calc_parameters (TARGETIMAGE * pTarget, SANE_Parameters * params)
{
DBG (DBG_FUNC, "calc_parameters: start\n");
params->pixels_per_line = pTarget->wWidth;
params->lines = pTarget->wHeight;
params->last_frame = SANE_TRUE;
switch (pTarget->cmColorMode)
{
case CM_RGB48:
params->format = SANE_FRAME_RGB;
params->depth = 16;
params->bytes_per_line = params->pixels_per_line * 6;
break;
case CM_RGB24:
params->format = SANE_FRAME_RGB;
params->depth = 8;
params->bytes_per_line = params->pixels_per_line * 3;
break;
case CM_GRAY16:
params->format = SANE_FRAME_GRAY;
params->depth = 16;
params->bytes_per_line = params->pixels_per_line * 2;
break;
case CM_GRAY8:
params->format = SANE_FRAME_GRAY;
params->depth = 8;
params->bytes_per_line = params->pixels_per_line;
break;
case CM_TEXT:
params->format = SANE_FRAME_GRAY;
params->depth = 1;
params->bytes_per_line = params->pixels_per_line / 8;
break;
}
DBG (DBG_FUNC, "calc_parameters: exit\n");
}
static size_t static size_t
max_string_size (SANE_String_Const *strings) max_string_size (SANE_String_Const *strings)
{ {
@ -136,120 +249,12 @@ max_string_size (SANE_String_Const *strings)
return max_size; return max_size;
} }
static void
calc_parameters (Mustek_Scanner * s)
{
SANE_String val, val_source;
float x1, y1, x2, y2;
DBG (DBG_FUNC, "calc_parameters: start\n");
if (s->val[OPT_PREVIEW].w)
s->setpara.wDpi = 75;
else
s->setpara.wDpi = s->val[OPT_RESOLUTION].w;
x1 = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH;
y1 = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH;
x2 = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH;
y2 = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH;
s->setpara.wX = (unsigned short) ((x1 * s->setpara.wDpi) + 0.5);
s->setpara.wY = (unsigned short) ((y1 * s->setpara.wDpi) + 0.5);
s->setpara.wWidth = (unsigned short) (((x2 - x1) * s->setpara.wDpi) + 0.5);
s->setpara.wHeight = (unsigned short) (((y2 - y1) * s->setpara.wDpi) + 0.5);
s->setpara.wLineartThreshold = s->val[OPT_THRESHOLD].w;
val_source = s->val[OPT_SOURCE].s;
DBG (DBG_DET, "calc_parameters: scan source = %s\n", val_source);
if (strcmp (val_source, source_list[SS_POSITIVE]) == 0)
s->setpara.ssScanSource = SS_POSITIVE;
else if (strcmp (val_source, source_list[SS_NEGATIVE]) == 0)
s->setpara.ssScanSource = SS_NEGATIVE;
else
s->setpara.ssScanSource = SS_REFLECTIVE;
val = s->val[OPT_MODE].s;
if (strcmp (val, mode_list[CM_RGB48]) == 0)
{
if (s->val[OPT_PREVIEW].w)
{
DBG (DBG_DET, "calc_parameters: preview, set ColorMode CM_RGB24\n");
s->setpara.cmColorMode = CM_RGB24;
}
else
{
s->setpara.cmColorMode = CM_RGB48;
}
}
else if (strcmp (val, mode_list[CM_RGB24]) == 0)
{
s->setpara.cmColorMode = CM_RGB24;
}
else if (strcmp (val, mode_list[CM_GRAY16]) == 0)
{
if (s->val[OPT_PREVIEW].w)
{
DBG (DBG_DET, "calc_parameters: preview, set ColorMode CM_GRAY8\n");
s->setpara.cmColorMode = CM_GRAY8;
}
else
{
s->setpara.cmColorMode = CM_GRAY16;
}
}
else if (strcmp (val, mode_list[CM_GRAY8]) == 0)
{
s->setpara.cmColorMode = CM_GRAY8;
}
else
{
s->setpara.cmColorMode = CM_TEXT;
}
/* provide an estimate for scan parameters returned by sane_get_parameters */
s->params.pixels_per_line = s->setpara.wWidth;
s->params.lines = s->setpara.wHeight;
s->params.last_frame = SANE_TRUE;
switch (s->setpara.cmColorMode)
{
case CM_RGB48:
s->params.format = SANE_FRAME_RGB;
s->params.depth = 16;
s->params.bytes_per_line = s->params.pixels_per_line * 6;
break;
case CM_RGB24:
s->params.format = SANE_FRAME_RGB;
s->params.depth = 8;
s->params.bytes_per_line = s->params.pixels_per_line * 3;
break;
case CM_GRAY16:
s->params.format = SANE_FRAME_GRAY;
s->params.depth = 16;
s->params.bytes_per_line = s->params.pixels_per_line * 2;
break;
case CM_GRAY8:
s->params.format = SANE_FRAME_GRAY;
s->params.depth = 8;
s->params.bytes_per_line = s->params.pixels_per_line;
break;
case CM_TEXT:
s->params.format = SANE_FRAME_GRAY;
s->params.depth = 1;
s->params.bytes_per_line = s->params.pixels_per_line / 8;
break;
}
DBG (DBG_FUNC, "calc_parameters: exit\n");
}
static SANE_Status static SANE_Status
init_options (Mustek_Scanner * s) init_options (Mustek_Scanner * s)
{ {
SANE_Int option, count = 0; SANE_Int option, count = 0;
SANE_Word *dpi_list; SANE_Word *dpi_list;
TARGETIMAGE target;
DBG (DBG_FUNC, "init_options: start\n"); DBG (DBG_FUNC, "init_options: start\n");
@ -401,40 +406,13 @@ init_options (Mustek_Scanner * s)
s->opt[OPT_BR_Y].constraint.range = &y_range; s->opt[OPT_BR_Y].constraint.range = &y_range;
s->val[OPT_BR_Y].w = y_range.max; s->val[OPT_BR_Y].w = y_range.max;
calc_parameters (s); get_target_image (s, &target);
calc_parameters (&target, &s->params);
DBG (DBG_FUNC, "init_options: exit\n"); DBG (DBG_FUNC, "init_options: exit\n");
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
static SANE_Bool
ReadScannedData (IMAGEROWS * pImageRows, TARGETIMAGE * pTarget)
{
SANE_Bool isRGBInvert;
unsigned short Rows;
unsigned int i;
DBG (DBG_FUNC, "ReadScannedData: start\n");
isRGBInvert = (pImageRows->roRgbOrder == RO_RGB) ? SANE_FALSE : SANE_TRUE;
Rows = pImageRows->wWantedLineNum;
DBG (DBG_INFO, "ReadScannedData: wanted rows = %d\n", Rows);
if (!MustScanner_GetRows (pImageRows->pBuffer, &Rows, isRGBInvert))
return SANE_FALSE;
pImageRows->wXferedLineNum = Rows;
if ((pTarget->cmColorMode == CM_TEXT) ||
(pTarget->ssScanSource == SS_NEGATIVE))
{
for (i = 0; i < (Rows * pTarget->dwBytesPerRow); i++)
pImageRows->pBuffer[i] ^= 0xff;
}
DBG (DBG_FUNC, "ReadScannedData: exit\n");
return SANE_TRUE;
}
/****************************** SANE API functions ****************************/ /****************************** SANE API functions ****************************/
@ -564,6 +542,7 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
SANE_Status status; SANE_Status status;
SANE_Word cap; SANE_Word cap;
SANE_Int myinfo = 0; SANE_Int myinfo = 0;
TARGETIMAGE target;
DBG (DBG_FUNC, "sane_control_option: start: action = %s, option = %s (%d)\n", DBG (DBG_FUNC, "sane_control_option: start: action = %s, option = %s (%d)\n",
(action == SANE_ACTION_GET_VALUE) ? "get" : (action == SANE_ACTION_GET_VALUE) ? "get" :
@ -645,7 +624,8 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
case OPT_BR_X: case OPT_BR_X:
case OPT_BR_Y: case OPT_BR_Y:
s->val[option].w = *(SANE_Word *) val; s->val[option].w = *(SANE_Word *) val;
calc_parameters (s); get_target_image (s, &target);
calc_parameters (&target, &s->params);
myinfo |= SANE_INFO_RELOAD_PARAMS; myinfo |= SANE_INFO_RELOAD_PARAMS;
break; break;
case OPT_THRESHOLD: case OPT_THRESHOLD:
@ -660,7 +640,8 @@ sane_control_option (SANE_Handle handle, SANE_Int option,
s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap &= ~SANE_CAP_INACTIVE;
else else
s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; s->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE;
calc_parameters (s); get_target_image (s, &target);
calc_parameters (&target, &s->params);
myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS; myinfo |= SANE_INFO_RELOAD_PARAMS | SANE_INFO_RELOAD_OPTIONS;
break; break;
case OPT_SOURCE: case OPT_SOURCE:
@ -740,6 +721,7 @@ SANE_Status
sane_start (SANE_Handle handle) sane_start (SANE_Handle handle)
{ {
Mustek_Scanner *s = handle; Mustek_Scanner *s = handle;
TARGETIMAGE target;
DBG (DBG_FUNC, "sane_start: start\n"); DBG (DBG_FUNC, "sane_start: start\n");
@ -750,29 +732,26 @@ sane_start (SANE_Handle handle)
return SANE_FALSE; return SANE_FALSE;
} }
calc_parameters (s); get_target_image (s, &target);
DBG (DBG_INFO, "sane_start: setpara.wX=%d\n", s->setpara.wX); DBG (DBG_INFO, "sane_start: target.wX=%d\n", target.wX);
DBG (DBG_INFO, "sane_start: setpara.wY=%d\n", s->setpara.wY); DBG (DBG_INFO, "sane_start: target.wY=%d\n", target.wY);
DBG (DBG_INFO, "sane_start: setpara.wWidth=%d\n", s->setpara.wWidth); DBG (DBG_INFO, "sane_start: target.wWidth=%d\n", target.wWidth);
DBG (DBG_INFO, "sane_start: setpara.wHeight=%d\n", s->setpara.wHeight); DBG (DBG_INFO, "sane_start: target.wHeight=%d\n", target.wHeight);
DBG (DBG_INFO, "sane_start: setpara.wLineartThreshold=%d\n", DBG (DBG_INFO, "sane_start: target.wLineartThreshold=%d\n",
s->setpara.wLineartThreshold); target.wLineartThreshold);
DBG (DBG_INFO, "sane_start: setpara.wDpi=%d\n", s->setpara.wDpi); DBG (DBG_INFO, "sane_start: target.wXDpi=%d\n", target.wXDpi);
DBG (DBG_INFO, "sane_start: setpara.cmColorMode=%d\n", DBG (DBG_INFO, "sane_start: target.wYDpi=%d\n", target.wYDpi);
s->setpara.cmColorMode); DBG (DBG_INFO, "sane_start: target.cmColorMode=%d\n", target.cmColorMode);
DBG (DBG_INFO, "sane_start: setpara.ssScanSource=%d\n", DBG (DBG_INFO, "sane_start: target.ssScanSource=%d\n", target.ssScanSource);
s->setpara.ssScanSource);
MustScanner_Reset (); MustScanner_Reset ();
/* adjust parameters to the scanner's requirements */ /* adjust parameters to the scanner's requirements */
MustScanner_ScanSuggest (&s->setpara); MustScanner_ScanSuggest (&target);
calc_parameters (&target, &s->params);
/* update the scan parameters to be returned by sane_get_parameters */ s->bInvertImage = ((target.cmColorMode == CM_TEXT) ^
s->params.pixels_per_line = s->setpara.wWidth; (target.ssScanSource == SS_NEGATIVE));
s->params.lines = s->setpara.wHeight;
s->params.bytes_per_line = s->setpara.dwBytesPerRow;
s->read_rows = s->params.lines; s->read_rows = s->params.lines;
DBG (DBG_INFO, "sane_start: read_rows = %d\n", s->read_rows); DBG (DBG_INFO, "sane_start: read_rows = %d\n", s->read_rows);
@ -787,7 +766,7 @@ sane_start (SANE_Handle handle)
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
s->scan_buf_len = 0; s->scan_buf_len = 0;
if (!MustScanner_SetupScan (&s->setpara)) if (!MustScanner_SetupScan (&target))
return SANE_STATUS_INVAL; return SANE_STATUS_INVAL;
DBG (DBG_FUNC, "sane_start: exit\n"); DBG (DBG_FUNC, "sane_start: exit\n");
@ -801,8 +780,9 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
Mustek_Scanner *s = handle; Mustek_Scanner *s = handle;
SANE_Byte *tempbuf; SANE_Byte *tempbuf;
long int tempbuf_size; long int tempbuf_size;
SANE_Int lines_to_read, lines_read; SANE_Int lines, lines_read;
IMAGEROWS image_row; unsigned short lines_received;
int i;
DBG (DBG_FUNC, "sane_read: start: max_len=%d\n", max_len); DBG (DBG_FUNC, "sane_read: start: max_len=%d\n", max_len);
@ -826,33 +806,34 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
{ {
if (s->read_rows > 0) if (s->read_rows > 0)
{ {
lines_to_read = SCAN_BUFFER_SIZE / s->setpara.dwBytesPerRow; lines = SCAN_BUFFER_SIZE / s->params.bytes_per_line;
if (lines_to_read > s->read_rows) lines = _MIN (lines, s->read_rows);
lines_to_read = s->read_rows;
tempbuf_size = lines_to_read * s->setpara.dwBytesPerRow + tempbuf_size = lines * s->params.bytes_per_line + 3 * 1024 + 1;
3 * 1024 + 1;
tempbuf = malloc (tempbuf_size); tempbuf = malloc (tempbuf_size);
if (!tempbuf) if (!tempbuf)
return SANE_STATUS_NO_MEM; return SANE_STATUS_NO_MEM;
memset (tempbuf, 0, tempbuf_size); memset (tempbuf, 0, tempbuf_size);
DBG (DBG_INFO, "sane_read: buffer size is %ld\n", tempbuf_size); DBG (DBG_INFO, "sane_read: buffer size is %ld\n", tempbuf_size);
image_row.roRgbOrder = s->model.line_mode_color_order;
image_row.wWantedLineNum = lines_to_read;
image_row.pBuffer = tempbuf;
s->bIsReading = SANE_TRUE; s->bIsReading = SANE_TRUE;
lines_received = (unsigned short) lines;
if (!ReadScannedData (&image_row, &s->setpara)) if (!MustScanner_GetRows (tempbuf, &lines_received,
s->model.isRGBInvert))
{ {
DBG (DBG_ERR, "sane_read: ReadScannedData error\n"); DBG (DBG_ERR, "sane_read: MustScanner_GetRows error\n");
s->bIsReading = SANE_FALSE; s->bIsReading = SANE_FALSE;
return SANE_STATUS_INVAL; return SANE_STATUS_INVAL;
} }
if (s->bInvertImage)
{
for (i = 0; i < (lines_received * s->params.bytes_per_line); i++)
tempbuf[i] ^= 0xff;
}
DBG (DBG_DBG, "sane_read: Finish ReadScanedData\n"); DBG (DBG_DBG, "sane_read: Finish ReadScanedData\n");
s->scan_buf_len = s->scan_buf_len = lines_received * s->params.bytes_per_line;
image_row.wXferedLineNum * s->setpara.dwBytesPerRow;
DBG (DBG_INFO, "sane_read : s->scan_buf_len = %ld\n", DBG (DBG_INFO, "sane_read : s->scan_buf_len = %ld\n",
(long int) s->scan_buf_len); (long int) s->scan_buf_len);
@ -866,7 +847,7 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
DBG (DBG_DBG, "sane_read: after memcpy\n"); DBG (DBG_DBG, "sane_read: after memcpy\n");
free (tempbuf); free (tempbuf);
s->scan_buf_start = s->scan_buf; s->scan_buf_start = s->scan_buf;
s->read_rows -= image_row.wXferedLineNum; s->read_rows -= lines_received;
s->bIsReading = SANE_FALSE; s->bIsReading = SANE_FALSE;
} }
else else
@ -882,17 +863,14 @@ sane_read (SANE_Handle handle, SANE_Byte * buf, SANE_Int max_len,
} }
} }
lines_read = _MIN (max_len, (SANE_Int) s->scan_buf_len); lines_read = _MIN (max_len, s->scan_buf_len);
DBG (DBG_DBG, "sane_read: after %d\n", lines_read); DBG (DBG_DBG, "sane_read: after %d\n", lines_read);
*len = lines_read;
*len = (SANE_Int) lines_read;
DBG (DBG_INFO, "sane_read: get lines_read = %d\n", lines_read);
DBG (DBG_INFO, "sane_read: get *len = %d\n", *len);
memcpy (buf, s->scan_buf_start, lines_read); memcpy (buf, s->scan_buf_start, lines_read);
s->scan_buf_len -= lines_read; s->scan_buf_len -= lines_read;
s->scan_buf_start += lines_read; s->scan_buf_start += lines_read;
DBG (DBG_FUNC, "sane_read: exit\n"); DBG (DBG_FUNC, "sane_read: exit\n");
return SANE_STATUS_GOOD; return SANE_STATUS_GOOD;
} }
@ -932,7 +910,6 @@ sane_cancel (SANE_Handle handle)
s->read_rows = 0; s->read_rows = 0;
s->scan_buf_len = 0; s->scan_buf_len = 0;
memset (&s->setpara, 0, sizeof (s->setpara));
} }
else else
{ {

Wyświetl plik

@ -79,20 +79,6 @@ enum
NUM_OPTIONS NUM_OPTIONS
}; };
typedef enum
{
RO_RGB,
RO_BGR
} RGBORDER;
typedef struct
{
RGBORDER roRgbOrder;
unsigned short wWantedLineNum;
unsigned short wXferedLineNum;
SANE_Byte * pBuffer;
} IMAGEROWS;
typedef struct typedef struct
{ {
@ -113,7 +99,8 @@ typedef struct
SANE_Fixed x_size_ta; /* size of scan area in TA mode in mm */ SANE_Fixed x_size_ta; /* size of scan area in TA mode in mm */
SANE_Fixed y_size_ta; SANE_Fixed y_size_ta;
RGBORDER line_mode_color_order; /* order of the CCD/CIS colors */ SANE_Bool isRGBInvert; /* order of the CCD/CIS colors:
RGB if SANE_False, BGR otherwise */
/*@} */ /*@} */
} Scanner_Model; } Scanner_Model;
@ -125,13 +112,13 @@ typedef struct Mustek_Scanner
Option_Value val[NUM_OPTIONS]; Option_Value val[NUM_OPTIONS];
SANE_Parameters params; SANE_Parameters params;
Scanner_Model model; Scanner_Model model;
TARGETIMAGE setpara;
SANE_Bool bIsScanning; SANE_Bool bIsScanning;
SANE_Bool bIsReading; SANE_Bool bIsReading;
SANE_Bool bInvertImage;
SANE_Word read_rows; /* number of image lines left to read */ SANE_Word read_rows; /* number of image lines left to read */
SANE_Byte * scan_buf; SANE_Byte * scan_buf;
SANE_Byte * scan_buf_start; SANE_Byte * scan_buf_start;
size_t scan_buf_len; SANE_Int scan_buf_len;
} Mustek_Scanner; } Mustek_Scanner;
#endif #endif

Wyświetl plik

@ -59,55 +59,38 @@
#include "mustek_usb2_high.h" #include "mustek_usb2_high.h"
/* HOLD: these global variables should go to scanner structure */ /* HOLD: these global variables should go to scanner structure */
static SANE_Bool g_bOpened; static SANE_Bool g_bOpened;
static SANE_Bool g_bPrepared; static SANE_Bool g_bPrepared;
static SANE_Bool g_isCanceled; static SANE_Bool g_isCanceled;
static SANE_Bool g_bFirstReadImage; static SANE_Bool g_bFirstReadImage;
static SANE_Byte * g_pReadImageHead; static SANE_Byte * g_pReadImageHead;
static unsigned short g_X; static TARGETIMAGE g_Target;
static unsigned short g_Y;
static unsigned short g_Width;
static unsigned short g_Height;
static unsigned short g_XDpi;
static unsigned short g_YDpi;
static unsigned short g_SWWidth; static unsigned short g_SWWidth;
static unsigned short g_SWHeight; static unsigned short g_SWHeight;
static unsigned short g_wPixelDistance; /* even & odd sensor problem */
/* even & odd sensor problem */
static unsigned short g_wPixelDistance;
static unsigned short g_wLineDistance; static unsigned short g_wLineDistance;
static unsigned short g_wScanLinesPerBlock; static unsigned short g_wScanLinesPerBlock;
static unsigned short g_wLineartThreshold;
static unsigned int g_wtheReadyLines; static unsigned int g_wtheReadyLines;
static unsigned int g_wMaxScanLines; static unsigned int g_wMaxScanLines;
static unsigned int g_dwScannedTotalLines; static unsigned int g_dwScannedTotalLines;
static unsigned int g_BytesPerRow; static unsigned int g_BytesPerRow;
static unsigned int g_SWBytesPerRow; static unsigned int g_SWBytesPerRow;
static unsigned int g_dwTotalTotalXferLines; static unsigned int g_dwTotalTotalXferLines;
static unsigned short * g_pGammaTable;
static pthread_t g_threadid_readimage; static pthread_t g_threadid_readimage;
static COLORMODE g_ScanMode;
static SCANSOURCE g_ssScanSource;
static ASIC g_chip;
static int g_nSecLength, g_nDarkSecLength;
static int g_nSecNum, g_nDarkSecNum;
static unsigned short g_wCalWidth;
static unsigned short g_wDarkCalWidth;
static int g_nPowerNum;
static unsigned short g_wStartPosition;
static pthread_mutex_t g_scannedLinesMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_scannedLinesMutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_readyLinesMutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_readyLinesMutex = PTHREAD_MUTEX_INITIALIZER;
static unsigned short * g_pGammaTable;
static ASIC g_chip;
/* for modifying the last point */ /* for modifying the last point */
static SANE_Bool g_bIsFirstReadBefData = SANE_TRUE; static SANE_Bool g_bIsFirstReadBefData = SANE_TRUE;
static SANE_Byte * g_pBefLineImageData; static SANE_Byte * g_pBefLineImageData;
@ -129,8 +112,6 @@ MustScanner_Init (void)
g_pGammaTable = NULL; g_pGammaTable = NULL;
g_ssScanSource = SS_REFLECTIVE;
DBG (DBG_FUNC, "MustScanner_Init: leave MustScanner_Init\n"); DBG (DBG_FUNC, "MustScanner_Init: leave MustScanner_Init\n");
} }
@ -350,7 +331,7 @@ GetRgb48BitLineFull (SANE_Byte * pLine, SANE_Bool isOrderInvert)
unsigned int dwRTempData, dwGTempData, dwBTempData; unsigned int dwRTempData, dwGTempData, dwBTempData;
unsigned short i = 0; unsigned short i = 0;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
wRLinePosOdd = g_wtheReadyLines - g_wPixelDistance; wRLinePosOdd = g_wtheReadyLines - g_wPixelDistance;
wGLinePosOdd = g_wtheReadyLines - g_wLineDistance - g_wPixelDistance; wGLinePosOdd = g_wtheReadyLines - g_wLineDistance - g_wPixelDistance;
@ -490,7 +471,7 @@ GetRgb24BitLineFull (SANE_Byte * pLine, SANE_Bool isOrderInvert)
unsigned short tempR, tempG, tempB; unsigned short tempR, tempG, tempB;
unsigned short i = 0; unsigned short i = 0;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
wRLinePosOdd = g_wtheReadyLines - g_wPixelDistance; wRLinePosOdd = g_wtheReadyLines - g_wPixelDistance;
wGLinePosOdd = g_wtheReadyLines - g_wLineDistance - g_wPixelDistance; wGLinePosOdd = g_wtheReadyLines - g_wLineDistance - g_wPixelDistance;
@ -588,7 +569,7 @@ GetMono16BitLineFull (SANE_Byte * pLine,
unsigned short wLinePosEven; unsigned short wLinePosEven;
unsigned short i = 0; unsigned short i = 0;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
wLinePosOdd = g_wtheReadyLines - g_wPixelDistance; wLinePosOdd = g_wtheReadyLines - g_wPixelDistance;
wLinePosEven = g_wtheReadyLines; wLinePosEven = g_wtheReadyLines;
@ -660,7 +641,7 @@ GetMono8BitLineFull (SANE_Byte * pLine,
unsigned short wGray; unsigned short wGray;
unsigned short i = 0; unsigned short i = 0;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
@ -705,7 +686,7 @@ GetMono1BitLineHalf (SANE_Byte * pLine,
for (i = 0; i < g_SWWidth; i++) for (i = 0; i < g_SWWidth; i++)
{ {
if (g_pReadImageHead[wLinePos + i] > g_wLineartThreshold) if (g_pReadImageHead[wLinePos + i] > g_Target.wLineartThreshold)
pLine[i / 8] |= 0x80 >> (i % 8); pLine[i / 8] |= 0x80 >> (i % 8);
} }
} }
@ -718,7 +699,7 @@ GetMono1BitLineFull (SANE_Byte * pLine,
unsigned short wLinePosEven; unsigned short wLinePosEven;
unsigned short i = 0; unsigned short i = 0;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines; wLinePosOdd = (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines; wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
@ -736,11 +717,11 @@ GetMono1BitLineFull (SANE_Byte * pLine,
if ((i + 1) >= g_SWWidth) if ((i + 1) >= g_SWWidth)
break; break;
if (g_pReadImageHead[wLinePosOdd + i] > g_wLineartThreshold) if (g_pReadImageHead[wLinePosOdd + i] > g_Target.wLineartThreshold)
pLine[i / 8] |= 0x80 >> (i % 8); pLine[i / 8] |= 0x80 >> (i % 8);
i++; i++;
if (g_pReadImageHead[wLinePosEven + i] > g_wLineartThreshold) if (g_pReadImageHead[wLinePosEven + i] > g_Target.wLineartThreshold)
pLine[i / 8] |= 0x80 >> (i % 8); pLine[i / 8] |= 0x80 >> (i % 8);
i++; i++;
} }
@ -822,7 +803,7 @@ static void *
MustScanner_ReadDataFromScanner (void __sane_unused__ * dummy) MustScanner_ReadDataFromScanner (void __sane_unused__ * dummy)
{ {
unsigned short wTotalReadImageLines = 0; unsigned short wTotalReadImageLines = 0;
unsigned short wWantedLines = g_Height; unsigned short wWantedLines = g_Target.wHeight;
SANE_Byte * pReadImage = g_pReadImageHead; SANE_Byte * pReadImage = g_pReadImageHead;
SANE_Bool isWaitImageLineDiff = SANE_FALSE; SANE_Bool isWaitImageLineDiff = SANE_FALSE;
unsigned int wMaxScanLines = g_wMaxScanLines; unsigned int wMaxScanLines = g_wMaxScanLines;
@ -996,24 +977,24 @@ MustScanner_GetRows (SANE_Byte * pBlock, unsigned short * Rows,
return SANE_FALSE; return SANE_FALSE;
} }
switch (g_ScanMode) switch (g_Target.cmColorMode)
{ {
case CM_RGB48: case CM_RGB48:
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
pFunc = GetRgb48BitLineFull; pFunc = GetRgb48BitLineFull;
else else
pFunc = GetRgb48BitLineHalf; pFunc = GetRgb48BitLineHalf;
break; break;
case CM_RGB24: case CM_RGB24:
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
pFunc = GetRgb24BitLineFull; pFunc = GetRgb24BitLineFull;
else else
pFunc = GetRgb24BitLineHalf; pFunc = GetRgb24BitLineHalf;
break; break;
case CM_GRAY16: case CM_GRAY16:
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
{ {
fixEvenOdd = SANE_TRUE; fixEvenOdd = SANE_TRUE;
pFunc = GetMono16BitLineFull; pFunc = GetMono16BitLineFull;
@ -1025,7 +1006,7 @@ MustScanner_GetRows (SANE_Byte * pBlock, unsigned short * Rows,
break; break;
case CM_GRAY8: case CM_GRAY8:
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
{ {
fixEvenOdd = SANE_TRUE; fixEvenOdd = SANE_TRUE;
pFunc = GetMono8BitLineFull; pFunc = GetMono8BitLineFull;
@ -1039,7 +1020,7 @@ MustScanner_GetRows (SANE_Byte * pBlock, unsigned short * Rows,
case CM_TEXT: case CM_TEXT:
memset (pBlock, 0, *Rows * g_SWWidth / 8); memset (pBlock, 0, *Rows * g_SWWidth / 8);
dwLineIncrement /= 8; dwLineIncrement /= 8;
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
pFunc = GetMono1BitLineFull; pFunc = GetMono1BitLineFull;
else else
pFunc = GetMono1BitLineHalf; pFunc = GetMono1BitLineHalf;
@ -1059,8 +1040,8 @@ MustScanner_ScanSuggest (TARGETIMAGE * pTarget)
DBG (DBG_FUNC, "MustScanner_ScanSuggest: call in\n"); DBG (DBG_FUNC, "MustScanner_ScanSuggest: call in\n");
/* check width and height */ /* check width and height */
wMaxWidth = (MAX_SCANNING_WIDTH * pTarget->wDpi) / 300; wMaxWidth = (MAX_SCANNING_WIDTH * pTarget->wXDpi) / 300;
wMaxHeight = (MAX_SCANNING_HEIGHT * pTarget->wDpi) / 300; wMaxHeight = (MAX_SCANNING_HEIGHT * pTarget->wYDpi) / 300;
DBG (DBG_FUNC, "MustScanner_ScanSuggest: wMaxWidth = %d\n", wMaxWidth); DBG (DBG_FUNC, "MustScanner_ScanSuggest: wMaxWidth = %d\n", wMaxWidth);
DBG (DBG_FUNC, "MustScanner_ScanSuggest: wMaxHeight = %d\n", wMaxHeight); DBG (DBG_FUNC, "MustScanner_ScanSuggest: wMaxHeight = %d\n", wMaxHeight);
@ -1068,27 +1049,6 @@ MustScanner_ScanSuggest (TARGETIMAGE * pTarget)
pTarget->wWidth = _MIN (pTarget->wWidth, wMaxWidth); pTarget->wWidth = _MIN (pTarget->wWidth, wMaxWidth);
pTarget->wHeight = _MIN (pTarget->wHeight, wMaxHeight); pTarget->wHeight = _MIN (pTarget->wHeight, wMaxHeight);
switch (pTarget->cmColorMode)
{
case CM_RGB48:
pTarget->dwBytesPerRow = (unsigned int) pTarget->wWidth * 6;
break;
case CM_RGB24:
pTarget->dwBytesPerRow = (unsigned int) pTarget->wWidth * 3;
break;
case CM_GRAY16:
pTarget->dwBytesPerRow = (unsigned int) pTarget->wWidth * 2;
break;
case CM_GRAY8:
pTarget->dwBytesPerRow = (unsigned int) pTarget->wWidth;
break;
case CM_TEXT:
pTarget->dwBytesPerRow = (unsigned int) pTarget->wWidth / 8;
break;
}
DBG (DBG_FUNC, "MustScanner_ScanSuggest: pTarget->dwBytesPerRow = %d\n",
pTarget->dwBytesPerRow);
DBG (DBG_FUNC, "MustScanner_ScanSuggest: leave MustScanner_ScanSuggest\n"); DBG (DBG_FUNC, "MustScanner_ScanSuggest: leave MustScanner_ScanSuggest\n");
} }
@ -1146,7 +1106,7 @@ MustScanner_PrepareScan (void)
g_wScanLinesPerBlock) * g_wScanLinesPerBlock; g_wScanLinesPerBlock) * g_wScanLinesPerBlock;
g_dwScannedTotalLines = 0; g_dwScannedTotalLines = 0;
switch (g_ScanMode) switch (g_Target.cmColorMode)
{ {
case CM_RGB48: case CM_RGB48:
case CM_RGB24: case CM_RGB24:
@ -1201,90 +1161,96 @@ MustScanner_Reset (void)
} }
static void static void
MustScanner_PrepareCalculateMaxMin (unsigned short wResolution) MustScanner_PrepareCalculateMaxMin (unsigned short wResolution,
CALIBRATIONPARAM * pCalParam)
{ {
g_wDarkCalWidth = 52; unsigned short wCalWidth, wDarkCalWidth;
wDarkCalWidth = 52;
if (wResolution <= (SENSOR_DPI / 2)) if (wResolution <= (SENSOR_DPI / 2))
{ {
g_wCalWidth = (5120 * wResolution / (SENSOR_DPI / 2) + 511) & ~511; wCalWidth = (5120 * wResolution / (SENSOR_DPI / 2) + 511) & ~511;
g_wDarkCalWidth *= wResolution / SENSOR_DPI; wDarkCalWidth *= wResolution / SENSOR_DPI;
if (wResolution < 200) if (wResolution < 200)
{ {
g_nPowerNum = 3; pCalParam->nPowerNum = 3;
g_nSecLength = 8; /* 2^nPowerNum */ pCalParam->nSecLength = 8; /* 2^nPowerNum */
/* dark has at least 2 sections */ /* dark has at least 2 sections */
g_nDarkSecLength = g_wDarkCalWidth / 2; pCalParam->nDarkSecLength = wDarkCalWidth / 2;
} }
else else
{ {
g_nPowerNum = 6; pCalParam->nPowerNum = 6;
g_nSecLength = 64; /* 2^nPowerNum */ pCalParam->nSecLength = 64; /* 2^nPowerNum */
g_nDarkSecLength = g_wDarkCalWidth / 3; pCalParam->nDarkSecLength = wDarkCalWidth / 3;
} }
} }
else else
{ {
g_nPowerNum = 6; pCalParam->nPowerNum = 6;
g_nSecLength = 64; /* 2^nPowerNum */ pCalParam->nSecLength = 64; /* 2^nPowerNum */
g_wCalWidth = 10240; wCalWidth = 10240;
g_nDarkSecLength = g_wDarkCalWidth / 5; pCalParam->nDarkSecLength = wDarkCalWidth / 5;
} }
if (g_nDarkSecLength <= 0) if (pCalParam->nDarkSecLength <= 0)
g_nDarkSecLength = 1; pCalParam->nDarkSecLength = 1;
g_wStartPosition = 13 * wResolution / SENSOR_DPI; pCalParam->wStartPosition = 13 * wResolution / SENSOR_DPI;
g_wCalWidth -= g_wStartPosition; wCalWidth -= pCalParam->wStartPosition;
/* start of find max value */ /* start of find max value */
g_nSecNum = (int) (g_wCalWidth / g_nSecLength); pCalParam->nSecNum = wCalWidth / pCalParam->nSecLength;
/* start of find min value */ /* start of find min value */
g_nDarkSecNum = (int) (g_wDarkCalWidth / g_nDarkSecLength); pCalParam->nDarkSecNum = wDarkCalWidth / pCalParam->nDarkSecLength;
} }
static SANE_Bool static SANE_Bool
MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * pMaxValue, MustScanner_CalculateMaxMin (CALIBRATIONPARAM * pCalParam, SANE_Byte * pBuffer,
unsigned short * pMaxValue,
unsigned short * pMinValue) unsigned short * pMinValue)
{ {
unsigned short *wSecData, *wDarkSecData; unsigned short *wSecData, *wDarkSecData;
int i, j; int i, j;
wSecData = malloc (g_nSecNum * sizeof (unsigned short)); wSecData = malloc (pCalParam->nSecNum * sizeof (unsigned short));
if (!wSecData) if (!wSecData)
return SANE_FALSE; return SANE_FALSE;
memset (wSecData, 0, g_nSecNum * sizeof (unsigned short)); memset (wSecData, 0, pCalParam->nSecNum * sizeof (unsigned short));
for (i = 0; i < g_nSecNum; i++) for (i = 0; i < pCalParam->nSecNum; i++)
{ {
for (j = 0; j < g_nSecLength; j++) for (j = 0; j < pCalParam->nSecLength; j++)
wSecData[i] += pBuffer[g_wStartPosition + i * g_nSecLength + j]; wSecData[i] += pBuffer[pCalParam->wStartPosition +
wSecData[i] >>= g_nPowerNum; i * pCalParam->nSecLength + j];
wSecData[i] >>= pCalParam->nPowerNum;
} }
*pMaxValue = wSecData[0]; *pMaxValue = wSecData[0];
for (i = 0; i < g_nSecNum; i++) for (i = 0; i < pCalParam->nSecNum; i++)
{ {
if (*pMaxValue < wSecData[i]) if (*pMaxValue < wSecData[i])
*pMaxValue = wSecData[i]; *pMaxValue = wSecData[i];
} }
free (wSecData); free (wSecData);
wDarkSecData = malloc (g_nDarkSecNum * sizeof (unsigned short)); wDarkSecData = malloc (pCalParam->nDarkSecNum * sizeof (unsigned short));
if (!wDarkSecData) if (!wDarkSecData)
return SANE_FALSE; return SANE_FALSE;
memset (wDarkSecData, 0, g_nDarkSecNum * sizeof (unsigned short)); memset (wDarkSecData, 0, pCalParam->nDarkSecNum * sizeof (unsigned short));
for (i = 0; i < g_nDarkSecNum; i++) for (i = 0; i < pCalParam->nDarkSecNum; i++)
{ {
for (j = 0; j < g_nDarkSecLength; j++) for (j = 0; j < pCalParam->nDarkSecLength; j++)
wDarkSecData[i] += pBuffer[g_wStartPosition + i * g_nDarkSecLength + j]; wDarkSecData[i] += pBuffer[pCalParam->wStartPosition +
wDarkSecData[i] /= g_nDarkSecLength; i * pCalParam->nDarkSecLength + j];
wDarkSecData[i] /= pCalParam->nDarkSecLength;
} }
*pMinValue = wDarkSecData[0]; *pMinValue = wDarkSecData[0];
for (i = 0; i < g_nDarkSecNum; i++) for (i = 0; i < pCalParam->nDarkSecNum; i++)
{ {
if (*pMinValue > wDarkSecData[i]) if (*pMinValue > wDarkSecData[i])
*pMinValue = wDarkSecData[i]; *pMinValue = wDarkSecData[i];
@ -1297,6 +1263,7 @@ MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * pMaxValue,
static SANE_Bool static SANE_Bool
MustScanner_AdjustAD (void) MustScanner_AdjustAD (void)
{ {
CALIBRATIONPARAM calParam;
SANE_Byte * pCalData; SANE_Byte * pCalData;
unsigned short wCalWidth; unsigned short wCalWidth;
unsigned short wMaxValue[3], wMinValue[3]; unsigned short wMaxValue[3], wMinValue[3];
@ -1321,7 +1288,7 @@ MustScanner_AdjustAD (void)
g_chip.AD.Direction[i] = DIR_POSITIVE; g_chip.AD.Direction[i] = DIR_POSITIVE;
g_chip.AD.Gain[i] = 0; g_chip.AD.Gain[i] = 0;
} }
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
g_chip.AD.Offset[0] = 152; /* red */ g_chip.AD.Offset[0] = 152; /* red */
g_chip.AD.Offset[1] = 56; /* green */ g_chip.AD.Offset[1] = 56; /* green */
@ -1334,7 +1301,7 @@ MustScanner_AdjustAD (void)
g_chip.AD.Offset[2] = 45; g_chip.AD.Offset[2] = 45;
} }
if (g_XDpi <= (SENSOR_DPI / 2)) if (g_Target.wXDpi <= (SENSOR_DPI / 2))
wAdjustADResolution = SENSOR_DPI / 2; wAdjustADResolution = SENSOR_DPI / 2;
else else
wAdjustADResolution = SENSOR_DPI; wAdjustADResolution = SENSOR_DPI;
@ -1347,11 +1314,11 @@ MustScanner_AdjustAD (void)
return SANE_FALSE; return SANE_FALSE;
} }
if (Asic_SetWindow (&g_chip, g_ssScanSource, SCAN_TYPE_CALIBRATE_DARK, 24, if (Asic_SetWindow (&g_chip, g_Target.ssScanSource, SCAN_TYPE_CALIBRATE_DARK,
wAdjustADResolution, wAdjustADResolution, 0, 0, 24, wAdjustADResolution, wAdjustADResolution, 0, 0,
wCalWidth, 1) != SANE_STATUS_GOOD) wCalWidth, 1) != SANE_STATUS_GOOD)
goto error; goto error;
MustScanner_PrepareCalculateMaxMin (wAdjustADResolution); MustScanner_PrepareCalculateMaxMin (wAdjustADResolution, &calParam);
for (i = 0; i < 10; i++) for (i = 0; i < 10; i++)
{ {
@ -1378,7 +1345,8 @@ MustScanner_AdjustAD (void)
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++)
{ {
if (!MustScanner_CalculateMaxMin (pCalData + (wCalWidth * j), if (!MustScanner_CalculateMaxMin (&calParam,
pCalData + (wCalWidth * j),
&wMaxValue[j], &wMinValue[j])) &wMaxValue[j], &wMinValue[j]))
goto error; goto error;
@ -1440,7 +1408,8 @@ MustScanner_AdjustAD (void)
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++)
{ {
if (!MustScanner_CalculateMaxMin (pCalData + (wCalWidth * j), if (!MustScanner_CalculateMaxMin (&calParam,
pCalData + (wCalWidth * j),
&wMaxValue[j], &wMinValue[j])) &wMaxValue[j], &wMinValue[j]))
goto error; goto error;
@ -1507,7 +1476,8 @@ MustScanner_AdjustAD (void)
for (j = 0; j < 3; j++) for (j = 0; j < 3; j++)
{ {
if (!MustScanner_CalculateMaxMin (pCalData + (wCalWidth * j), if (!MustScanner_CalculateMaxMin (&calParam,
pCalData + (wCalWidth * j),
&wMaxValue[j], &wMinValue[j])) &wMaxValue[j], &wMinValue[j]))
goto error; goto error;
@ -1579,7 +1549,7 @@ MustScanner_FindTopLeft (unsigned short * pwStartX, unsigned short * pwStartY)
return SANE_FALSE; return SANE_FALSE;
} }
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
wCalWidth = FIND_LEFT_TOP_WIDTH_IN_DIP; wCalWidth = FIND_LEFT_TOP_WIDTH_IN_DIP;
wCalHeight = FIND_LEFT_TOP_HEIGHT_IN_DIP; wCalHeight = FIND_LEFT_TOP_HEIGHT_IN_DIP;
@ -1599,8 +1569,8 @@ MustScanner_FindTopLeft (unsigned short * pwStartX, unsigned short * pwStartY)
} }
nScanBlock = dwTotalSize / CALIBRATION_BLOCK_SIZE; nScanBlock = dwTotalSize / CALIBRATION_BLOCK_SIZE;
if (Asic_SetWindow (&g_chip, g_ssScanSource, SCAN_TYPE_CALIBRATE_LIGHT, 8, if (Asic_SetWindow (&g_chip, g_Target.ssScanSource, SCAN_TYPE_CALIBRATE_LIGHT,
FIND_LEFT_TOP_CALIBRATE_RESOLUTION, 8, FIND_LEFT_TOP_CALIBRATE_RESOLUTION,
FIND_LEFT_TOP_CALIBRATE_RESOLUTION, 0, 0, FIND_LEFT_TOP_CALIBRATE_RESOLUTION, 0, 0,
wCalWidth, wCalHeight) != SANE_STATUS_GOOD) wCalWidth, wCalHeight) != SANE_STATUS_GOOD)
goto error; goto error;
@ -1652,7 +1622,7 @@ MustScanner_FindTopLeft (unsigned short * pwStartX, unsigned short * pwStartY)
} }
} }
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
/* find top side, i = left side */ /* find top side, i = left side */
for (j = 0; j < wCalHeight; j++) for (j = 0; j < wCalHeight; j++)
@ -1781,7 +1751,7 @@ MustScanner_LineCalibration16Bits (void)
return SANE_FALSE; return SANE_FALSE;
} }
wCalWidth = g_Width; wCalWidth = g_Target.wWidth;
wCalHeight = LINE_CALIBRATION_HEIGHT; wCalHeight = LINE_CALIBRATION_HEIGHT;
dwTotalSize = wCalWidth * wCalHeight * 3 * 2; dwTotalSize = wCalWidth * wCalHeight * 3 * 2;
DBG (DBG_FUNC, "MustScanner_LineCalibration16Bits: wCalWidth = %d, " \ DBG (DBG_FUNC, "MustScanner_LineCalibration16Bits: wCalWidth = %d, " \
@ -1797,9 +1767,9 @@ MustScanner_LineCalibration16Bits (void)
/* read white level data */ /* read white level data */
SetAFEGainOffset (&g_chip); SetAFEGainOffset (&g_chip);
if (Asic_SetWindow (&g_chip, g_ssScanSource, SCAN_TYPE_CALIBRATE_LIGHT, 48, if (Asic_SetWindow (&g_chip, g_Target.ssScanSource, SCAN_TYPE_CALIBRATE_LIGHT,
g_XDpi, 600, g_X, 0, wCalWidth, wCalHeight) != 48, g_Target.wXDpi, 600, g_Target.wX, 0,
SANE_STATUS_GOOD) wCalWidth, wCalHeight) != SANE_STATUS_GOOD)
goto error; goto error;
if (Asic_ScanStart (&g_chip) != SANE_STATUS_GOOD) if (Asic_ScanStart (&g_chip) != SANE_STATUS_GOOD)
@ -1814,12 +1784,12 @@ MustScanner_LineCalibration16Bits (void)
/* read dark level data */ /* read dark level data */
SetAFEGainOffset (&g_chip); SetAFEGainOffset (&g_chip);
if (Asic_SetWindow (&g_chip, g_ssScanSource, SCAN_TYPE_CALIBRATE_DARK, 48, if (Asic_SetWindow (&g_chip, g_Target.ssScanSource, SCAN_TYPE_CALIBRATE_DARK,
g_XDpi, 600, g_X, 0, wCalWidth, wCalHeight) != 48, g_Target.wXDpi, 600, g_Target.wX, 0, wCalWidth,
SANE_STATUS_GOOD) wCalHeight) != SANE_STATUS_GOOD)
goto error; goto error;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
if (Asic_TurnLamp (&g_chip, SANE_FALSE) != SANE_STATUS_GOOD) if (Asic_TurnLamp (&g_chip, SANE_FALSE) != SANE_STATUS_GOOD)
goto error; goto error;
@ -1842,7 +1812,7 @@ MustScanner_LineCalibration16Bits (void)
if (Asic_ScanStop (&g_chip) != SANE_STATUS_GOOD) if (Asic_ScanStop (&g_chip) != SANE_STATUS_GOOD)
goto error; goto error;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
if (Asic_TurnLamp (&g_chip, SANE_TRUE) != SANE_STATUS_GOOD) if (Asic_TurnLamp (&g_chip, SANE_TRUE) != SANE_STATUS_GOOD)
goto error; goto error;
@ -1903,7 +1873,7 @@ MustScanner_LineCalibration16Bits (void)
} }
/* sum of dark level for all pixels */ /* sum of dark level for all pixels */
if ((g_XDpi == SENSOR_DPI) && ((i % 2) == 0)) if ((g_Target.wXDpi == SENSOR_DPI) && ((i % 2) == 0))
{ {
/* compute dark shading table with mean */ /* compute dark shading table with mean */
dwREvenDarkLevel += MustScanner_FiltLower (pRDarkSort, wCalHeight, dwREvenDarkLevel += MustScanner_FiltLower (pRDarkSort, wCalHeight,
@ -1924,7 +1894,7 @@ MustScanner_LineCalibration16Bits (void)
} }
} }
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
{ {
dwRDarkLevel /= wCalWidth / 2; dwRDarkLevel /= wCalWidth / 2;
dwGDarkLevel /= wCalWidth / 2; dwGDarkLevel /= wCalWidth / 2;
@ -1939,7 +1909,7 @@ MustScanner_LineCalibration16Bits (void)
dwGDarkLevel /= wCalWidth; dwGDarkLevel /= wCalWidth;
dwBDarkLevel /= wCalWidth; dwBDarkLevel /= wCalWidth;
} }
if (g_ssScanSource != SS_REFLECTIVE) if (g_Target.ssScanSource != SS_REFLECTIVE)
{ {
dwRDarkLevel -= 512; dwRDarkLevel -= 512;
dwGDarkLevel -= 512; dwGDarkLevel -= 512;
@ -1964,11 +1934,11 @@ MustScanner_LineCalibration16Bits (void)
pBWhiteSort[j] += pWhiteData[j * wCalWidth * 2 * 3 + i * 6 + 5] << 8; pBWhiteSort[j] += pWhiteData[j * wCalWidth * 2 * 3 + i * 6 + 5] << 8;
} }
if ((g_XDpi == SENSOR_DPI) && ((i % 2) == 0)) if ((g_Target.wXDpi == SENSOR_DPI) && ((i % 2) == 0))
{ {
pDarkShading[i * 3] = dwREvenDarkLevel; pDarkShading[i * 3] = dwREvenDarkLevel;
pDarkShading[i * 3 + 1] = dwGEvenDarkLevel; pDarkShading[i * 3 + 1] = dwGEvenDarkLevel;
if (g_ssScanSource == SS_POSITIVE) if (g_Target.ssScanSource == SS_POSITIVE)
pDarkShading[i * 3 + 1] *= 0.78; pDarkShading[i * 3 + 1] *= 0.78;
pDarkShading[i * 3 + 2] = dwBEvenDarkLevel; pDarkShading[i * 3 + 2] = dwBEvenDarkLevel;
} }
@ -1976,7 +1946,7 @@ MustScanner_LineCalibration16Bits (void)
{ {
pDarkShading[i * 3] = dwRDarkLevel; pDarkShading[i * 3] = dwRDarkLevel;
pDarkShading[i * 3 + 1] = dwGDarkLevel; pDarkShading[i * 3 + 1] = dwGDarkLevel;
if (g_ssScanSource == SS_POSITIVE) if (g_Target.ssScanSource == SS_POSITIVE)
pDarkShading[i * 3 + 1] *= 0.78; pDarkShading[i * 3 + 1] *= 0.78;
pDarkShading[i * 3 + 2] = dwBDarkLevel; pDarkShading[i * 3 + 2] = dwBDarkLevel;
} }
@ -1988,7 +1958,7 @@ MustScanner_LineCalibration16Bits (void)
wBWhiteLevel = MustScanner_FiltLower (pBWhiteSort, wCalHeight, 20, 30) - wBWhiteLevel = MustScanner_FiltLower (pBWhiteSort, wCalHeight, 20, 30) -
pDarkShading[i * 3 + 2]; pDarkShading[i * 3 + 2];
switch (g_ssScanSource) switch (g_Target.ssScanSource)
{ {
case SS_REFLECTIVE: case SS_REFLECTIVE:
if (wRWhiteLevel > 0) if (wRWhiteLevel > 0)
@ -2059,8 +2029,8 @@ MustScanner_LineCalibration16Bits (void)
free (pGDarkSort); free (pGDarkSort);
free (pBDarkSort); free (pBDarkSort);
if (Asic_SetShadingTable (&g_chip, pWhiteShading, pDarkShading, g_XDpi, if (Asic_SetShadingTable (&g_chip, pWhiteShading, pDarkShading,
wCalWidth) != SANE_STATUS_GOOD) g_Target.wXDpi, wCalWidth) != SANE_STATUS_GOOD)
goto error; /* TODO: memory leak */ goto error; /* TODO: memory leak */
free (pWhiteShading); free (pWhiteShading);
@ -2081,7 +2051,7 @@ error:
SANE_Bool SANE_Bool
MustScanner_SetupScan (TARGETIMAGE * pTarget) MustScanner_SetupScan (TARGETIMAGE * pTarget)
{ {
unsigned short targetY; unsigned short finalY;
SANE_Byte bScanBits; SANE_Byte bScanBits;
DBG (DBG_FUNC, "MustScanner_SetupScan: call in\n"); DBG (DBG_FUNC, "MustScanner_SetupScan: call in\n");
@ -2092,19 +2062,16 @@ MustScanner_SetupScan (TARGETIMAGE * pTarget)
return SANE_FALSE; return SANE_FALSE;
} }
g_ScanMode = pTarget->cmColorMode; g_Target = *pTarget;
g_XDpi = pTarget->wDpi; g_SWWidth = g_Target.wWidth;
g_YDpi = pTarget->wDpi; g_SWHeight = g_Target.wHeight;
g_Width = (pTarget->wWidth + 15) & ~15; /* real scan width */ /* set real scan width according to ASIC limit: width must be 8x */
g_Height = pTarget->wHeight; g_Target.wWidth = (g_Target.wWidth + 15) & ~15;
g_SWWidth = pTarget->wWidth;
g_SWHeight = pTarget->wHeight;
g_wLineartThreshold = pTarget->wLineartThreshold;
g_ssScanSource = pTarget->ssScanSource;
/* create gamma table */ /* create gamma table */
if ((pTarget->cmColorMode == CM_GRAY8) || /* TODO: move into separate function */
(pTarget->cmColorMode == CM_RGB24)) if ((g_Target.cmColorMode == CM_GRAY8) ||
(g_Target.cmColorMode == CM_RGB24))
{ {
unsigned short i; unsigned short i;
SANE_Byte bGammaData; SANE_Byte bGammaData;
@ -2124,8 +2091,8 @@ MustScanner_SetupScan (TARGETIMAGE * pTarget)
g_pGammaTable[i + 8192] = bGammaData; g_pGammaTable[i + 8192] = bGammaData;
} }
} }
else if ((pTarget->cmColorMode == CM_GRAY16) || else if ((g_Target.cmColorMode == CM_GRAY16) ||
(pTarget->cmColorMode == CM_RGB48)) (g_Target.cmColorMode == CM_RGB48))
{ {
unsigned int i; unsigned int i;
unsigned short wGammaData; unsigned short wGammaData;
@ -2152,12 +2119,12 @@ MustScanner_SetupScan (TARGETIMAGE * pTarget)
g_pGammaTable = NULL; g_pGammaTable = NULL;
} }
switch (g_YDpi) switch (g_Target.wYDpi)
{ {
case 1200: case 1200:
g_wPixelDistance = 4; /* even & odd sensor problem */ g_wPixelDistance = 4; /* even & odd sensor problem */
g_wLineDistance = 24; g_wLineDistance = 24;
g_Height += g_wPixelDistance; g_Target.wHeight += g_wPixelDistance;
break; break;
case 600: case 600:
g_wPixelDistance = 0; /* no even & odd problem */ g_wPixelDistance = 0; /* no even & odd problem */
@ -2181,41 +2148,41 @@ MustScanner_SetupScan (TARGETIMAGE * pTarget)
g_wLineDistance = 0; g_wLineDistance = 0;
} }
DBG (DBG_FUNC, "MustScanner_SetupScan: g_YDpi=%d\n", g_YDpi); DBG (DBG_FUNC, "MustScanner_SetupScan: wYDpi=%d\n", g_Target.wYDpi);
DBG (DBG_FUNC, "MustScanner_SetupScan: g_wLineDistance=%d\n", DBG (DBG_FUNC, "MustScanner_SetupScan: g_wLineDistance=%d\n",
g_wLineDistance); g_wLineDistance);
DBG (DBG_FUNC, "MustScanner_SetupScan: g_wPixelDistance=%d\n", DBG (DBG_FUNC, "MustScanner_SetupScan: g_wPixelDistance=%d\n",
g_wPixelDistance); g_wPixelDistance);
switch (g_ScanMode) switch (g_Target.cmColorMode)
{ {
case CM_RGB48: case CM_RGB48:
g_BytesPerRow = 6 * g_Width; /* ASIC limit: width must be 8x */ g_BytesPerRow = 6 * g_Target.wWidth;
g_SWBytesPerRow = 6 * g_SWWidth; /* ASIC limit: width must be 8x */ g_SWBytesPerRow = 6 * g_SWWidth;
g_Height += g_wLineDistance * 2; g_Target.wHeight += g_wLineDistance * 2;
bScanBits = 48; bScanBits = 48;
break; break;
case CM_RGB24: case CM_RGB24:
g_BytesPerRow = 3 * g_Width; g_BytesPerRow = 3 * g_Target.wWidth;
g_SWBytesPerRow = 3 * g_SWWidth; g_SWBytesPerRow = 3 * g_SWWidth;
g_Height += g_wLineDistance * 2; g_Target.wHeight += g_wLineDistance * 2;
bScanBits = 24; bScanBits = 24;
break; break;
case CM_GRAY16: case CM_GRAY16:
g_BytesPerRow = 2 * g_Width; g_BytesPerRow = 2 * g_Target.wWidth;
g_SWBytesPerRow = 2 * g_SWWidth; g_SWBytesPerRow = 2 * g_SWWidth;
bScanBits = 16; bScanBits = 16;
break; break;
case CM_GRAY8: case CM_GRAY8:
case CM_TEXT: case CM_TEXT:
default: default:
g_BytesPerRow = g_Width; g_BytesPerRow = g_Target.wWidth;
g_SWBytesPerRow = g_SWWidth; g_SWBytesPerRow = g_SWWidth;
bScanBits = 8; bScanBits = 8;
break; break;
} }
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
if (!MustScanner_PowerControl (SANE_TRUE, SANE_FALSE)) if (!MustScanner_PowerControl (SANE_TRUE, SANE_FALSE))
return SANE_FALSE; return SANE_FALSE;
@ -2232,97 +2199,103 @@ MustScanner_SetupScan (TARGETIMAGE * pTarget)
g_bOpened = SANE_TRUE; g_bOpened = SANE_TRUE;
/* find left & top side */ /* find left & top side */
if (g_ssScanSource != SS_REFLECTIVE) if (g_Target.ssScanSource != SS_REFLECTIVE)
if (Asic_MotorMove (&g_chip, SANE_TRUE, TRAN_START_POS) != SANE_STATUS_GOOD) if (Asic_MotorMove (&g_chip, SANE_TRUE, TRAN_START_POS) != SANE_STATUS_GOOD)
return SANE_FALSE; return SANE_FALSE;
if (g_XDpi == SENSOR_DPI) if (g_Target.wXDpi == SENSOR_DPI)
{ {
g_XDpi = SENSOR_DPI / 2; g_Target.wXDpi = SENSOR_DPI / 2;
if (!MustScanner_AdjustAD ()) if (!MustScanner_AdjustAD ())
return SANE_FALSE; return SANE_FALSE;
if (!MustScanner_FindTopLeft (&g_X, &g_Y)) if (!MustScanner_FindTopLeft (&g_Target.wX, &g_Target.wY))
{ {
g_X = 187; g_Target.wX = 187;
g_Y = 43; g_Target.wY = 43;
} }
g_XDpi = SENSOR_DPI; g_Target.wXDpi = SENSOR_DPI;
if (!MustScanner_AdjustAD ()) if (!MustScanner_AdjustAD ())
return SANE_FALSE; return SANE_FALSE;
g_X = g_X * SENSOR_DPI / FIND_LEFT_TOP_CALIBRATE_RESOLUTION + pTarget->wX; g_Target.wX = g_Target.wX * SENSOR_DPI /
if (g_ssScanSource == SS_REFLECTIVE) FIND_LEFT_TOP_CALIBRATE_RESOLUTION + pTarget->wX;
if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
g_X += 47; g_Target.wX += 47;
g_Y = g_Y * SENSOR_DPI / FIND_LEFT_TOP_CALIBRATE_RESOLUTION + g_Target.wY = g_Target.wY * SENSOR_DPI /
pTarget->wY * SENSOR_DPI / g_YDpi + 47; FIND_LEFT_TOP_CALIBRATE_RESOLUTION +
pTarget->wY * SENSOR_DPI / g_Target.wYDpi + 47;
} }
} }
else else
{ {
if (!MustScanner_AdjustAD ()) if (!MustScanner_AdjustAD ())
return SANE_FALSE; return SANE_FALSE;
if (!MustScanner_FindTopLeft (&g_X, &g_Y)) if (!MustScanner_FindTopLeft (&g_Target.wX, &g_Target.wY))
{ {
g_X = 187; g_Target.wX = 187;
g_Y = 43; g_Target.wY = 43;
} }
g_X += pTarget->wX * (SENSOR_DPI / 2) / g_XDpi; g_Target.wX += pTarget->wX * (SENSOR_DPI / 2) / g_Target.wXDpi;
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
if (g_XDpi != 75) if (g_Target.wXDpi != 75)
g_X += 23; g_Target.wX += 23;
g_Y = g_Y * SENSOR_DPI / FIND_LEFT_TOP_CALIBRATE_RESOLUTION + g_Target.wY = g_Target.wY * SENSOR_DPI /
pTarget->wY * SENSOR_DPI / g_YDpi + 47; FIND_LEFT_TOP_CALIBRATE_RESOLUTION +
pTarget->wY * SENSOR_DPI / g_Target.wYDpi + 47;
} }
else else
{ {
if (g_XDpi == 75) if (g_Target.wXDpi == 75)
g_X -= 23; g_Target.wX -= 23;
} }
} }
DBG (DBG_FUNC, "MustScanner_SetupScan: before line calibration g_X=%d," \ DBG (DBG_FUNC, "MustScanner_SetupScan: before line calibration wX=%d," \
"g_Y=%d\n", g_X, g_Y); "wY=%d\n", g_Target.wX, g_Target.wY);
if (!MustScanner_LineCalibration16Bits ()) if (!MustScanner_LineCalibration16Bits ())
return SANE_FALSE; return SANE_FALSE;
DBG (DBG_FUNC, "MustScanner_SetupScan: after " \ DBG (DBG_FUNC, "MustScanner_SetupScan: after " \
"MustScanner_LineCalibration16Bits g_X=%d,g_Y=%d\n", g_X, g_Y); "MustScanner_LineCalibration16Bits wX=%d,wY=%d\n",
g_Target.wX, g_Target.wY);
DBG (DBG_FUNC, "MustScanner_SetupScan: bScanBits=%d, g_XDpi=%d, " \ DBG (DBG_FUNC, "MustScanner_SetupScan: bScanBits=%d, wXDpi=%d, " \
"g_YDpi=%d, g_X=%d, g_Y=%d, g_Width=%d, g_Height=%d\n", "wYDpi=%d, wX=%d, wY=%d, wWidth=%d, wHeight=%d\n",
bScanBits, g_XDpi, g_YDpi, g_X, g_Y, g_Width, g_Height); bScanBits, g_Target.wXDpi, g_Target.wYDpi, g_Target.wX, g_Target.wY,
g_Target.wWidth, g_Target.wHeight);
if (g_ssScanSource == SS_REFLECTIVE) if (g_Target.ssScanSource == SS_REFLECTIVE)
{ {
targetY = 300; finalY = 300;
} }
else else
{ {
g_Y = pTarget->wY * SENSOR_DPI / g_YDpi + (300 - 40) + 189; g_Target.wY = pTarget->wY * SENSOR_DPI / g_Target.wYDpi + (300 - 40) +189;
targetY = 360; finalY = 360;
} }
if (g_Y > targetY) if (g_Target.wY > finalY)
{ {
if (Asic_MotorMove (&g_chip, SANE_TRUE, g_Y - targetY) != if (Asic_MotorMove (&g_chip, SANE_TRUE, g_Target.wY - finalY) !=
SANE_STATUS_GOOD) SANE_STATUS_GOOD)
return SANE_FALSE; return SANE_FALSE;
} }
else else
{ {
if (Asic_MotorMove (&g_chip, SANE_FALSE, targetY - g_Y) != if (Asic_MotorMove (&g_chip, SANE_FALSE, finalY - g_Target.wY) !=
SANE_STATUS_GOOD) SANE_STATUS_GOOD)
return SANE_FALSE; return SANE_FALSE;
} }
g_Y = targetY; g_Target.wY = finalY;
if (Asic_SetWindow (&g_chip, g_ssScanSource, SCAN_TYPE_NORMAL, bScanBits, if (Asic_SetWindow (&g_chip, g_Target.ssScanSource, SCAN_TYPE_NORMAL,
g_XDpi, g_YDpi, g_X, g_Y, g_Width, g_Height) != bScanBits, g_Target.wXDpi, g_Target.wYDpi, g_Target.wX,
g_Target.wY, g_Target.wWidth, g_Target.wHeight) !=
SANE_STATUS_GOOD) SANE_STATUS_GOOD)
return SANE_FALSE; return SANE_FALSE;

Wyświetl plik

@ -65,15 +65,23 @@ typedef struct
{ {
COLORMODE cmColorMode; COLORMODE cmColorMode;
SCANSOURCE ssScanSource; SCANSOURCE ssScanSource;
unsigned short wDpi; unsigned short wXDpi;
unsigned short wYDpi;
unsigned short wX; unsigned short wX;
unsigned short wY; unsigned short wY;
unsigned short wWidth; unsigned short wWidth;
unsigned short wHeight; unsigned short wHeight;
unsigned short wLineartThreshold; unsigned short wLineartThreshold;
unsigned int dwBytesPerRow;
} TARGETIMAGE; } TARGETIMAGE;
typedef struct
{
int nSecLength, nDarkSecLength;
int nSecNum, nDarkSecNum;
int nPowerNum;
unsigned short wStartPosition;
} CALIBRATIONPARAM;
#define _MAX(a,b) ((a)>(b)?(a):(b)) #define _MAX(a,b) ((a)>(b)?(a):(b))
#define _MIN(a,b) ((a)<(b)?(a):(b)) #define _MIN(a,b) ((a)<(b)?(a):(b))