summaryrefslogtreecommitdiff
path: root/backend/mustek_usb2_high.c
diff options
context:
space:
mode:
Diffstat (limited to 'backend/mustek_usb2_high.c')
-rw-r--r--backend/mustek_usb2_high.c3240
1 files changed, 3240 insertions, 0 deletions
diff --git a/backend/mustek_usb2_high.c b/backend/mustek_usb2_high.c
new file mode 100644
index 0000000..a10dbc7
--- /dev/null
+++ b/backend/mustek_usb2_high.c
@@ -0,0 +1,3240 @@
+/* sane - Scanner Access Now Easy.
+
+ Copyright (C) 2005 Mustek.
+ Originally maintained by Mustek
+ Author:Jack Roy 2005.5.24
+
+ 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.
+
+ This file implements a SANE backend for the Mustek BearPaw 2448 TA Pro
+ and similar USB2 scanners. */
+
+#include <pthread.h> /* HOLD */
+#include <stdlib.h>
+
+/* local header files */
+#include "mustek_usb2_asic.c"
+
+#include "mustek_usb2_high.h"
+
+/* ******************++ spuicall_g.h ****************************/
+
+/*global variable HOLD: these should go to scanner structure */
+
+/*base type*/
+static SANE_Bool g_bOpened;
+static SANE_Bool g_bPrepared;
+static SANE_Bool g_isCanceled;
+static SANE_Bool g_bSharpen;
+static SANE_Bool g_bFirstReadImage;
+static SANE_Bool g_isScanning;
+static SANE_Bool g_isSelfGamma;
+
+static SANE_Byte g_bScanBits;
+static SANE_Byte *g_lpReadImageHead;
+
+static unsigned short s_wOpticalYDpi[] = { 1200, 600, 300, 150, 75, 0 };
+static unsigned short s_wOpticalXDpi[] = { 1200, 600, 300, 150, 75, 0 };
+static unsigned short g_X;
+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_SWHeight;
+static unsigned short g_wPixelDistance; /*even & odd sensor problem */
+static unsigned short g_wLineDistance;
+static unsigned short g_wScanLinesPerBlock;
+static unsigned short g_wReadedLines;
+static unsigned short g_wReadImageLines;
+static unsigned short g_wReadyShadingLine;
+static unsigned short g_wStartShadingLinePos;
+static unsigned short g_wLineartThreshold;
+
+static unsigned int g_wtheReadyLines;
+static unsigned int g_wMaxScanLines;
+static unsigned int g_dwScannedTotalLines;
+static unsigned int g_dwImageBufferSize;
+static unsigned int g_BytesPerRow;
+static unsigned int g_SWBytesPerRow;
+static unsigned int g_dwCalibrationSize;
+static unsigned int g_dwBufferSize;
+
+static unsigned int g_dwTotalTotalXferLines;
+
+static unsigned short *g_pGammaTable;
+static unsigned char *g_pDeviceFile;
+
+static pthread_t g_threadid_readimage;
+
+/*user define type*/
+static COLORMODE g_ScanMode;
+static TARGETIMAGE g_tiTarget;
+static SCANTYPE g_ScanType = ST_Reflective;
+static SCANSOURCE g_ssScanSource;
+static PIXELFLAVOR g_PixelFlavor;
+
+static SUGGESTSETTING g_ssSuggest;
+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_readyLinesMutex = PTHREAD_MUTEX_INITIALIZER;
+
+/*for modify the last point*/
+static SANE_Byte * g_lpBefLineImageData = NULL;
+static SANE_Bool g_bIsFirstReadBefData = TRUE;
+static unsigned int g_dwAlreadyGetLines = 0;
+
+/* forward declarations */
+static SANE_Bool MustScanner_Init (void);
+static SANE_Bool MustScanner_GetScannerState (void);
+static SANE_Bool MustScanner_PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn);
+static SANE_Bool MustScanner_BackHome (void);
+static SANE_Bool MustScanner_Prepare (SANE_Byte bScanSource);
+#ifdef SANE_UNUSED
+static SANE_Bool MustScanner_AdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset,
+ SANE_Byte * bLastMin, SANE_Byte * bLastOffset,
+ unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound,
+ SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel,
+ unsigned short wStdMaxLevel);
+static SANE_Bool MustScanner_SecondAdjustOffset (int nTimes, SANE_Bool * bDirection,
+ SANE_Byte * bOffset, SANE_Byte * bLastMin,
+ SANE_Byte * bLastOffset, unsigned short * wMinValue,
+ SANE_Byte * bOffsetUpperBound,
+ SANE_Byte * bOffsetLowerBound,
+ unsigned short wStdMinLevel, unsigned short wStdMaxLevel);
+#endif
+static unsigned short MustScanner_FiltLower (unsigned short * pSort, unsigned short TotalCount, unsigned short LowCount,
+ unsigned short HighCount);
+static SANE_Bool MustScanner_GetRgb48BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetRgb48BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetRgb24BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetRgb24BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetMono16BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetMono16BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetMono8BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetMono8BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetMono1BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static SANE_Bool MustScanner_GetMono1BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount);
+static void *MustScanner_ReadDataFromScanner (void * dummy);
+static void MustScanner_PrepareCalculateMaxMin (unsigned short wResolution);
+static void MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * lpMaxValue,
+ unsigned short * lpMinValue, unsigned short wResolution);
+
+static SANE_Byte QBET4 (SANE_Byte A, SANE_Byte B);
+static unsigned int GetScannedLines (void);
+static unsigned int GetReadyLines (void);
+static void AddScannedLines (unsigned short wAddLines);
+static void AddReadyLines (void);
+static void ModifyLinePoint (SANE_Byte * lpImageData,
+ SANE_Byte * lpImageDataBefore,
+ unsigned int dwBytesPerLine,
+ unsigned int dwLinesCount,
+ unsigned short wPixDistance, unsigned short wModPtCount);
+
+#include "mustek_usb2_reflective.c"
+#include "mustek_usb2_transparent.c"
+
+/**********************************************************************
+Author: Jack Date: 2005/05/13
+ Routine Description:
+Parameters:
+ none
+Return value:
+ if initialize the scanner success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_Init ()
+{
+ DBG (DBG_FUNC, "MustScanner_Init: Call in\n");
+
+ g_chip.firmwarestate = FS_NULL;
+ if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
+ {
+ DBG (DBG_FUNC, "MustScanner_Init: Asic_Open return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_Initialize (&g_chip))
+ {
+ DBG (DBG_FUNC, "MustScanner_Init: Asic_Initialize return error\n");
+ return FALSE;
+ }
+
+ g_dwImageBufferSize = 24L * 1024L * 1024L;
+ g_dwBufferSize = 64L * 1024L;
+ g_dwCalibrationSize = 64L * 1024L;
+ g_lpReadImageHead = NULL;
+
+ g_isCanceled = FALSE;
+ g_bFirstReadImage = TRUE;
+ g_bOpened = FALSE;
+ g_bPrepared = FALSE;
+ g_bSharpen = FALSE;
+
+ g_isScanning = FALSE;
+ g_isSelfGamma = FALSE;
+ g_pGammaTable = NULL;
+
+ if (NULL != g_pDeviceFile)
+ {
+ free (g_pDeviceFile);
+ g_pDeviceFile = NULL;
+ }
+
+ g_ssScanSource = SS_Reflective;
+ g_PixelFlavor = PF_BlackIs0;
+
+ Asic_Close (&g_chip);
+
+ DBG (DBG_FUNC, "MustScanner_Init: leave MustScanner_Init\n");
+
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/13
+Routine Description:
+ check the scanner connect status
+Parameters:
+ none
+Return value:
+ if scanner's status is OK
+ return TRUE
+ else
+ return FASLE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetScannerState ()
+{
+
+ if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
+ {
+ DBG (DBG_FUNC, "MustScanner_GetScannerState: Asic_Open return error\n");
+ return FALSE;
+ }
+ else
+ {
+ Asic_Close (&g_chip);
+ return TRUE;
+ }
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/13
+Routine Description:
+ Turn the lamp on or off
+Parameters:
+ isLampOn: turn the lamp on or off
+ isTALampOn: turn the TA lamp on or off
+Return value:
+ if operation success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_PowerControl (SANE_Bool isLampOn, SANE_Bool isTALampOn)
+{
+ SANE_Bool hasTA;
+ DBG (DBG_FUNC, "MustScanner_PowerControl: Call in\n");
+ if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
+ {
+ DBG (DBG_FUNC, "MustScanner_PowerControl: Asic_Open return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_TurnLamp (&g_chip, isLampOn))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_PowerControl: Asic_TurnLamp return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_IsTAConnected (&g_chip, &hasTA))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_PowerControl: Asic_IsTAConnected return error\n");
+ return FALSE;
+ }
+
+ if (hasTA)
+ {
+ if (STATUS_GOOD != Asic_TurnTA (&g_chip, isTALampOn))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_PowerControl: Asic_TurnTA return error\n");
+ return FALSE;
+ }
+ }
+
+ Asic_Close (&g_chip);
+
+ DBG (DBG_FUNC,
+ "MustScanner_PowerControl: leave MustScanner_PowerControl\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/13
+Routine Description:
+ Turn the carriage home
+Parameters:
+ none
+Return value:
+ if the operation success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_BackHome ()
+{
+ DBG (DBG_FUNC, "MustScanner_BackHome: call in \n");
+
+ if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
+ {
+ DBG (DBG_FUNC, "MustScanner_BackHome: Asic_Open return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_CarriageHome (&g_chip, FALSE))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_BackHome: Asic_CarriageHome return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_WaitUnitReady (&g_chip))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_BackHome: Asic_WaitUnitReady return error\n");
+ return FALSE;
+ }
+
+ Asic_Close (&g_chip);
+
+ DBG (DBG_FUNC, "MustScanner_BackHome: leave MustScanner_BackHome\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/13
+Routine Description:
+ prepare the scan image
+Parameters:
+ bScanSource: the scan source
+Return value:
+ if operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_Prepare (SANE_Byte bScanSource)
+{
+ DBG (DBG_FUNC, "MustScanner_Prepare: call in\n");
+
+ if (STATUS_GOOD != Asic_Open (&g_chip, g_pDeviceFile))
+
+
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare: Asic_Open return error\n");
+ return FALSE;
+ }
+ if (STATUS_GOOD != Asic_WaitUnitReady (&g_chip))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_Prepare: Asic_WaitUnitReady return error\n");
+ return FALSE;
+ }
+
+ if (SS_Reflective == bScanSource)
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Reflective\n");
+ if (STATUS_GOOD != Asic_TurnLamp (&g_chip, TRUE))
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnLamp return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_REFLECTIVE))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_Prepare: Asic_SetSource return error\n");
+ return FALSE;
+ }
+ }
+ else if (SS_Positive == bScanSource)
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Positive\n");
+ if (STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE))
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnTA return error\n");
+ return FALSE;
+ }
+ if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_POSITIVE))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_Prepare: Asic_SetSource return error\n");
+ return FALSE;
+ }
+ }
+ else if (SS_Negative == bScanSource)
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare:ScanSource is SS_Negative\n");
+
+ if (STATUS_GOOD != Asic_TurnTA (&g_chip, TRUE))
+ {
+ DBG (DBG_FUNC, "MustScanner_Prepare: Asic_TurnTA return error\n");
+ return FALSE;
+ }
+
+ if (STATUS_GOOD != Asic_SetSource (&g_chip, LS_NEGATIVE))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_Prepare: Asic_SetSource return error\n");
+ return FALSE;
+ }
+ DBG (DBG_FUNC, "MustScanner_Prepare: Asic_SetSource return good\n");
+ }
+
+ Asic_Close (&g_chip);
+ g_bPrepared = TRUE;
+
+ DBG (DBG_FUNC, "MustScanner_Prepare: leave MustScanner_Prepare\n");
+ return TRUE;
+}
+
+#ifdef SANE_UNUSED
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Adjuest the offset
+Parameters:
+ nTimes: Adjuest offset the times
+ bDirection: whether direction
+ bOffset: the data of offset
+ bLastMin: the last min data
+ bLastOffset: the last offset data
+ wMinValue: the min value of offset
+ bOffsetUpperBound: the upper bound of offset
+ bOffsetLowerBound: the lower bound of offset
+ wStdMinLevel: the min level of offset
+ wStdMaxLevel: the max level of offset
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_AdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset,
+ SANE_Byte * bLastMin, SANE_Byte * bLastOffset,
+ unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound,
+ SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel,
+ unsigned short wStdMaxLevel)
+{
+ if ((*wMinValue <= wStdMaxLevel) && (*wMinValue >= wStdMinLevel))
+ {
+ return TRUE;
+ }
+
+ if (nTimes == 0)
+ {
+ *bLastMin = LOSANE_Byte (*wMinValue);
+ *bLastOffset = *bOffset;
+
+ if (*wMinValue == 255)
+ {
+ *bOffset = 0;
+ }
+ else
+ {
+ *bOffset = 255;
+ }
+ }
+
+ if (nTimes == 1)
+ {
+ if (*wMinValue > *bLastMin)
+ {
+ if (*wMinValue > wStdMaxLevel && *bLastMin > wStdMaxLevel)
+ {
+ *bDirection = !(*bDirection);
+ return TRUE;
+ }
+
+ if (*wMinValue < wStdMinLevel && *bLastMin < wStdMinLevel)
+ return TRUE;
+ }
+
+ if (*wMinValue < *bLastMin)
+ {
+ if (*wMinValue < wStdMinLevel && *bLastMin < wStdMinLevel)
+ *bDirection = !(*bDirection);
+
+ if (*wMinValue > wStdMaxLevel && *bLastMin > wStdMaxLevel)
+ return TRUE;
+ }
+ }
+
+ if (nTimes > 1)
+ {
+ if (*wMinValue > *bLastMin)
+ {
+ SANE_Byte bTemp;
+
+ bTemp = *bOffset;
+
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+
+ if (nTimes > 2)
+ {
+ if (*wMinValue > wStdMaxLevel)
+ if (bDirection)
+ *bOffsetLowerBound = bTemp;
+ else
+ *bOffsetUpperBound = bTemp;
+
+
+ else if (bDirection)
+ *bOffsetUpperBound = bTemp;
+ else
+ *bOffsetLowerBound = bTemp;
+ }
+
+ *bLastOffset = bTemp;
+ *bLastMin = (SANE_Byte) * wMinValue;
+ }
+ else
+ {
+ SANE_Byte bTemp;
+
+ bTemp = *bOffset;
+
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+
+ if (nTimes > 2)
+ {
+ if (*wMinValue == *bLastMin)
+ {
+ if (*wMinValue > wStdMaxLevel)
+ {
+ if (!bDirection)
+ *bOffsetUpperBound = bTemp;
+ else
+ *bOffsetLowerBound = bTemp;
+ }
+ else
+ {
+ if (!bDirection)
+ *bOffsetLowerBound = bTemp;
+ else
+ *bOffsetUpperBound = bTemp;
+ }
+ }
+ else
+ {
+ if (*wMinValue > wStdMaxLevel)
+ {
+ if (bDirection)
+ *bOffsetUpperBound = bTemp;
+ else
+ *bOffsetLowerBound = bTemp;
+ }
+ else
+ {
+ if (bDirection)
+ *bOffsetLowerBound = bTemp;
+ else
+ *bOffsetUpperBound = bTemp;
+ }
+ }
+ }
+
+ *bLastOffset = bTemp;
+ *bLastMin = (SANE_Byte) * wMinValue;
+
+ }
+ } /* end of if(nTimes > 1) */
+
+ return TRUE;
+}
+#endif
+
+#ifdef SANE_UNUSED
+/**********************************************************************
+
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Adjuest the offset second times
+Parameters:
+ nTimes: Adjuest offset the times
+ bDirection: whether direction
+ bOffset: the data of offset
+ bLastMin: the last min data
+ bLastOffset: the last offset data
+ wMinValue: the min value of offset
+ bOffsetUpperBound: the upper bound of offset
+ bOffsetLowerBound: the lower bound of offset
+ wStdMinLevel: the min level of offset
+ wStdMaxLevel: the max level of offset
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_SecondAdjustOffset (int nTimes, SANE_Bool * bDirection, SANE_Byte * bOffset,
+ SANE_Byte * bLastMin, SANE_Byte * bLastOffset,
+ unsigned short * wMinValue, SANE_Byte * bOffsetUpperBound,
+ SANE_Byte * bOffsetLowerBound, unsigned short wStdMinLevel,
+ unsigned short wStdMaxLevel)
+{
+ if ((*wMinValue <= wStdMaxLevel) && (*wMinValue >= wStdMinLevel))
+ {
+ return TRUE;
+ }
+ if (nTimes == 0)
+ {
+ *bLastMin = LOSANE_Byte (*wMinValue);
+ *bLastOffset = *bOffset;
+
+ if (*bDirection == 0)
+ {
+ *bOffsetUpperBound = *bLastOffset;
+ *bOffsetLowerBound = 0;
+ *bOffset = 0;
+ }
+ else
+ {
+ *bOffsetUpperBound = 255;
+ *bOffsetLowerBound = *bLastOffset;
+ *bOffset = 255;
+ }
+ }
+
+ if (nTimes >= 1)
+ {
+ if (*wMinValue > wStdMaxLevel)
+ {
+ if (*wMinValue > *bLastMin)
+ {
+ if (*bDirection == 0)
+ {
+ *bOffsetUpperBound = *bOffset;
+ }
+ else
+ {
+ *bOffsetLowerBound = *bOffset;
+ }
+
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+ }
+ else
+ {
+ if (*bDirection == 1)
+ {
+ *bOffsetUpperBound = *bOffset;
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+ }
+ else
+ {
+ *bOffsetLowerBound = *bOffset;
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+ }
+ }
+ } /*end of if(*wMinValue > MAX_OFFSET) */
+
+
+ if (*wMinValue < wStdMinLevel)
+ {
+ if (*wMinValue > *bLastMin)
+ {
+ if (*bDirection == 0)
+ {
+ *bOffsetLowerBound = *bOffset;
+ }
+ else
+ {
+ *bOffsetUpperBound = *bOffset;
+ }
+
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+ }
+ else
+ {
+ if (*bDirection == 1)
+ {
+ *bOffsetUpperBound = *bOffset;
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+ }
+ else
+ {
+ *bOffsetLowerBound = *bOffset;
+ *bOffset = (*bOffsetUpperBound + *bOffsetLowerBound) / 2;
+ }
+ }
+ } /*end of if(*wMinValue > MIN_OFFSET) */
+ *bLastMin = (SANE_Byte) * wMinValue;
+ } /*end of if(nTimes >= 1) */
+
+ /* HOLD: missing return value! Correct? */
+ return FALSE;
+}
+#endif
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Filter the data
+Parameters:
+ pSort: the sort data
+ TotalCount: the total count
+ LowCount: the low count
+ HighCount: the upper count
+Return value:
+ the data of Filter
+***********************************************************************/
+static unsigned short
+MustScanner_FiltLower (unsigned short * pSort, unsigned short TotalCount, unsigned short LowCount,
+ unsigned short HighCount)
+{
+ unsigned short Bound = TotalCount - 1;
+ unsigned short LeftCount = HighCount - LowCount;
+ int Temp = 0;
+ unsigned int Sum = 0;
+ unsigned short i, j;
+
+ for (i = 0; i < Bound; i++)
+
+ {
+ for (j = 0; j < Bound - i; j++)
+ {
+ if (pSort[j + 1] > pSort[j])
+ {
+ Temp = pSort[j];
+ pSort[j] = pSort[j + 1];
+ pSort[j + 1] = Temp;
+ }
+ }
+ }
+
+ for (i = 0; i < LeftCount; i++)
+ Sum += pSort[i + LowCount];
+ return (unsigned short) (Sum / LeftCount);
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when single CCD and color is 48bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetRgb48BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned short wRLinePos = 0;
+ unsigned short wGLinePos = 0;
+ unsigned short wBLinePos = 0;
+ unsigned short wRTempData;
+ unsigned short wGTempData;
+ unsigned short wBTempData;
+ unsigned short i;
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: call in \n");
+
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+ TotalXferLines = 0;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ if (!isOrderInvert)
+ {
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
+ wGLinePos =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePos =
+ (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ wRTempData =
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
+ 0);
+ wRTempData +=
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
+ 1) << 8;
+ wGTempData =
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
+ 2);
+ wGTempData +=
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
+ 3) << 8;
+ wBTempData =
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
+ 4);
+ wBTempData +=
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
+ 5) << 8;
+ *(lpLine + i * 6 + 0) = LOBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 1) = HIBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 2) =
+ LOBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 3) =
+ HIBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 4) =
+ LOBYTE (g_pGammaTable[wBTempData + 131072]);
+ *(lpLine + i * 6 + 5) =
+ HIBYTE (g_pGammaTable[wBTempData + 131072]);
+ }
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+ }
+
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
+
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
+ wGLinePos =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePos =
+ (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ wRTempData =
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
+ 0);
+ wRTempData +=
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 6 +
+ 1) << 8;
+ wGTempData =
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
+ 2);
+ wGTempData +=
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 6 +
+ 3) << 8;
+ wBTempData =
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
+ 4);
+ wBTempData +=
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 6 +
+ 5) << 8;
+ *(lpLine + i * 6 + 4) = LOBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 5) = HIBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 2) =
+ LOBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 3) =
+ HIBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 0) =
+ LOBYTE (g_pGammaTable[wBTempData + 131072]);
+ *(lpLine + i * 6 + 1) =
+ HIBYTE (g_pGammaTable[wBTempData + 131072]);
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine: thread exit\n");
+ break;
+ }
+ } /*end for */
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb48BitLine: leave MustScanner_GetRgb48BitLine\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when double CCD and color is 48bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetRgb48BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+
+ unsigned short wRLinePosOdd = 0;
+ unsigned short wGLinePosOdd = 0;
+ unsigned short wBLinePosOdd = 0;
+ unsigned short wRLinePosEven = 0;
+ unsigned short wGLinePosEven = 0;
+ unsigned short wBLinePosEven = 0;
+ unsigned int wRTempData;
+ unsigned int wGTempData;
+ unsigned int wBTempData;
+ unsigned int wNextTempData;
+ unsigned short i;
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: call in \n");
+
+ TotalXferLines = 0;
+ wWantedTotalLines = *wLinesCount;
+
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb48BitLine1200DPI: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ if (!isOrderInvert)
+ {
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+ {
+ wRLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+ else
+ {
+ wRLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if (i + 1 != g_SWWidth)
+ {
+ wRTempData =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ i * 6 + 0);
+ wRTempData +=
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ i * 6 + 1) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 0);
+ wNextTempData +=
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 1) << 8;
+ wRTempData = (wRTempData + wNextTempData) >> 1;
+
+ wGTempData =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ i * 6 + 2);
+ wGTempData +=
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ i * 6 + 3) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 2);
+ wNextTempData +=
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 3) << 8;
+ wGTempData = (wGTempData + wNextTempData) >> 1;
+
+ wBTempData =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ i * 6 + 4);
+ wBTempData +=
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ i * 6 + 5) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 4);
+ wNextTempData +=
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 5) << 8;
+ wBTempData = (wBTempData + wNextTempData) >> 1;
+
+ *(lpLine + i * 6 + 0) =
+ LOBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 1) =
+ HIBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 2) =
+ LOBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 3) =
+ HIBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 4) =
+ LOBYTE (g_pGammaTable[wBTempData + 131072]);
+ *(lpLine + i * 6 + 5) =
+ HIBYTE (g_pGammaTable[wBTempData + 131072]);
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ wRTempData =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ i * 6 + 0);
+ wRTempData +=
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ i * 6 + 1) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 0);
+ wNextTempData +=
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 1) << 8;
+ wRTempData = (wRTempData + wNextTempData) >> 1;
+
+ wGTempData =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ i * 6 + 2);
+ wGTempData +=
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ i * 6 + 3) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 2);
+ wNextTempData +=
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 3) << 8;
+ wGTempData = (wGTempData + wNextTempData) >> 1;
+
+ wBTempData =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ i * 6 + 4);
+ wBTempData +=
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ i * 6 + 5) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 4);
+ wNextTempData +=
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 5) << 8;
+ wBTempData = (wBTempData + wNextTempData) >> 1;
+
+ *(lpLine + i * 6 + 0) =
+ LOBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 1) =
+ HIBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 2) =
+ LOBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 3) =
+ HIBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 4) =
+ LOBYTE (g_pGammaTable[wBTempData + 131072]);
+ *(lpLine + i * 6 + 5) =
+ HIBYTE (g_pGammaTable[wBTempData + 131072]);
+
+ i++;
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
+ break;
+
+ }
+ }
+
+
+ }
+ else
+ {
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+ {
+ wRLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+ else
+ {
+ wRLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if ((i + 1) != g_SWWidth)
+ {
+ wRTempData =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ i * 6 + 0);
+ wRTempData +=
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ i * 6 + 1) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 0);
+ wNextTempData +=
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 1) << 8;
+ wRTempData = (wRTempData + wNextTempData) >> 1;
+
+ wGTempData =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ i * 6 + 2);
+ wGTempData +=
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ i * 6 + 3) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 2);
+ wNextTempData +=
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 3) << 8;
+ wGTempData = (wGTempData + wNextTempData) >> 1;
+
+ wBTempData =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ i * 6 + 4);
+ wBTempData +=
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ i * 6 + 5) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 4);
+ wNextTempData +=
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ (i + 1) * 6 + 5) << 8;
+ wBTempData = (wBTempData + wNextTempData) >> 1;
+
+ *(lpLine + i * 6 + 4) =
+ LOBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 5) =
+ HIBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 2) =
+ LOBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 3) =
+ HIBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 0) =
+ LOBYTE (g_pGammaTable[wBTempData + 131072]);
+ *(lpLine + i * 6 + 1) =
+ HIBYTE (g_pGammaTable[wBTempData + 131072]);
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ wRTempData =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ i * 6 + 0);
+ wRTempData +=
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ i * 6 + 1) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 0);
+ wNextTempData +=
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 1) << 8;
+ wRTempData = (wRTempData + wNextTempData) >> 1;
+
+ wGTempData =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ i * 6 + 2);
+ wGTempData +=
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ i * 6 + 3) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 2);
+ wNextTempData +=
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 3) << 8;
+ wGTempData = (wGTempData + wNextTempData) >> 1;
+
+
+ wBTempData =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ i * 6 + 4);
+ wBTempData +=
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ i * 6 + 5) << 8;
+ wNextTempData =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 4);
+ wNextTempData +=
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ (i + 1) * 6 + 5) << 8;
+ wBTempData = (wBTempData + wNextTempData) >> 1;
+
+ *(lpLine + i * 6 + 4) =
+ LOBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 5) =
+ HIBYTE (g_pGammaTable[wRTempData]);
+ *(lpLine + i * 6 + 2) =
+ LOBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 3) =
+ HIBYTE (g_pGammaTable[wGTempData + 65536]);
+ *(lpLine + i * 6 + 0) =
+ LOBYTE (g_pGammaTable[wBTempData + 131072]);
+ *(lpLine + i * 6 + 1) =
+ HIBYTE (g_pGammaTable[wBTempData + 131072]);
+ i++;
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb48BitLine1200DPI: thread exit\n");
+
+ break;
+ }
+ }
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb48BitLine1200DPI: leave MustScanner_GetRgb48BitLine1200DPI\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when single CCD and color is 24bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetRgb24BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned short wRLinePos = 0;
+ unsigned short wGLinePos = 0;
+ unsigned short wBLinePos = 0;
+ SANE_Byte byRed;
+ SANE_Byte byGreen;
+ SANE_Byte byBlue;
+ SANE_Byte bNextPixel = 0;
+ unsigned short i;
+
+ unsigned short tempR, tempG, tempB;
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: call in\n");
+
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+
+ wWantedTotalLines = *wLinesCount;
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: get wWantedTotalLines= %d\n",
+ wWantedTotalLines);
+
+ TotalXferLines = 0;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread create\n");
+
+ g_bFirstReadImage = FALSE;
+ }
+
+ if (!isOrderInvert)
+ {
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: !isOrderInvert\n");
+
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
+ wGLinePos =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePos =
+ (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ byRed =
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 3 +
+ 0);
+ bNextPixel =
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow +
+ (i + 1) * 3 + 0);
+ byRed = (byRed + bNextPixel) >> 1;
+
+ byGreen =
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 3 +
+ 1);
+ bNextPixel =
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow +
+ (i + 1) * 3 + 1);
+ byGreen = (byGreen + bNextPixel) >> 1;
+
+ byBlue =
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 3 +
+ 2);
+ bNextPixel =
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow +
+ (i + 1) * 3 + 2);
+ byBlue = (byBlue + bNextPixel) >> 1;
+
+#ifdef ENABLE_GAMMA
+ tempR = (unsigned short) ((byRed << 4) | QBET4 (byBlue, byGreen));
+ tempG = (unsigned short) ((byGreen << 4) | QBET4 (byRed, byBlue));
+ tempB = (unsigned short) ((byBlue << 4) | QBET4 (byGreen, byRed));
+
+ *(lpLine + i * 3 + 0) =
+ (unsigned char) (*(g_pGammaTable + tempR));
+ *(lpLine + i * 3 + 1) =
+ (unsigned char) (*(g_pGammaTable + 4096 + tempG));
+ *(lpLine + i * 3 + 2) =
+ (unsigned char) (*(g_pGammaTable + 8192 + tempB));
+#else
+ *(lpLine + i * 3 + 0) = (unsigned char) byRed;
+ *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
+ *(lpLine + i * 3 + 2) = (unsigned char) byBlue;
+#endif
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: g_dwTotalTotalXferLines=%d,g_SWHeight=%d\n",
+ g_dwTotalTotalXferLines, g_SWHeight);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: g_SWBytesPerRow=%d\n",
+ g_SWBytesPerRow);
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: isOrderInvert is TRUE\n");
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wRLinePos = g_wtheReadyLines % g_wMaxScanLines;
+ wGLinePos =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePos =
+ (g_wtheReadyLines - g_wLineDistance * 2) % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: before byRed\n");
+ byRed =
+ *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + i * 3 +
+ 0);
+ bNextPixel = *(g_lpReadImageHead + wRLinePos * g_BytesPerRow + (i + 1) * 3 + 0); /*R-channel */
+ byRed = (byRed + bNextPixel) >> 1;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: before byGreen\n");
+
+ byGreen =
+ *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + i * 3 +
+ 1);
+ bNextPixel = *(g_lpReadImageHead + wGLinePos * g_BytesPerRow + (i + 1) * 3 + 1); /*G-channel */
+ byGreen = (byGreen + bNextPixel) >> 1;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: before byBlue\n");
+
+ byBlue =
+ *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + i * 3 +
+ 2);
+ bNextPixel = *(g_lpReadImageHead + wBLinePos * g_BytesPerRow + (i + 1) * 3 + 2); /*B-channel */
+ byBlue = (byBlue + bNextPixel) >> 1;
+
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: before set lpLine\n");
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: i=%d\n", i);
+#ifdef ENABLE_GAMMA
+ *(lpLine + i * 3 + 2) =
+ (unsigned
+ char) (*(g_pGammaTable +
+ (unsigned short) ((byRed << 4) |
+ QBET4 (byBlue, byGreen))));
+ *(lpLine + i * 3 + 1) =
+ (unsigned
+ char) (*(g_pGammaTable + 4096 +
+ (unsigned short) ((byGreen << 4) |
+ QBET4 (byRed, byBlue))));
+ *(lpLine + i * 3 + 0) =
+ (unsigned
+ char) (*(g_pGammaTable + 8192 +
+ (unsigned short) ((byBlue << 4) |
+ QBET4 (byGreen, byRed))));
+#else
+ *(lpLine + i * 3 + 2) = (unsigned char) byRed;
+ *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
+ *(lpLine + i * 3 + 0) = (unsigned char) byBlue;
+#endif
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: g_dwTotalTotalXferLines=%d,g_SWHeight=%d\n",
+ g_dwTotalTotalXferLines, g_SWHeight);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: g_SWBytesPerRow=%d\n",
+ g_SWBytesPerRow);
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine: thread exit\n");
+
+ break;
+ }
+ } /*end for */
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine: leave MustScanner_GetRgb24BitLine\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when double CCD and color is 24bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetRgb24BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ SANE_Byte *lpTemp;
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned short wRLinePosOdd = 0;
+ unsigned short wGLinePosOdd = 0;
+ unsigned short wBLinePosOdd = 0;
+ unsigned short wRLinePosEven = 0;
+ unsigned short wGLinePosEven = 0;
+ unsigned short wBLinePosEven = 0;
+ SANE_Byte byRed;
+ SANE_Byte byGreen;
+ SANE_Byte byBlue;
+ SANE_Byte bNextPixel = 0;
+ unsigned short i;
+
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: call in\n");
+
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ TotalXferLines = 0;
+ wWantedTotalLines = *wLinesCount;
+ lpTemp = lpLine;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetRgb24BitLine1200DPI: thread create\n");
+
+ g_bFirstReadImage = FALSE;
+ }
+
+ if (!isOrderInvert)
+ {
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
+ g_dwTotalTotalXferLines);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
+ g_Height);
+
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+ {
+ wRLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+ else
+ {
+ wRLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+
+
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if ((i + 1) != g_SWWidth)
+ {
+ byRed =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ i * 3 + 0);
+ bNextPixel = *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow + (i + 1) * 3 + 0); /*R-channel */
+ byRed = (byRed + bNextPixel) >> 1;
+
+ byGreen =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ i * 3 + 1);
+ bNextPixel = *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow + (i + 1) * 3 + 1); /*G-channel */
+ byGreen = (byGreen + bNextPixel) >> 1;
+
+ byBlue =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ i * 3 + 2);
+ bNextPixel = *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow + (i + 1) * 3 + 2); /*B-channel */
+ byBlue = (byBlue + bNextPixel) >> 1;
+#ifdef ENABLE_GAMMA
+ *(lpLine + i * 3 + 0) =
+ (unsigned
+ char) (*(g_pGammaTable +
+ (unsigned short) ((byRed << 4) |
+ QBET4 (byBlue, byGreen))));
+ *(lpLine + i * 3 + 1) =
+ (unsigned
+ char) (*(g_pGammaTable + 4096 +
+ (unsigned short) ((byGreen << 4) |
+ QBET4 (byRed, byBlue))));
+ *(lpLine + i * 3 + 2) =
+ (unsigned
+ char) (*(g_pGammaTable + 8192 +
+ (unsigned short) ((byBlue << 4) |
+ QBET4 (byGreen, byRed))));
+#else
+ *(lpLine + i * 3 + 0) = (unsigned char) byRed;
+ *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
+ *(lpLine + i * 3 + 2) = (unsigned char) byBlue;
+#endif
+
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ byRed =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ i * 3 + 0);
+ bNextPixel =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ (i + 1) * 3 + 0);
+ byRed = (byRed + bNextPixel) >> 1;
+
+ byGreen =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ i * 3 + 1);
+ bNextPixel =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ (i + 1) * 3 + 1);
+ byGreen = (byGreen + bNextPixel) >> 1;
+
+ byBlue =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ i * 3 + 2);
+ bNextPixel =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ (i + 1) * 3 + 2);
+ byBlue = (byBlue + bNextPixel) >> 1;
+#ifdef ENABLE_GAMMA
+ *(lpLine + i * 3 + 0) =
+ (unsigned
+ char) (*(g_pGammaTable +
+ (unsigned short) ((byRed << 4) |
+ QBET4 (byBlue, byGreen))));
+ *(lpLine + i * 3 + 1) =
+ (unsigned
+ char) (*(g_pGammaTable + 4096 +
+ (unsigned short) ((byGreen << 4) |
+ QBET4 (byRed, byBlue))));
+ *(lpLine + i * 3 + 2) =
+ (unsigned
+ char) (*(g_pGammaTable + 8192 +
+ (unsigned short) ((byBlue << 4) |
+ QBET4 (byGreen, byRed))));
+#else
+ *(lpLine + i * 3 + 0) = (unsigned char) byRed;
+ *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
+ *(lpLine + i * 3 + 2) = (unsigned char) byBlue;
+#endif
+ i++;
+ }
+ }
+
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
+ g_dwTotalTotalXferLines);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
+ g_Height);
+
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
+
+ break;
+ }
+
+ }
+ }
+ else
+ {
+
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
+ g_dwTotalTotalXferLines);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
+ g_Height);
+
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+ {
+ wRLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+ else
+ {
+ wRLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wGLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wBLinePosEven =
+ (g_wtheReadyLines - g_wLineDistance * 2 -
+ g_wPixelDistance) % g_wMaxScanLines;
+ wRLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ wGLinePosOdd =
+ (g_wtheReadyLines - g_wLineDistance) % g_wMaxScanLines;
+ wBLinePosOdd =
+ (g_wtheReadyLines -
+ g_wLineDistance * 2) % g_wMaxScanLines;
+ }
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if ((i + 1) != g_SWWidth)
+ {
+ byRed =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ i * 3 + 0);
+ bNextPixel =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ (i + 1) * 3 + 0);
+ byRed = (byRed + bNextPixel) >> 1;
+
+ byGreen =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ i * 3 + 1);
+ bNextPixel =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ (i + 1) * 3 + 1);
+ byGreen = (byGreen + bNextPixel) >> 1;
+
+ byBlue =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ i * 3 + 2);
+ bNextPixel =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ (i + 1) * 3 + 2);
+ byBlue = (byBlue + bNextPixel) >> 1;
+
+#ifdef ENABLE_GAMMA
+ *(lpLine + i * 3 + 2) =
+ (unsigned
+ char) (*(g_pGammaTable +
+ (unsigned short) ((byRed << 4) |
+ QBET4 (byBlue, byGreen))));
+ *(lpLine + i * 3 + 1) =
+ (unsigned
+ char) (*(g_pGammaTable + 4096 +
+ (unsigned short) ((byGreen << 4) |
+ QBET4 (byRed, byBlue))));
+ *(lpLine + i * 3 + 0) =
+ (unsigned
+ char) (*(g_pGammaTable + 8192 +
+ (unsigned short) ((byBlue << 4) |
+ QBET4 (byGreen, byRed))));
+#else
+ *(lpLine + i * 3 + 2) = (unsigned char) byRed;
+ *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
+ *(lpLine + i * 3 + 0) = (unsigned char) byBlue;
+#endif
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ byRed =
+ *(g_lpReadImageHead + wRLinePosEven * g_BytesPerRow +
+ i * 3 + 0);
+ bNextPixel =
+ *(g_lpReadImageHead + wRLinePosOdd * g_BytesPerRow +
+ (i + 1) * 3 + 0);
+ byRed = (byRed + bNextPixel) >> 1;
+
+ byGreen =
+ *(g_lpReadImageHead + wGLinePosEven * g_BytesPerRow +
+ i * 3 + 1);
+ bNextPixel =
+ *(g_lpReadImageHead + wGLinePosOdd * g_BytesPerRow +
+ (i + 1) * 3 + 1);
+ byGreen = (byGreen + bNextPixel) >> 1;
+
+ byBlue =
+ *(g_lpReadImageHead + wBLinePosEven * g_BytesPerRow +
+ i * 3 + 2);
+ bNextPixel =
+ *(g_lpReadImageHead + wBLinePosOdd * g_BytesPerRow +
+ (i + 1) * 3 + 2);
+ byBlue = (byBlue + bNextPixel) >> 1;
+#ifdef ENABLE_GAMMA
+ *(lpLine + i * 3 + 2) =
+ (unsigned
+ char) (*(g_pGammaTable +
+ (unsigned short) ((byRed << 4) |
+ QBET4 (byBlue, byGreen))));
+ *(lpLine + i * 3 + 1) =
+ (unsigned
+ char) (*(g_pGammaTable + 4096 +
+ (unsigned short) ((byGreen << 4) |
+ QBET4 (byRed, byBlue))));
+ *(lpLine + i * 3 + 0) =
+ (unsigned
+ char) (*(g_pGammaTable + 8192 +
+ (unsigned short) ((byBlue << 4) |
+ QBET4 (byGreen, byRed))));
+#else
+ *(lpLine + i * 3 + 2) = (unsigned char) byRed;
+ *(lpLine + i * 3 + 1) = (unsigned char) byGreen;
+ *(lpLine + i * 3 + 0) = (unsigned char) byBlue;
+#endif
+ i++;
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_dwTotalTotalXferLines=%d\n",
+ g_dwTotalTotalXferLines);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: g_Height=%d\n",
+ g_Height);
+
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: thread exit\n");
+
+
+ break;
+ }
+ }
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetRgb24BitLine1200DPI: leave MustScanner_GetRgb24BitLine1200DPI\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when single CCD and color is 16bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetMono16BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned int wTempData;
+
+ unsigned short wLinePos = 0;
+ unsigned short i;
+
+ isOrderInvert = isOrderInvert;
+
+ DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: call in\n");
+
+ TotalXferLines = 0;
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wLinePos = g_wtheReadyLines % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ wTempData =
+ *(g_lpReadImageHead + wLinePos * g_BytesPerRow + i * 2 + 0);
+ wTempData +=
+ *(g_lpReadImageHead + wLinePos * g_BytesPerRow + i * 2 +
+ 1) << 8;
+ *(lpLine + i * 2 + 0) = LOBYTE (g_pGammaTable[wTempData]);
+ *(lpLine + i * 2 + 1) = HIBYTE (g_pGammaTable[wTempData]);
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono16BitLine: thread exit\n");
+
+ break;
+ }
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono16BitLine: leave MustScanner_GetMono16BitLine\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when double CCD and color is 16bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetMono16BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned int dwTempData;
+ unsigned short wLinePosOdd = 0;
+ unsigned short wLinePosEven = 0;
+ unsigned short i;
+ SANE_Byte * lpTemp = lpLine;
+
+ isOrderInvert = isOrderInvert;
+ DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: call in\n");
+
+ TotalXferLines = 0;
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono16BitLine1200DPI: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono16BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+ {
+ wLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ }
+ else
+ {
+ wLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ }
+
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if ((i + 1) != g_SWWidth)
+ {
+ dwTempData =
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosOdd * g_BytesPerRow + i * 2 + 0));
+ dwTempData +=
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosOdd * g_BytesPerRow + i * 2 + 1) << 8);
+ dwTempData +=
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosEven * g_BytesPerRow + (i + 1) * 2 +
+ 0));
+ dwTempData +=
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosEven * g_BytesPerRow + (i + 1) * 2 +
+ 1) << 8);
+ dwTempData = g_pGammaTable[dwTempData >> 1];
+ *(lpLine + i * 2 + 0) = LOBYTE ((unsigned short) dwTempData);
+ *(lpLine + i * 2 + 1) = HIBYTE ((unsigned short) dwTempData);
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ dwTempData =
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosEven * g_BytesPerRow + i * 2 + 0));
+ dwTempData +=
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosEven * g_BytesPerRow + i * 2 + 1) << 8);
+ dwTempData +=
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosOdd * g_BytesPerRow + (i + 1) * 2 + 0));
+ dwTempData +=
+ (unsigned int) (*
+ (g_lpReadImageHead +
+ wLinePosOdd * g_BytesPerRow + (i + 1) * 2 +
+ 1) << 8);
+ dwTempData = g_pGammaTable[dwTempData >> 1];
+ *(lpLine + i * 2 + 0) = LOBYTE ((unsigned short) dwTempData);
+ *(lpLine + i * 2 + 1) = HIBYTE ((unsigned short) dwTempData);
+ i++;
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono16BitLine1200DPI: thread exit\n");
+
+ break;
+ }
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ /*for modify the last point */
+ if (g_bIsFirstReadBefData)
+ {
+ g_lpBefLineImageData = (SANE_Byte *) malloc (g_SWBytesPerRow);
+ if (NULL == g_lpBefLineImageData)
+ {
+ return FALSE;
+ }
+ memset (g_lpBefLineImageData, 0, g_SWBytesPerRow);
+ memcpy (g_lpBefLineImageData, lpTemp, g_SWBytesPerRow);
+ g_bIsFirstReadBefData = FALSE;
+ }
+
+ ModifyLinePoint (lpTemp, g_lpBefLineImageData, g_SWBytesPerRow,
+ wWantedTotalLines, 2, 4);
+
+ memcpy (g_lpBefLineImageData,
+ lpTemp + (wWantedTotalLines - 1) * g_SWBytesPerRow,
+ g_SWBytesPerRow);
+ g_dwAlreadyGetLines += wWantedTotalLines;
+ if (g_dwAlreadyGetLines >= g_SWHeight)
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono16BitLine1200DPI: free before line data!\n");
+ free (g_lpBefLineImageData);
+ g_lpBefLineImageData = NULL;
+ g_dwAlreadyGetLines = 0;
+ g_bIsFirstReadBefData = TRUE;
+ }
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono16BitLine1200DPI: leave MustScanner_GetMono16BitLine1200DPI\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when single CCD and color is 8bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetMono8BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+
+ unsigned short i;
+ unsigned short wLinePos = 0;
+
+ isOrderInvert = isOrderInvert;
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: call in\n");
+
+ TotalXferLines = 0;
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wLinePos = g_wtheReadyLines % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ *(lpLine + i) =
+ (SANE_Byte) * (g_pGammaTable +
+ (unsigned short) ((*
+ (g_lpReadImageHead +
+ wLinePos * g_BytesPerRow +
+ i) << 4) | (rand () & 0x0f)));
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine: thread exit\n");
+
+ break;
+ }
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono8BitLine: leave MustScanner_GetMono8BitLine\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when double CCD and color is 8bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetMono8BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ SANE_Byte *lpTemp;
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+
+ unsigned short wLinePosOdd = 0;
+ unsigned short wLinePosEven = 0;
+ SANE_Byte byGray;
+ unsigned short i;
+ SANE_Byte bNextPixel = 0;
+
+ isOrderInvert = isOrderInvert;
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: call in\n");
+
+ TotalXferLines = 0;
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+ lpTemp = lpLine;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ for (; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+
+ {
+ wLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ }
+ else
+ {
+ wLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ }
+
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if ((i + 1) != g_SWWidth)
+ {
+ byGray =
+ *(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i);
+ bNextPixel =
+ *(g_lpReadImageHead + wLinePosEven * g_BytesPerRow +
+ (i + 1));
+ byGray = (byGray + bNextPixel) >> 1;
+
+ *(lpLine + i) =
+ (SANE_Byte) * (g_pGammaTable +
+ (byGray << 4 | (rand () & 0x0f)));
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ byGray =
+ *(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i);
+ bNextPixel =
+ *(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow +
+ (i + 1));
+ byGray = (byGray + bNextPixel) >> 1;
+
+ *(lpLine + i) =
+ (SANE_Byte) * (g_pGammaTable +
+ (byGray << 4 | (rand () & 0x0f)));
+ i++;
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow;
+ AddReadyLines ();
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono8BitLine1200DPI: thread exit\n");
+
+ break;
+ }
+ }
+
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ /*for modify the last point */
+ if (g_bIsFirstReadBefData)
+ {
+ g_lpBefLineImageData = (SANE_Byte *) malloc (g_SWBytesPerRow);
+ if (NULL == g_lpBefLineImageData)
+ {
+ return FALSE;
+ }
+ memset (g_lpBefLineImageData, 0, g_SWBytesPerRow);
+ memcpy (g_lpBefLineImageData, lpTemp, g_SWBytesPerRow);
+ g_bIsFirstReadBefData = FALSE;
+ }
+
+ ModifyLinePoint (lpTemp, g_lpBefLineImageData, g_SWBytesPerRow,
+ wWantedTotalLines, 1, 4);
+
+ memcpy (g_lpBefLineImageData,
+ lpTemp + (wWantedTotalLines - 1) * g_SWBytesPerRow,
+ g_SWBytesPerRow);
+ g_dwAlreadyGetLines += wWantedTotalLines;
+ if (g_dwAlreadyGetLines >= g_SWHeight)
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono8BitLine1200DPI: free the before line data!\n");
+ free (g_lpBefLineImageData);
+ g_lpBefLineImageData = NULL;
+ g_dwAlreadyGetLines = 0;
+ g_bIsFirstReadBefData = TRUE;
+ }
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono8BitLine1200DPI: leave MustScanner_GetMono8BitLine1200DPI\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when single CCD and color is 1bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetMono1BitLine (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned short wLinePos;
+ unsigned short i;
+
+ isOrderInvert = isOrderInvert;
+
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: call in\n");
+
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ memset (lpLine, 0, wWantedTotalLines * g_SWWidth / 8);
+
+ for (TotalXferLines = 0; TotalXferLines < wWantedTotalLines;)
+
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ wLinePos = g_wtheReadyLines % g_wMaxScanLines;
+
+ for (i = 0; i < g_SWWidth; i++)
+ {
+ if (*(g_lpReadImageHead + wLinePos * g_BytesPerRow + i) >
+ g_wLineartThreshold)
+ {
+ *(lpLine + i / 8) += (0x80 >> (i % 8));
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += (g_SWBytesPerRow / 8);
+ AddReadyLines ();
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine: thread exit\n");
+
+ break;
+ }
+ }
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono1BitLine: leave MustScanner_GetMono1BitLine\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Repair line when double CCD and color is 1bit
+Parameters:
+ lpLine: point to image be repaired
+ isOrderInvert: RGB or BGR
+ wLinesCount: how many line be repaired
+Return value:
+ if the operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static SANE_Bool
+MustScanner_GetMono1BitLine1200DPI (SANE_Byte * lpLine, SANE_Bool isOrderInvert,
+ unsigned short * wLinesCount)
+{
+ unsigned short wWantedTotalLines;
+ unsigned short TotalXferLines;
+ unsigned short i;
+ unsigned short wLinePosOdd;
+ unsigned short wLinePosEven;
+
+ isOrderInvert = isOrderInvert;
+
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: call in\n");
+
+ g_isCanceled = FALSE;
+ g_isScanning = TRUE;
+ wWantedTotalLines = *wLinesCount;
+
+ if (g_bFirstReadImage)
+ {
+ pthread_create (&g_threadid_readimage, NULL,
+ MustScanner_ReadDataFromScanner, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread create\n");
+ g_bFirstReadImage = FALSE;
+ }
+
+ memset (lpLine, 0, wWantedTotalLines * g_SWWidth / 8);
+
+ for (TotalXferLines = 0; TotalXferLines < wWantedTotalLines;)
+ {
+ if (g_dwTotalTotalXferLines >= g_SWHeight)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread exit\n");
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+ return TRUE;
+ }
+
+ if (GetScannedLines () > g_wtheReadyLines)
+ {
+ if (ST_Reflective == g_ScanType)
+ {
+ wLinePosEven = (g_wtheReadyLines) % g_wMaxScanLines;
+ wLinePosOdd =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ }
+ else
+ {
+ wLinePosOdd = (g_wtheReadyLines) % g_wMaxScanLines;
+ wLinePosEven =
+ (g_wtheReadyLines - g_wPixelDistance) % g_wMaxScanLines;
+ }
+
+
+
+ for (i = 0; i < g_SWWidth;)
+ {
+ if ((i + 1) != g_SWWidth)
+ {
+ if (*(g_lpReadImageHead + wLinePosOdd * g_BytesPerRow + i) >
+ g_wLineartThreshold)
+ *(lpLine + i / 8) += (0x80 >> (i % 8));
+ i++;
+ if (i >= g_SWWidth)
+ {
+ break;
+ }
+
+ if (*(g_lpReadImageHead + wLinePosEven * g_BytesPerRow + i)
+ > g_wLineartThreshold)
+ *(lpLine + i / 8) += (0x80 >> (i % 8));
+ i++;
+ }
+ }
+
+ TotalXferLines++;
+ g_dwTotalTotalXferLines++;
+ lpLine += g_SWBytesPerRow / 8;
+ AddReadyLines ();
+
+
+ }
+ if (g_isCanceled)
+ {
+ pthread_cancel (g_threadid_readimage);
+ pthread_join (g_threadid_readimage, NULL);
+ DBG (DBG_FUNC, "MustScanner_GetMono1BitLine1200DPI: thread exit\n");
+
+ break;
+ }
+ } /*end for */
+
+ *wLinesCount = TotalXferLines;
+ g_isScanning = FALSE;
+
+ DBG (DBG_FUNC,
+ "MustScanner_GetMono1BitLine1200DPI: leave MustScanner_GetMono1BitLine1200DPI\n");
+ return TRUE;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/21
+Routine Description:
+ prepare calculate Max and Min value
+Parameters:
+ wResolution: the scan resolution
+Return value:
+ none
+***********************************************************************/
+static void
+MustScanner_PrepareCalculateMaxMin (unsigned short wResolution)
+{
+ g_wDarkCalWidth = 52;
+ if (wResolution <= 600)
+ {
+ g_wCalWidth = ((5120 * wResolution / 600 + 511) >> 9) << 9;
+ g_wDarkCalWidth = g_wDarkCalWidth / (1200 / wResolution);
+
+ if (wResolution < 200)
+ {
+ g_nPowerNum = 3;
+ g_nSecLength = 8; /* 2^nPowerNum */
+ g_nDarkSecLength = g_wDarkCalWidth / 2; /* Dark has at least 2 sections */
+ }
+ else
+ {
+ g_nPowerNum = 6;
+ g_nSecLength = 64; /* 2^nPowerNum */
+ g_nDarkSecLength = g_wDarkCalWidth / 3;
+ }
+ }
+ else
+ {
+ g_nPowerNum = 6;
+ g_nSecLength = 64; /*2^nPowerNum */
+ g_wCalWidth = 10240;
+ g_nDarkSecLength = g_wDarkCalWidth / 5;
+ }
+
+ if (g_nDarkSecLength <= 0)
+ {
+ g_nDarkSecLength = 1;
+ }
+
+ g_wStartPosition = 13 * wResolution / 1200;
+ g_wCalWidth -= g_wStartPosition;
+
+
+ /* start of find Max value */
+ g_nSecNum = (int) (g_wCalWidth / g_nSecLength);
+
+ /* start of fin min value */
+ g_nDarkSecNum = (int) (g_wDarkCalWidth / g_nDarkSecLength);
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/21
+Routine Description:
+ calculate the Max and Min value
+Parameters:
+ pBuffer: the image data
+ lpMaxValue: the max value
+ lpMinValue: the min value
+ wResolution: the scan resolution
+Return value:
+ none
+***********************************************************************/
+static void
+MustScanner_CalculateMaxMin (SANE_Byte * pBuffer, unsigned short * lpMaxValue,
+ unsigned short * lpMinValue, unsigned short wResolution)
+{
+ unsigned short *wSecData = NULL, *wDarkSecData = NULL;
+ int i, j;
+
+ wResolution = wResolution;
+
+ wSecData = (unsigned short *) malloc (sizeof (unsigned short) * g_nSecNum);
+ if (wSecData == NULL)
+ {
+ return;
+ }
+ else
+ {
+ memset (wSecData, 0, g_nSecNum * sizeof (unsigned short));
+ }
+
+ for (i = 0; i < g_nSecNum; i++)
+ {
+
+ for (j = 0; j < g_nSecLength; j++)
+ wSecData[i] += *(pBuffer + g_wStartPosition + i * g_nSecLength + j);
+ wSecData[i] >>= g_nPowerNum;
+ }
+
+ *lpMaxValue = wSecData[0];
+ for (i = 0; i < g_nSecNum; i++)
+ {
+ if (*lpMaxValue < wSecData[i])
+ *lpMaxValue = wSecData[i];
+ }
+
+ free (wSecData);
+
+ wDarkSecData = (unsigned short *) malloc (sizeof (unsigned short) * g_nDarkSecNum);
+ if (wDarkSecData == NULL)
+ {
+ return;
+ }
+ else
+ {
+ memset (wDarkSecData, 0, g_nDarkSecNum * sizeof (unsigned short));
+ }
+
+ for (i = 0; i < g_nDarkSecNum; i++)
+ {
+ for (j = 0; j < g_nDarkSecLength; j++)
+ wDarkSecData[i] +=
+ *(pBuffer + g_wStartPosition + i * g_nDarkSecLength + j);
+
+ wDarkSecData[i] /= g_nDarkSecLength;
+ }
+
+ *lpMinValue = wDarkSecData[0];
+ for (i = 0; i < g_nDarkSecNum; i++)
+ {
+ if (*lpMinValue > wDarkSecData[i])
+ *lpMinValue = wDarkSecData[i];
+ }
+ free (wDarkSecData);
+}
+
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Read the data from scanner
+Parameters:
+ none
+Return value:
+ if operation is success
+ return TRUE
+ else
+ return FALSE
+***********************************************************************/
+static void *
+MustScanner_ReadDataFromScanner (void * dummy)
+{
+ unsigned short wTotalReadImageLines = 0;
+ unsigned short wWantedLines = g_Height;
+ SANE_Byte * lpReadImage = g_lpReadImageHead;
+ SANE_Bool isWaitImageLineDiff = FALSE;
+ unsigned int wMaxScanLines = g_wMaxScanLines;
+ unsigned short wReadImageLines = 0;
+ unsigned short wScanLinesThisBlock;
+ unsigned short wBufferLines = g_wLineDistance * 2 + g_wPixelDistance;
+
+ dummy = dummy;
+ DBG (DBG_FUNC,
+ "MustScanner_ReadDataFromScanner: call in, and in new thread\n");
+
+ while (wTotalReadImageLines < wWantedLines && g_lpReadImageHead)
+ {
+ if (!isWaitImageLineDiff)
+ {
+ wScanLinesThisBlock =
+ (wWantedLines - wTotalReadImageLines) <
+ g_wScanLinesPerBlock ? (wWantedLines -
+ wTotalReadImageLines) :
+ g_wScanLinesPerBlock;
+
+ DBG (DBG_FUNC,
+ "MustScanner_ReadDataFromScanner: wWantedLines=%d\n",
+ wWantedLines);
+
+ DBG (DBG_FUNC,
+ "MustScanner_ReadDataFromScanner: wScanLinesThisBlock=%d\n",
+ wScanLinesThisBlock);
+
+ if (STATUS_GOOD !=
+ Asic_ReadImage (&g_chip, lpReadImage, wScanLinesThisBlock))
+ {
+ DBG (DBG_FUNC,
+ "MustScanner_ReadDataFromScanner:Asic_ReadImage return error\n");
+ DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner:thread exit\n");
+ return NULL;
+ }
+
+ /*has read in memroy Buffer */
+ wReadImageLines += wScanLinesThisBlock;
+
+ AddScannedLines (wScanLinesThisBlock);
+
+ wTotalReadImageLines += wScanLinesThisBlock;
+
+ lpReadImage += wScanLinesThisBlock * g_BytesPerRow;
+
+ /*Buffer is full */
+ if (wReadImageLines >= wMaxScanLines)
+ {
+ lpReadImage = g_lpReadImageHead;
+ wReadImageLines = 0;
+ }
+
+ if ((g_dwScannedTotalLines - GetReadyLines ())
+ >= (wMaxScanLines - (wBufferLines + g_wScanLinesPerBlock))
+ && g_dwScannedTotalLines > GetReadyLines ())
+ {
+ isWaitImageLineDiff = TRUE;
+ }
+ }
+ else if (g_dwScannedTotalLines <=
+ GetReadyLines () + wBufferLines + g_wScanLinesPerBlock)
+ {
+ isWaitImageLineDiff = FALSE;
+ }
+
+ pthread_testcancel ();
+ }
+
+ DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: Read image ok\n");
+ DBG (DBG_FUNC, "MustScanner_ReadDataFromScanner: thread exit\n");
+ DBG (DBG_FUNC,
+ "MustScanner_ReadDataFromScanner: leave MustScanner_ReadDataFromScanner\n");
+ return NULL;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/26
+Routine Description:
+ get the lines of scanned
+Parameters:
+ none
+Return value:
+ the lines of scanned
+***********************************************************************/
+static unsigned int
+GetScannedLines ()
+{
+ unsigned int dwScannedLines = 0;
+
+ pthread_mutex_lock (&g_scannedLinesMutex);
+ dwScannedLines = g_dwScannedTotalLines;
+ pthread_mutex_unlock (&g_scannedLinesMutex);
+
+ return dwScannedLines;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/26
+
+Routine Description:
+ get lines which pass to superstratum
+Parameters:
+ none
+Return value:
+ the lines which pass to superstratum
+***********************************************************************/
+static unsigned int
+GetReadyLines ()
+{
+ unsigned int dwReadyLines = 0;
+
+ pthread_mutex_lock (&g_readyLinesMutex);
+ dwReadyLines = g_wtheReadyLines;
+ pthread_mutex_unlock (&g_readyLinesMutex);
+
+ return dwReadyLines;
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/26
+Routine Description:
+ add the scanned total lines
+Parameters:
+ wAddLines: add the lines
+Return value:
+ none
+***********************************************************************/
+static void
+AddScannedLines (unsigned short wAddLines)
+{
+ pthread_mutex_lock (&g_scannedLinesMutex);
+
+ g_dwScannedTotalLines += wAddLines;
+
+ pthread_mutex_unlock (&g_scannedLinesMutex);
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/26
+Routine Description:
+ add the ready lines
+Parameters:
+ none
+Return value:
+ none
+***********************************************************************/
+static void
+AddReadyLines ()
+{
+ pthread_mutex_lock (&g_readyLinesMutex);
+ g_wtheReadyLines++;
+ pthread_mutex_unlock (&g_readyLinesMutex);
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/26
+Routine Description:
+ modify the point
+Parameters:
+ lpImageData: the data of image
+ lpImageDataBefore: the data of before line image
+ dwBytesPerLine: the bytes of per line
+ dwLinesCount: the line count
+ wPixDistance: the pixel distance
+ wModPtCount: the modify point count
+Return value:
+ none
+***********************************************************************/
+static void
+ModifyLinePoint (SANE_Byte * lpImageData,
+ SANE_Byte * lpImageDataBefore,
+ unsigned int dwBytesPerLine,
+ unsigned int dwLinesCount, unsigned short wPixDistance, unsigned short wModPtCount)
+{
+ unsigned short i = 0;
+ unsigned short j = 0;
+ unsigned short wLines = 0;
+ unsigned int dwWidth = dwBytesPerLine / wPixDistance;
+ for (i = wModPtCount; i > 0; i--)
+ {
+ for (j = 0; j < wPixDistance; j++)
+ {
+ /*modify the first line */
+ *(lpImageData + (dwWidth - i) * wPixDistance + j) =
+ (*(lpImageData + (dwWidth - i - 1) * wPixDistance + j) +
+ *(lpImageDataBefore + (dwWidth - i) * wPixDistance + j)) / 2;
+ /*modify other lines */
+ for (wLines = 1; wLines < dwLinesCount; wLines++)
+ {
+ unsigned int dwBytesBefor = (wLines - 1) * dwBytesPerLine;
+ unsigned int dwBytes = wLines * dwBytesPerLine;
+ *(lpImageData + dwBytes + (dwWidth - i) * wPixDistance + j) =
+ (*
+ (lpImageData + dwBytes + (dwWidth - i - 1) * wPixDistance +
+ j) + *(lpImageData + dwBytesBefor + (dwWidth -
+ i) * wPixDistance +
+ j)) / 2;
+ }
+ }
+ }
+}
+
+/**********************************************************************
+Author: Jack Date: 2005/05/15
+Routine Description:
+ Modifiy the image data
+Parameters:
+ A: the input the image data
+ B: the input the iamge data
+Return value:
+ the modified data
+***********************************************************************/
+static SANE_Byte
+QBET4 (SANE_Byte A, SANE_Byte B)
+{
+ SANE_Byte bQBET[16][16] = {
+ {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
+ {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
+ {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
+ {0, 0, 0, 0, 1, 1, 2, 2, 4, 4, 5, 5, 8, 8, 9, 9},
+ {1, 1, 1, 1, 3, 3, 3, 3, 6, 6, 6, 6, 10, 10, 11, 11},
+ {1, 1, 1, 1, 3, 3, 3, 3, 6, 6, 6, 6, 10, 10, 11, 11},
+ {2, 2, 2, 2, 3, 3, 3, 3, 7, 7, 7, 7, 10, 10, 11, 11},
+ {2, 2, 2, 2, 3, 3, 3, 3, 7, 7, 7, 7, 10, 10, 11, 11},
+ {4, 4, 4, 4, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
+ {4, 4, 4, 4, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
+ {5, 5, 5, 5, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
+ {5, 5, 5, 5, 6, 6, 7, 7, 12, 12, 12, 12, 13, 13, 14, 14},
+ {8, 8, 8, 8, 10, 10, 10, 10, 13, 13, 13, 13, 15, 15, 15, 15},
+ {8, 8, 8, 8, 10, 10, 10, 10, 13, 13, 13, 13, 15, 15, 15, 15},
+ {9, 9, 9, 9, 11, 11, 11, 11, 14, 14, 14, 14, 15, 15, 15, 15},
+ {9, 9, 9, 9, 11, 11, 11, 11, 14, 14, 14, 14, 15, 15, 15, 15}
+ };
+
+ A = A & 0x0f;
+ B = B & 0x0f;
+ return bQBET[A][B];
+} /* end of the file MustScanner.c */