1141cc406Sopenharmony_ci/* @file u12_image.c
2141cc406Sopenharmony_ci * @brief functions to convert scanner data into image data
3141cc406Sopenharmony_ci *
4141cc406Sopenharmony_ci * based on sources acquired from Plustek Inc.
5141cc406Sopenharmony_ci * Copyright (c) 2003-2004 Gerhard Jaeger <gerhard@gjaeger.de>
6141cc406Sopenharmony_ci *
7141cc406Sopenharmony_ci * History:
8141cc406Sopenharmony_ci * - 0.01 - initial version
9141cc406Sopenharmony_ci * - 0.02 - fixed fnColor42() to return 16bit values instead of
10141cc406Sopenharmony_ci *          only 12bit (this is the maximum the scanner can)
11141cc406Sopenharmony_ci *        - added scaling function u12image_ScaleX()
12141cc406Sopenharmony_ci * .
13141cc406Sopenharmony_ci * <hr>
14141cc406Sopenharmony_ci * This file is part of the SANE package.
15141cc406Sopenharmony_ci *
16141cc406Sopenharmony_ci * This program is free software; you can redistribute it and/or
17141cc406Sopenharmony_ci * modify it under the terms of the GNU General Public License as
18141cc406Sopenharmony_ci * published by the Free Software Foundation; either version 2 of the
19141cc406Sopenharmony_ci * License, or (at your option) any later version.
20141cc406Sopenharmony_ci *
21141cc406Sopenharmony_ci * This program is distributed in the hope that it will be useful, but
22141cc406Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
23141cc406Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24141cc406Sopenharmony_ci * General Public License for more details.
25141cc406Sopenharmony_ci *
26141cc406Sopenharmony_ci * You should have received a copy of the GNU General Public License
27141cc406Sopenharmony_ci * along with this program.  If not, see <https://www.gnu.org/licenses/>.
28141cc406Sopenharmony_ci *
29141cc406Sopenharmony_ci * As a special exception, the authors of SANE give permission for
30141cc406Sopenharmony_ci * additional uses of the libraries contained in this release of SANE.
31141cc406Sopenharmony_ci *
32141cc406Sopenharmony_ci * The exception is that, if you link a SANE library with other files
33141cc406Sopenharmony_ci * to produce an executable, this does not by itself cause the
34141cc406Sopenharmony_ci * resulting executable to be covered by the GNU General Public
35141cc406Sopenharmony_ci * License.  Your use of that executable is in no way restricted on
36141cc406Sopenharmony_ci * account of linking the SANE library code into it.
37141cc406Sopenharmony_ci *
38141cc406Sopenharmony_ci * This exception does not, however, invalidate any other reasons why
39141cc406Sopenharmony_ci * the executable file might be covered by the GNU General Public
40141cc406Sopenharmony_ci * License.
41141cc406Sopenharmony_ci *
42141cc406Sopenharmony_ci * If you submit changes to SANE to the maintainers to be included in
43141cc406Sopenharmony_ci * a subsequent release, you agree by submitting the changes that
44141cc406Sopenharmony_ci * those changes may be distributed with this exception intact.
45141cc406Sopenharmony_ci *
46141cc406Sopenharmony_ci * If you write modifications of your own for SANE, it is your choice
47141cc406Sopenharmony_ci * whether to permit this exception to apply to your modifications.
48141cc406Sopenharmony_ci * If you do not wish that, delete this exception notice.
49141cc406Sopenharmony_ci * <hr>
50141cc406Sopenharmony_ci */
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_ci/*************************** local vars **************************************/
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_cistatic u_short wPreviewScanned = 0;
55141cc406Sopenharmony_ci
56141cc406Sopenharmony_cistatic ExpXStepDef negScan[5] = {
57141cc406Sopenharmony_ci	{128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96}
58141cc406Sopenharmony_ci};
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_cistatic ExpXStepDef posScan[5] = {
61141cc406Sopenharmony_ci	{128, 8}, {96, 12}, {96, 24}, {96, 48}, {96, 96}
62141cc406Sopenharmony_ci};
63141cc406Sopenharmony_ci
64141cc406Sopenharmony_cistatic ExpXStepDef nmlScan[5] = {
65141cc406Sopenharmony_ci	{160, 10}, {96, 12}, {96, 24}, {96, 48}, {96, 96},
66141cc406Sopenharmony_ci};
67141cc406Sopenharmony_ci
68141cc406Sopenharmony_ci/*************************** local functions *********************************/
69141cc406Sopenharmony_ci
70141cc406Sopenharmony_ci/**
71141cc406Sopenharmony_ci */
72141cc406Sopenharmony_cistatic SANE_Bool fnReadToDriver( U12_Device *dev )
73141cc406Sopenharmony_ci{
74141cc406Sopenharmony_ci	dev->regs.RD_ModeControl = _ModeFifoBSel;
75141cc406Sopenharmony_ci	u12io_ReadMonoData( dev, dev->scan.BufPut.blue.bp,
76141cc406Sopenharmony_ci	                    dev->DataInf.dwAsicBytesPerPlane );
77141cc406Sopenharmony_ci
78141cc406Sopenharmony_ci	dev->regs.RD_ModeControl = _ModeFifoGSel;
79141cc406Sopenharmony_ci	u12io_ReadMonoData( dev, dev->scan.BufPut.green.bp,
80141cc406Sopenharmony_ci	                    dev->DataInf.dwAsicBytesPerPlane );
81141cc406Sopenharmony_ci
82141cc406Sopenharmony_ci	if( dev->scan.gd_gk.wGreenKeep )
83141cc406Sopenharmony_ci		dev->scan.gd_gk.wGreenKeep--;
84141cc406Sopenharmony_ci	else {
85141cc406Sopenharmony_ci		dev->scan.BufPut.green.bp += dev->DataInf.dwAsicBytesPerPlane;
86141cc406Sopenharmony_ci
87141cc406Sopenharmony_ci		if( dev->scan.BufPut.green.bp >= dev->scan.BufEnd.green.bp )
88141cc406Sopenharmony_ci		    dev->scan.BufPut.green.bp = dev->scan.BufBegin.green.bp;
89141cc406Sopenharmony_ci	}
90141cc406Sopenharmony_ci
91141cc406Sopenharmony_ci	dev->regs.RD_ModeControl = _ModeFifoRSel;
92141cc406Sopenharmony_ci	u12io_ReadMonoData( dev, dev->scan.BufPut.red.bp,
93141cc406Sopenharmony_ci	                    dev->DataInf.dwAsicBytesPerPlane );
94141cc406Sopenharmony_ci
95141cc406Sopenharmony_ci	dev->scan.BufPut.red.bp += dev->DataInf.dwAsicBytesPerPlane;
96141cc406Sopenharmony_ci	if( dev->scan.BufPut.red.bp >= dev->scan.BufEnd.red.bp )
97141cc406Sopenharmony_ci		dev->scan.BufPut.red.bp = dev->scan.BufBegin.red.bp;
98141cc406Sopenharmony_ci
99141cc406Sopenharmony_ci	if( dev->scan.bd_rk.wRedKeep ) {
100141cc406Sopenharmony_ci		dev->scan.bd_rk.wRedKeep--;
101141cc406Sopenharmony_ci		return SANE_FALSE;
102141cc406Sopenharmony_ci
103141cc406Sopenharmony_ci	} else {
104141cc406Sopenharmony_ci
105141cc406Sopenharmony_ci		dev->scan.BufData.green.bp = dev->scan.BufGet.green.bp;
106141cc406Sopenharmony_ci		dev->scan.BufData.red.bp   = dev->scan.BufGet.red.bp;
107141cc406Sopenharmony_ci		dev->scan.BufData.blue.bp  = dev->scan.BufGet.blue.bp;
108141cc406Sopenharmony_ci
109141cc406Sopenharmony_ci		dev->scan.BufGet.red.bp   += dev->DataInf.dwAsicBytesPerPlane;
110141cc406Sopenharmony_ci		dev->scan.BufGet.green.bp += dev->DataInf.dwAsicBytesPerPlane;
111141cc406Sopenharmony_ci
112141cc406Sopenharmony_ci		if( dev->scan.BufGet.red.bp >= dev->scan.BufEnd.red.bp )
113141cc406Sopenharmony_ci			dev->scan.BufGet.red.bp = dev->scan.BufBegin.red.bp;
114141cc406Sopenharmony_ci
115141cc406Sopenharmony_ci		if( dev->scan.BufGet.green.bp >= dev->scan.BufEnd.green.bp )
116141cc406Sopenharmony_ci			dev->scan.BufGet.green.bp = dev->scan.BufBegin.green.bp;
117141cc406Sopenharmony_ci
118141cc406Sopenharmony_ci		return SANE_TRUE;
119141cc406Sopenharmony_ci	}
120141cc406Sopenharmony_ci}
121141cc406Sopenharmony_ci
122141cc406Sopenharmony_ci/**
123141cc406Sopenharmony_ci */
124141cc406Sopenharmony_cistatic SANE_Bool fnReadOutScanner( U12_Device *dev )
125141cc406Sopenharmony_ci{
126141cc406Sopenharmony_ci	if( dev->scan.bd_rk.wBlueDiscard ) {
127141cc406Sopenharmony_ci
128141cc406Sopenharmony_ci		dev->scan.bd_rk.wBlueDiscard--;
129141cc406Sopenharmony_ci		dev->regs.RD_ModeControl = _ModeFifoBSel;
130141cc406Sopenharmony_ci
131141cc406Sopenharmony_ci		u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf,
132141cc406Sopenharmony_ci		                dev->DataInf.dwAsicBytesPerPlane );
133141cc406Sopenharmony_ci
134141cc406Sopenharmony_ci		if( dev->scan.gd_gk.wGreenDiscard ) {
135141cc406Sopenharmony_ci			dev->scan.gd_gk.wGreenDiscard--;
136141cc406Sopenharmony_ci
137141cc406Sopenharmony_ci			dev->regs.RD_ModeControl = _ModeFifoGSel;
138141cc406Sopenharmony_ci			u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf,
139141cc406Sopenharmony_ci			                    dev->DataInf.dwAsicBytesPerPlane );
140141cc406Sopenharmony_ci		}
141141cc406Sopenharmony_ci		return SANE_FALSE;
142141cc406Sopenharmony_ci
143141cc406Sopenharmony_ci	} else {
144141cc406Sopenharmony_ci		u12io_ReadColorData( dev, dev->bufs.b1.pReadBuf,
145141cc406Sopenharmony_ci		                     dev->DataInf.dwAsicBytesPerPlane );
146141cc406Sopenharmony_ci		return SANE_TRUE;
147141cc406Sopenharmony_ci	}
148141cc406Sopenharmony_ci}
149141cc406Sopenharmony_ci
150141cc406Sopenharmony_ci/** some sampling functions
151141cc406Sopenharmony_ci */
152141cc406Sopenharmony_cistatic SANE_Bool fnEveryLine( U12_Device *dev )
153141cc406Sopenharmony_ci{
154141cc406Sopenharmony_ci	_VAR_NOT_USED( dev );
155141cc406Sopenharmony_ci	return SANE_TRUE;
156141cc406Sopenharmony_ci}
157141cc406Sopenharmony_ci
158141cc406Sopenharmony_cistatic SANE_Bool fnSampleLines( U12_Device *dev )
159141cc406Sopenharmony_ci{
160141cc406Sopenharmony_ci	dev->DataInf.wYSum += dev->DataInf.xyAppDpi.y;
161141cc406Sopenharmony_ci
162141cc406Sopenharmony_ci	if( dev->DataInf.wYSum >= dev->DataInf.xyPhyDpi.y ) {
163141cc406Sopenharmony_ci		dev->DataInf.wYSum -= dev->DataInf.xyPhyDpi.y;
164141cc406Sopenharmony_ci		return	SANE_TRUE;
165141cc406Sopenharmony_ci	}
166141cc406Sopenharmony_ci	return SANE_FALSE;
167141cc406Sopenharmony_ci}
168141cc406Sopenharmony_ci
169141cc406Sopenharmony_cistatic SANE_Bool fnSamplePreview( U12_Device *dev )
170141cc406Sopenharmony_ci{
171141cc406Sopenharmony_ci	dev->DataInf.wYSum += wPreviewScanned;
172141cc406Sopenharmony_ci	if( dev->DataInf.wYSum >= 150 ) {
173141cc406Sopenharmony_ci
174141cc406Sopenharmony_ci		dev->DataInf.wYSum -= 150;
175141cc406Sopenharmony_ci		return SANE_TRUE;
176141cc406Sopenharmony_ci	}
177141cc406Sopenharmony_ci
178141cc406Sopenharmony_ci	return SANE_FALSE;
179141cc406Sopenharmony_ci}
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci/** this function is used when
182141cc406Sopenharmony_ci * - the data type is B/W or GrayScale.
183141cc406Sopenharmony_ci * - the required horizontal resolution doesn't exceed the optic spec.
184141cc406Sopenharmony_ci * - the required vertical resolution exceeds the optic spec.
185141cc406Sopenharmony_ci */
186141cc406Sopenharmony_cistatic void fnDataDirect( U12_Device *dev, void *src, void *dest, u_long len )
187141cc406Sopenharmony_ci{
188141cc406Sopenharmony_ci	_VAR_NOT_USED( dev );
189141cc406Sopenharmony_ci	memcpy( dest, src, len );
190141cc406Sopenharmony_ci}
191141cc406Sopenharmony_ci
192141cc406Sopenharmony_ci/** merges the color planes to pixels style without enlarge operation.
193141cc406Sopenharmony_ci */
194141cc406Sopenharmony_cistatic void fnColorDirect( U12_Device *dev, void *pb, void *img, u_long len )
195141cc406Sopenharmony_ci{
196141cc406Sopenharmony_ci	SANE_Byte  *src;
197141cc406Sopenharmony_ci	RGBByteDef *dest;
198141cc406Sopenharmony_ci
199141cc406Sopenharmony_ci	src  = (SANE_Byte*)img;
200141cc406Sopenharmony_ci	dest = (RGBByteDef*)pb;
201141cc406Sopenharmony_ci
202141cc406Sopenharmony_ci	for ( len = dev->DataInf.dwAsicPixelsPerPlane; len; len--, src++, dest++) {
203141cc406Sopenharmony_ci
204141cc406Sopenharmony_ci		dest->Red   = *src;
205141cc406Sopenharmony_ci		dest->Green = src[dev->DataInf.dwAsicPixelsPerPlane];
206141cc406Sopenharmony_ci		dest->Blue  = src[dev->DataInf.dwAsicPixelsPerPlane*2];
207141cc406Sopenharmony_ci	}
208141cc406Sopenharmony_ci}
209141cc406Sopenharmony_ci
210141cc406Sopenharmony_ci/** merges the color planes to pixels style without enlarge operation.
211141cc406Sopenharmony_ci *  The scanner returns the pixel data in Motorola-Format, so we have to swap
212141cc406Sopenharmony_ci *  (at least on x86)
213141cc406Sopenharmony_ci */
214141cc406Sopenharmony_cistatic void fnColor42( U12_Device *dev, void *pb, void *img, u_long len )
215141cc406Sopenharmony_ci{
216141cc406Sopenharmony_ci	u_short      *src;
217141cc406Sopenharmony_ci	RGBUShortDef *dest;
218141cc406Sopenharmony_ci
219141cc406Sopenharmony_ci	register u_long i;
220141cc406Sopenharmony_ci
221141cc406Sopenharmony_ci	_VAR_NOT_USED( len );
222141cc406Sopenharmony_ci	src  = (u_short*)img;
223141cc406Sopenharmony_ci	dest = (RGBUShortDef*)pb;
224141cc406Sopenharmony_ci
225141cc406Sopenharmony_ci	for ( i = dev->DataInf.dwAsicPixelsPerPlane; i; i--, src++, dest++) {
226141cc406Sopenharmony_ci
227141cc406Sopenharmony_ci		dest->Red   = (*src) << 4;
228141cc406Sopenharmony_ci		dest->Green = (src[dev->DataInf.dwAsicPixelsPerPlane]) << 4;
229141cc406Sopenharmony_ci		dest->Blue  = (src[dev->DataInf.dwAsicPixelsPerPlane * 2]) << 4;
230141cc406Sopenharmony_ci	}
231141cc406Sopenharmony_ci}
232141cc406Sopenharmony_ci
233141cc406Sopenharmony_ci/**
234141cc406Sopenharmony_ci */
235141cc406Sopenharmony_cistatic void u12image_SetupScanStateVariables( U12_Device *dev, u_long index )
236141cc406Sopenharmony_ci{
237141cc406Sopenharmony_ci	DataType var;
238141cc406Sopenharmony_ci
239141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12image_SetupScanStateVariables(%lu)\n", index );
240141cc406Sopenharmony_ci	dev->scan.dpiIdx = index;
241141cc406Sopenharmony_ci
242141cc406Sopenharmony_ci	if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA)) {
243141cc406Sopenharmony_ci
244141cc406Sopenharmony_ci		dev->shade.wExposure = nmlScan[index].exposureTime;
245141cc406Sopenharmony_ci		dev->shade.wXStep     = nmlScan[index].xStepTime;
246141cc406Sopenharmony_ci
247141cc406Sopenharmony_ci		if( dev->shade.intermediate & _ScanMode_AverageOut ) {
248141cc406Sopenharmony_ci			dev->shade.wExposure >>= 1;
249141cc406Sopenharmony_ci			dev->shade.wXStep    >>= 1;
250141cc406Sopenharmony_ci		}
251141cc406Sopenharmony_ci	} else {
252141cc406Sopenharmony_ci		if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency ) {
253141cc406Sopenharmony_ci			dev->shade.wExposure = posScan[index].exposureTime;
254141cc406Sopenharmony_ci			dev->shade.wXStep    = posScan[index].xStepTime;
255141cc406Sopenharmony_ci		} else {
256141cc406Sopenharmony_ci			dev->shade.wExposure = dev->scan.negScan[index].exposureTime;
257141cc406Sopenharmony_ci			dev->shade.wXStep    = dev->scan.negScan[index].xStepTime;
258141cc406Sopenharmony_ci		}
259141cc406Sopenharmony_ci	}
260141cc406Sopenharmony_ci	dev->scan.dwInterval = 1;
261141cc406Sopenharmony_ci
262141cc406Sopenharmony_ci	if( dev->DataInf.wPhyDataType == COLOR_BW )
263141cc406Sopenharmony_ci		var.dwValue = 0;
264141cc406Sopenharmony_ci	else {
265141cc406Sopenharmony_ci		if( dev->DataInf.wPhyDataType == COLOR_256GRAY )
266141cc406Sopenharmony_ci    		var.dwValue = 2500;
267141cc406Sopenharmony_ci		else
268141cc406Sopenharmony_ci			var.dwValue = 3200;
269141cc406Sopenharmony_ci	}
270141cc406Sopenharmony_ci
271141cc406Sopenharmony_ci	/* for small size/descreen */
272141cc406Sopenharmony_ci	if((dev->DataInf.xyAppDpi.y >= 300) && var.dwValue &&
273141cc406Sopenharmony_ci	   (dev->DataInf.dwAsicBytesPerPlane <= var.dwValue)) {
274141cc406Sopenharmony_ci		dev->scan.dwInterval <<= 1;
275141cc406Sopenharmony_ci	}
276141cc406Sopenharmony_ci
277141cc406Sopenharmony_ci	if( var.dwValue && dev->DataInf.dwAsicBytesPerPlane > var.dwValue ) {
278141cc406Sopenharmony_ci		if((var.dwValue << 1) > dev->DataInf.dwAsicBytesPerPlane)
279141cc406Sopenharmony_ci			dev->scan.dwInterval <<= 1;
280141cc406Sopenharmony_ci		else
281141cc406Sopenharmony_ci			if((var.dwValue << 2) > dev->DataInf.dwAsicBytesPerPlane)
282141cc406Sopenharmony_ci				dev->scan.dwInterval <<= 2;
283141cc406Sopenharmony_ci			else
284141cc406Sopenharmony_ci				dev->scan.dwInterval <<= 3;
285141cc406Sopenharmony_ci	}
286141cc406Sopenharmony_ci
287141cc406Sopenharmony_ci	if( dev->DataInf.wPhyDataType >= COLOR_TRUE24 ) {
288141cc406Sopenharmony_ci
289141cc406Sopenharmony_ci		if( dev->DataInf.xyPhyDpi.y > 75U ) {
290141cc406Sopenharmony_ci			if( dev->f0_8_16 ) {
291141cc406Sopenharmony_ci				dev->scan.gd_gk.wGreenDiscard = dev->DataInf.xyPhyDpi.y / 75U;
292141cc406Sopenharmony_ci			} else {
293141cc406Sopenharmony_ci				dev->scan.gd_gk.wGreenDiscard = dev->DataInf.xyPhyDpi.y / 150U;
294141cc406Sopenharmony_ci			}
295141cc406Sopenharmony_ci		} else {
296141cc406Sopenharmony_ci			dev->scan.gd_gk.wGreenDiscard = 1;
297141cc406Sopenharmony_ci		}
298141cc406Sopenharmony_ci
299141cc406Sopenharmony_ci		dev->scan.bd_rk.wBlueDiscard = dev->scan.gd_gk.wGreenDiscard << 1;
300141cc406Sopenharmony_ci	} else {
301141cc406Sopenharmony_ci		dev->scan.bd_rk.wBlueDiscard = dev->scan.gd_gk.wGreenDiscard = 0;
302141cc406Sopenharmony_ci	}
303141cc406Sopenharmony_ci}
304141cc406Sopenharmony_ci
305141cc406Sopenharmony_ci/** limit the resolution
306141cc406Sopenharmony_ci */
307141cc406Sopenharmony_cistatic u_short
308141cc406Sopenharmony_ciu12image_GetPhysDPI( U12_Device *dev, ImgDef *img, SANE_Bool fDpiX )
309141cc406Sopenharmony_ci{
310141cc406Sopenharmony_ci	if( fDpiX ) {
311141cc406Sopenharmony_ci
312141cc406Sopenharmony_ci		if( img->xyDpi.x > dev->dpi_max_x )
313141cc406Sopenharmony_ci			return dev->dpi_max_x;
314141cc406Sopenharmony_ci		else
315141cc406Sopenharmony_ci			return img->xyDpi.x;
316141cc406Sopenharmony_ci
317141cc406Sopenharmony_ci	} else {
318141cc406Sopenharmony_ci
319141cc406Sopenharmony_ci		if( img->xyDpi.y > dev->dpi_max_y )
320141cc406Sopenharmony_ci				return dev->dpi_max_y;
321141cc406Sopenharmony_ci		else
322141cc406Sopenharmony_ci			return img->xyDpi.y;
323141cc406Sopenharmony_ci	}
324141cc406Sopenharmony_ci}
325141cc406Sopenharmony_ci
326141cc406Sopenharmony_ci/** calculate the image properties according to the scanmode
327141cc406Sopenharmony_ci *  set all internally needed information
328141cc406Sopenharmony_ci */
329141cc406Sopenharmony_cistatic void u12image_GetImageInfo( U12_Device *dev, ImgDef *image )
330141cc406Sopenharmony_ci{
331141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12image_GetImageInfo()\n" );
332141cc406Sopenharmony_ci
333141cc406Sopenharmony_ci	dev->DataInf.xyPhyDpi.x = u12image_GetPhysDPI(dev, image, SANE_TRUE );
334141cc406Sopenharmony_ci	dev->DataInf.xyPhyDpi.y = u12image_GetPhysDPI(dev, image, SANE_FALSE);
335141cc406Sopenharmony_ci
336141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* xyPhyDpi.x = %u, xyPhyDpi.y = %u\n",
337141cc406Sopenharmony_ci	                dev->DataInf.xyPhyDpi.x, dev->DataInf.xyPhyDpi.y );
338141cc406Sopenharmony_ci
339141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* crArea.x = %u, crArea.y = %u\n",
340141cc406Sopenharmony_ci	                image->crArea.x, image->crArea.y );
341141cc406Sopenharmony_ci
342141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* crArea.cx = %u, crArea.cy = %u\n",
343141cc406Sopenharmony_ci	                image->crArea.cx, image->crArea.cy );
344141cc406Sopenharmony_ci
345141cc406Sopenharmony_ci	dev->DataInf.xyRatio = (double)dev->DataInf.xyPhyDpi.y/
346141cc406Sopenharmony_ci	                       (double)dev->DataInf.xyPhyDpi.x;
347141cc406Sopenharmony_ci
348141cc406Sopenharmony_ci	dev->DataInf.dwAppLinesPerArea = (u_long)image->crArea.cy *
349141cc406Sopenharmony_ci									  image->xyDpi.y / _MEASURE_BASE;
350141cc406Sopenharmony_ci
351141cc406Sopenharmony_ci    dev->DataInf.dwAppPixelsPerLine = (u_long)image->crArea.cx *
352141cc406Sopenharmony_ci									   image->xyDpi.x / _MEASURE_BASE;
353141cc406Sopenharmony_ci
354141cc406Sopenharmony_ci	dev->DataInf.dwPhysBytesPerLine = (u_long)image->crArea.cx *
355141cc406Sopenharmony_ci									   dev->DataInf.xyPhyDpi.x / _MEASURE_BASE;
356141cc406Sopenharmony_ci
357141cc406Sopenharmony_ci    if( image->wDataType <= COLOR_BW ) {
358141cc406Sopenharmony_ci		dev->DataInf.dwAsicPixelsPerPlane =
359141cc406Sopenharmony_ci		                  (dev->DataInf.dwAppPixelsPerLine+7UL) & 0xfffffff8UL;
360141cc406Sopenharmony_ci		dev->DataInf.dwAppPhyBytesPerLine =
361141cc406Sopenharmony_ci		dev->DataInf.dwAppBytesPerLine 	  =
362141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerLine   =
363141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerPlane  = dev->DataInf.dwAsicPixelsPerPlane>>3;
364141cc406Sopenharmony_ci    } else {
365141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerPlane  =
366141cc406Sopenharmony_ci		dev->DataInf.dwAsicPixelsPerPlane = dev->DataInf.dwAppPixelsPerLine;
367141cc406Sopenharmony_ci	}
368141cc406Sopenharmony_ci
369141cc406Sopenharmony_ci	if( COLOR_TRUE42 == image->wDataType ) {
370141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerPlane *= 2;
371141cc406Sopenharmony_ci	}
372141cc406Sopenharmony_ci
373141cc406Sopenharmony_ci	switch( image->wDataType ) {
374141cc406Sopenharmony_ci
375141cc406Sopenharmony_ci	case COLOR_BW:
376141cc406Sopenharmony_ci		dev->scan.DataProcess     = fnDataDirect;
377141cc406Sopenharmony_ci		dev->DataInf.wPhyDataType = COLOR_BW;
378141cc406Sopenharmony_ci		dev->shade.intermediate   = _ScanMode_Mono;
379141cc406Sopenharmony_ci		break;
380141cc406Sopenharmony_ci
381141cc406Sopenharmony_ci	case COLOR_256GRAY:
382141cc406Sopenharmony_ci		dev->scan.DataProcess     = fnDataDirect;
383141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerLine =
384141cc406Sopenharmony_ci		dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine;
385141cc406Sopenharmony_ci		dev->DataInf.wPhyDataType = COLOR_256GRAY;
386141cc406Sopenharmony_ci		dev->shade.intermediate   = _ScanMode_Mono;
387141cc406Sopenharmony_ci		break;
388141cc406Sopenharmony_ci
389141cc406Sopenharmony_ci	case COLOR_TRUE24:
390141cc406Sopenharmony_ci		dev->scan.DataProcess = fnColorDirect;
391141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerLine =
392141cc406Sopenharmony_ci		dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine * 3;
393141cc406Sopenharmony_ci		dev->DataInf.wPhyDataType = COLOR_TRUE24;
394141cc406Sopenharmony_ci		dev->shade.intermediate  = _ScanMode_Color;
395141cc406Sopenharmony_ci		break;
396141cc406Sopenharmony_ci
397141cc406Sopenharmony_ci	case COLOR_TRUE42:
398141cc406Sopenharmony_ci		dev->scan.DataProcess = fnColor42;
399141cc406Sopenharmony_ci		dev->DataInf.dwAsicBytesPerLine =
400141cc406Sopenharmony_ci		dev->DataInf.dwAppPhyBytesPerLine = dev->DataInf.dwAppPixelsPerLine * 6;
401141cc406Sopenharmony_ci		dev->DataInf.wPhyDataType = COLOR_TRUE42;
402141cc406Sopenharmony_ci		dev->shade.intermediate  = _ScanMode_Color;
403141cc406Sopenharmony_ci		break;
404141cc406Sopenharmony_ci	}
405141cc406Sopenharmony_ci
406141cc406Sopenharmony_ci	/* raus mit einem von beiden!!!!*/
407141cc406Sopenharmony_ci	dev->DataInf.dwAppBytesPerLine = dev->DataInf.dwAppPhyBytesPerLine;
408141cc406Sopenharmony_ci
409141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AppLinesPerArea    = %lu\n", dev->DataInf.dwAppLinesPerArea    );
410141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AppPixelsPerLine   = %lu\n", dev->DataInf.dwAppPixelsPerLine   );
411141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AppPhyBytesPerLine = %lu\n", dev->DataInf.dwAppPhyBytesPerLine );
412141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AppBytesPerLine    = %lu\n", dev->DataInf.dwAppBytesPerLine    );
413141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AsicPixelsPerPlane = %lu\n", dev->DataInf.dwAsicPixelsPerPlane );
414141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AsicBytesPerPlane  = %lu\n", dev->DataInf.dwAsicBytesPerPlane  );
415141cc406Sopenharmony_ci	DBG( _DBG_INFO, "AsicBytesPerLine   = %lu\n", dev->DataInf.dwAsicBytesPerLine   );
416141cc406Sopenharmony_ci	DBG( _DBG_INFO, "Physical Bytes     = %lu\n", dev->DataInf.dwPhysBytesPerLine   );
417141cc406Sopenharmony_ci}
418141cc406Sopenharmony_ci
419141cc406Sopenharmony_ci/**
420141cc406Sopenharmony_ci */
421141cc406Sopenharmony_cistatic int imageSetupScanSettings( U12_Device *dev, ImgDef *img )
422141cc406Sopenharmony_ci{
423141cc406Sopenharmony_ci	u_short brightness;
424141cc406Sopenharmony_ci
425141cc406Sopenharmony_ci	DBG( _DBG_INFO, "imageSetupScanSettings()\n" );
426141cc406Sopenharmony_ci
427141cc406Sopenharmony_ci	dev->DataInf.dwScanFlag = img->dwFlag;
428141cc406Sopenharmony_ci	dev->DataInf.crImage    = img->crArea;
429141cc406Sopenharmony_ci
430141cc406Sopenharmony_ci	DBG( _DBG_INFO,"* DataInf.dwScanFlag = 0x%08lx\n",dev->DataInf.dwScanFlag);
431141cc406Sopenharmony_ci
432141cc406Sopenharmony_ci	dev->DataInf.crImage.x <<= 1;
433141cc406Sopenharmony_ci
434141cc406Sopenharmony_ci	dev->DataInf.xyAppDpi     = img->xyDpi;
435141cc406Sopenharmony_ci	dev->DataInf.wAppDataType = img->wDataType;
436141cc406Sopenharmony_ci
437141cc406Sopenharmony_ci	u12image_GetImageInfo( dev, img );
438141cc406Sopenharmony_ci
439141cc406Sopenharmony_ci	dev->scan.lBufferAdjust = (long)dev->DataInf.dwAppBytesPerLine;
440141cc406Sopenharmony_ci
441141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* Scan settings:\n" );
442141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* ImageInfo: (x=%u,y=%u,dx=%u,dy=%u)\n",
443141cc406Sopenharmony_ci			 dev->DataInf.crImage.x,  dev->DataInf.crImage.y,
444141cc406Sopenharmony_ci			 dev->DataInf.crImage.cx, dev->DataInf.crImage.cy );
445141cc406Sopenharmony_ci
446141cc406Sopenharmony_ci	/*
447141cc406Sopenharmony_ci	 * 0                   _DEF_BW_THRESHOLD                     255
448141cc406Sopenharmony_ci	 * +-------------------------+--------------------------------+
449141cc406Sopenharmony_ci	 * |<------- Black --------->|<----------- White ------------>|
450141cc406Sopenharmony_ci	 *  So, if user wish to make image darker, the threshold value should be
451141cc406Sopenharmony_ci	 *  higher than _defBwThreshold, otherwise it should lower than the
452141cc406Sopenharmony_ci	 *  _DefBwThreshold.
453141cc406Sopenharmony_ci	 *  Darker = _DEF_BW_THRESHOLD + White * Input / 127;
454141cc406Sopenharmony_ci	 *             Input < 0, and White = 255 - _DEF_BW_THRESHOLD, so
455141cc406Sopenharmony_ci	 *           = _DEF_BW_THRESHOLD - (255 - _DEF_BW_THRESHOLD) * Input / 127;
456141cc406Sopenharmony_ci	 *  The brighter is the same idea.
457141cc406Sopenharmony_ci	 */
458141cc406Sopenharmony_ci
459141cc406Sopenharmony_ci/* CHECK: We have now two methods for setting the brightness...
460141cc406Sopenharmony_ci*/
461141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* brightness = %i\n", dev->DataInf.siBrightness );
462141cc406Sopenharmony_ci	if ( dev->DataInf.siBrightness < 0) {
463141cc406Sopenharmony_ci		brightness = (u_short)(_DEF_BW_THRESHOLD -
464141cc406Sopenharmony_ci			       (255 - _DEF_BW_THRESHOLD) * dev->DataInf.siBrightness /127);
465141cc406Sopenharmony_ci	} else {
466141cc406Sopenharmony_ci		brightness = (u_short)(_DEF_BW_THRESHOLD -
467141cc406Sopenharmony_ci					       _DEF_BW_THRESHOLD * dev->DataInf.siBrightness /127);
468141cc406Sopenharmony_ci	}
469141cc406Sopenharmony_ci
470141cc406Sopenharmony_ci	dev->regs.RD_ThresholdControl = brightness;
471141cc406Sopenharmony_ci	DBG( _DBG_INFO, "* RD_ThresholdControl = %i\n", brightness );
472141cc406Sopenharmony_ci	return 0;
473141cc406Sopenharmony_ci}
474141cc406Sopenharmony_ci
475141cc406Sopenharmony_ci/** PrepareScanningVariables() !!!
476141cc406Sopenharmony_ci */
477141cc406Sopenharmony_cistatic SANE_Status u12image_SetupScanSettings( U12_Device *dev, ImgDef *img )
478141cc406Sopenharmony_ci{
479141cc406Sopenharmony_ci	DBG( _DBG_INFO, "u12image_SetupScanSettings()\n" );
480141cc406Sopenharmony_ci
481141cc406Sopenharmony_ci	wPreviewScanned   = 0;
482141cc406Sopenharmony_ci	dev->scan.dpiIdx  = 0;
483141cc406Sopenharmony_ci	dev->scan.negScan = negScan;
484141cc406Sopenharmony_ci
485141cc406Sopenharmony_ci	imageSetupScanSettings( dev, img );
486141cc406Sopenharmony_ci
487141cc406Sopenharmony_ci	if( !(dev->DataInf.dwScanFlag & _SCANDEF_TPA )) {
488141cc406Sopenharmony_ci
489141cc406Sopenharmony_ci		dev->scan.dwScanOrigin = dev->adj.upNormal * 4 + _RFT_SCANNING_ORG;
490141cc406Sopenharmony_ci
491141cc406Sopenharmony_ci	} else if( dev->DataInf.dwScanFlag & _SCANDEF_Transparency) {
492141cc406Sopenharmony_ci
493141cc406Sopenharmony_ci		dev->scan.dwScanOrigin = dev->adj.upPositive * 4 + _POS_SCANNING_ORG;
494141cc406Sopenharmony_ci	} else {
495141cc406Sopenharmony_ci		dev->scan.dwScanOrigin = dev->adj.upNegative * 4 + _NEG_SCANNING_ORG;
496141cc406Sopenharmony_ci	}
497141cc406Sopenharmony_ci	dev->scan.dwScanOrigin += 64 /*dev->dwModelOriginY*/;
498141cc406Sopenharmony_ci
499141cc406Sopenharmony_ci	if( dev->DataInf.xyAppDpi.y <= 75 ) {
500141cc406Sopenharmony_ci
501141cc406Sopenharmony_ci		if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) {
502141cc406Sopenharmony_ci
503141cc406Sopenharmony_ci			dev->scan.bDiscardAll   = 0;
504141cc406Sopenharmony_ci			dev->DataInf.xyPhyDpi.y = 150;
505141cc406Sopenharmony_ci			dev->shade.intermediate |= _ScanMode_AverageOut;
506141cc406Sopenharmony_ci			u12image_SetupScanStateVariables( dev, 1 );
507141cc406Sopenharmony_ci	        dev->scan.gd_gk.wGreenDiscard = 0;
508141cc406Sopenharmony_ci
509141cc406Sopenharmony_ci			if( dev->DataInf.xyAppDpi.y >= 38 )
510141cc406Sopenharmony_ci				dev->scan.bd_rk.wBlueDiscard = 1;
511141cc406Sopenharmony_ci			else
512141cc406Sopenharmony_ci				dev->scan.bd_rk.wBlueDiscard = 0;
513141cc406Sopenharmony_ci
514141cc406Sopenharmony_ci			if( dev->DataInf.wPhyDataType >= COLOR_256GRAY ) {
515141cc406Sopenharmony_ci				dev->shade.wXStep    = 6;
516141cc406Sopenharmony_ci				dev->shade.wExposure = 8 * dev->shade.wXStep;
517141cc406Sopenharmony_ci			}
518141cc406Sopenharmony_ci		} else {
519141cc406Sopenharmony_ci			if(!(dev->DataInf.dwScanFlag & _SCANDEF_TPA) &&
520141cc406Sopenharmony_ci			    (dev->DataInf.xyAppDpi.y <= 50) &&
521141cc406Sopenharmony_ci			    (dev->DataInf.wPhyDataType >= COLOR_TRUE24)) {
522141cc406Sopenharmony_ci				dev->shade.intermediate |= _ScanMode_AverageOut;
523141cc406Sopenharmony_ci			}
524141cc406Sopenharmony_ci
525141cc406Sopenharmony_ci			if((dev->DataInf.wPhyDataType<COLOR_TRUE24) || dev->f0_8_16 ||
526141cc406Sopenharmony_ci			         (dev->shade.intermediate & _ScanMode_AverageOut)) {
527141cc406Sopenharmony_ci
528141cc406Sopenharmony_ci				dev->scan.bDiscardAll   = 1;
529141cc406Sopenharmony_ci				dev->DataInf.xyPhyDpi.y = 75;
530141cc406Sopenharmony_ci				u12image_SetupScanStateVariables( dev, 0 );
531141cc406Sopenharmony_ci    		} else {
532141cc406Sopenharmony_ci				dev->scan.bDiscardAll   = 2;
533141cc406Sopenharmony_ci				dev->DataInf.xyPhyDpi.y = 150;
534141cc406Sopenharmony_ci				u12image_SetupScanStateVariables( dev, 1 );
535141cc406Sopenharmony_ci			}
536141cc406Sopenharmony_ci		}
537141cc406Sopenharmony_ci	} else {
538141cc406Sopenharmony_ci		if( dev->DataInf.xyAppDpi.y <= 150 ) {
539141cc406Sopenharmony_ci
540141cc406Sopenharmony_ci			dev->scan.bDiscardAll   = 2;
541141cc406Sopenharmony_ci			dev->DataInf.xyPhyDpi.y = 150;
542141cc406Sopenharmony_ci			u12image_SetupScanStateVariables( dev, 1 );
543141cc406Sopenharmony_ci
544141cc406Sopenharmony_ci		} else if( dev->DataInf.xyAppDpi.y <= 300 ) {
545141cc406Sopenharmony_ci
546141cc406Sopenharmony_ci			dev->scan.bDiscardAll   = 4;
547141cc406Sopenharmony_ci			dev->DataInf.xyPhyDpi.y = 300;
548141cc406Sopenharmony_ci			u12image_SetupScanStateVariables( dev, 2 );
549141cc406Sopenharmony_ci
550141cc406Sopenharmony_ci		} else if( dev->DataInf.xyAppDpi.y <= 600 ) {
551141cc406Sopenharmony_ci
552141cc406Sopenharmony_ci			dev->scan.bDiscardAll   = 8;
553141cc406Sopenharmony_ci			dev->DataInf.xyPhyDpi.y = 600;
554141cc406Sopenharmony_ci			u12image_SetupScanStateVariables( dev, 3 );
555141cc406Sopenharmony_ci
556141cc406Sopenharmony_ci		} else {
557141cc406Sopenharmony_ci
558141cc406Sopenharmony_ci			dev->scan.bDiscardAll   = 16;
559141cc406Sopenharmony_ci			dev->DataInf.xyPhyDpi.y = 1200;
560141cc406Sopenharmony_ci			u12image_SetupScanStateVariables( dev, 4 );
561141cc406Sopenharmony_ci		}
562141cc406Sopenharmony_ci	}
563141cc406Sopenharmony_ci
564141cc406Sopenharmony_ci	/* ------- lines to sample or not? ------- */
565141cc406Sopenharmony_ci	if( dev->DataInf.xyAppDpi.y == dev->DataInf.xyPhyDpi.y ) {
566141cc406Sopenharmony_ci		DBG( _DBG_INFO, "* Sample every line\n" );
567141cc406Sopenharmony_ci		dev->scan.DoSample = fnEveryLine;
568141cc406Sopenharmony_ci	} else {
569141cc406Sopenharmony_ci		if( dev->DataInf.dwScanFlag & _SCANDEF_PREVIEW ) {
570141cc406Sopenharmony_ci
571141cc406Sopenharmony_ci			DBG( _DBG_INFO, "* Sample preview\n" );
572141cc406Sopenharmony_ci			dev->scan.DoSample = fnSamplePreview;
573141cc406Sopenharmony_ci			dev->DataInf.wYSum = 150;
574141cc406Sopenharmony_ci
575141cc406Sopenharmony_ci			if( dev->DataInf.xyAppDpi.y >= 38 )
576141cc406Sopenharmony_ci				wPreviewScanned = dev->DataInf.xyAppDpi.y * 2;
577141cc406Sopenharmony_ci			else if( dev->DataInf.xyAppDpi.y >= 19 )
578141cc406Sopenharmony_ci				wPreviewScanned = dev->DataInf.xyAppDpi.y * 4;
579141cc406Sopenharmony_ci			else
580141cc406Sopenharmony_ci				wPreviewScanned = dev->DataInf.xyAppDpi.y * 8;
581141cc406Sopenharmony_ci		} else {
582141cc406Sopenharmony_ci
583141cc406Sopenharmony_ci			DBG( _DBG_INFO, "* Sample lines (%u - %u)...\n",
584141cc406Sopenharmony_ci						  dev->DataInf.xyPhyDpi.y, dev->DataInf.xyAppDpi.y );
585141cc406Sopenharmony_ci			dev->scan.DoSample = fnSampleLines;
586141cc406Sopenharmony_ci			dev->DataInf.wYSum = dev->DataInf.xyPhyDpi.y - dev->DataInf.xyAppDpi.y;
587141cc406Sopenharmony_ci		}
588141cc406Sopenharmony_ci	}
589141cc406Sopenharmony_ci
590141cc406Sopenharmony_ci	/* now assign the buffer pointers for image acquisition
591141cc406Sopenharmony_ci	 */
592141cc406Sopenharmony_ci	dev->scan.p48BitBuf.pb = NULL;
593141cc406Sopenharmony_ci
594141cc406Sopenharmony_ci	if( dev->DataInf.wPhyDataType >= COLOR_TRUE24 ) {
595141cc406Sopenharmony_ci
596141cc406Sopenharmony_ci		u_long r, g, b;
597141cc406Sopenharmony_ci
598141cc406Sopenharmony_ci		r = (u_long)_SIZE_REDFIFO /
599141cc406Sopenharmony_ci			dev->DataInf.dwAsicBytesPerPlane - dev->scan.bd_rk.wRedKeep;
600141cc406Sopenharmony_ci		g = (u_long)_SIZE_GREENFIFO /
601141cc406Sopenharmony_ci			dev->DataInf.dwAsicBytesPerPlane - dev->scan.gd_gk.wGreenKeep;
602141cc406Sopenharmony_ci
603141cc406Sopenharmony_ci		if((int)r < 16 || (int)g < 16) {
604141cc406Sopenharmony_ci
605141cc406Sopenharmony_ci			b = (u_long)(dev->scan.bd_rk.wRedKeep +
606141cc406Sopenharmony_ci			             dev->scan.gd_gk.wGreenKeep + 2U) *
607141cc406Sopenharmony_ci			             dev->DataInf.dwAsicBytesPerPlane;
608141cc406Sopenharmony_ci
609141cc406Sopenharmony_ci			DBG( _DBG_INFO, "48Bit buffer request: "
610141cc406Sopenharmony_ci			     "len=%lu bytes, available=%lu\n", b, _SIZE_TOTAL_BUF_TPA );
611141cc406Sopenharmony_ci
612141cc406Sopenharmony_ci			if( b > _SIZE_TOTAL_BUF_TPA ) {
613141cc406Sopenharmony_ci				DBG( _DBG_ERROR, "Not that much FIFO memory available!\n" );
614141cc406Sopenharmony_ci				return SANE_STATUS_NO_MEM;
615141cc406Sopenharmony_ci			}
616141cc406Sopenharmony_ci
617141cc406Sopenharmony_ci			dev->scan.p48BitBuf.pb = dev->bufs.b1.pReadBuf;
618141cc406Sopenharmony_ci		}
619141cc406Sopenharmony_ci	}
620141cc406Sopenharmony_ci
621141cc406Sopenharmony_ci	if( dev->scan.p48BitBuf.pb ){
622141cc406Sopenharmony_ci		dev->scan.DataRead          = fnReadToDriver;
623141cc406Sopenharmony_ci		dev->scan.BufGet.red.bp     =
624141cc406Sopenharmony_ci		dev->scan.BufPut.red.bp     =
625141cc406Sopenharmony_ci		dev->scan.BufBegin.red.bp   = dev->scan.p48BitBuf.pb;
626141cc406Sopenharmony_ci		dev->scan.BufEnd.red.bp     =
627141cc406Sopenharmony_ci		dev->scan.BufBegin.green.bp =
628141cc406Sopenharmony_ci		dev->scan.BufGet.green.bp   =
629141cc406Sopenharmony_ci		dev->scan.BufPut.green.bp   = dev->scan.p48BitBuf.pb +
630141cc406Sopenharmony_ci		                              dev->DataInf.dwAsicBytesPerLine *
631141cc406Sopenharmony_ci		                              (dev->scan.bd_rk.wRedKeep + 1U);
632141cc406Sopenharmony_ci
633141cc406Sopenharmony_ci		dev->scan.BufEnd.green.bp = dev->scan.BufBegin.green.bp +
634141cc406Sopenharmony_ci		                            dev->DataInf.dwAsicBytesPerLine *
635141cc406Sopenharmony_ci		                            (dev->scan.gd_gk.wGreenKeep + 1U);
636141cc406Sopenharmony_ci		dev->scan.BufPut.blue.bp =
637141cc406Sopenharmony_ci		dev->scan.BufGet.blue.bp = dev->bufs.b1.pReadBuf +
638141cc406Sopenharmony_ci		                           dev->DataInf.dwAsicBytesPerLine * 2;
639141cc406Sopenharmony_ci	} else {
640141cc406Sopenharmony_ci		dev->scan.DataRead         = fnReadOutScanner;
641141cc406Sopenharmony_ci		dev->scan.BufPut.red.bp    = dev->bufs.b1.pReadBuf;
642141cc406Sopenharmony_ci		dev->scan.BufData.green.bp =
643141cc406Sopenharmony_ci		dev->scan.BufPut.green.bp  = dev->scan.BufPut.red.bp +
644141cc406Sopenharmony_ci		                             dev->DataInf.dwAsicBytesPerLine;
645141cc406Sopenharmony_ci		dev->scan.BufPut.blue.bp   = dev->scan.BufPut.green.bp +
646141cc406Sopenharmony_ci		                             dev->DataInf.dwAsicBytesPerLine;
647141cc406Sopenharmony_ci
648141cc406Sopenharmony_ci		dev->scan.BufData.red.bp  = dev->scan.BufPut.red.bp;
649141cc406Sopenharmony_ci		dev->scan.BufData.blue.bp = dev->scan.BufPut.blue.bp;
650141cc406Sopenharmony_ci	}
651141cc406Sopenharmony_ci
652141cc406Sopenharmony_ci/* CHECK: maybe remove this stuff */
653141cc406Sopenharmony_ci#if 0
654141cc406Sopenharmony_ci	if( ps->DataInf.dwScanFlag & _SCANDEF_Transparency) {
655141cc406Sopenharmony_ci	    posScan[1].exposureTime = 96;
656141cc406Sopenharmony_ci	    posScan[1].xStepTime    = 12;
657141cc406Sopenharmony_ci	    posScan[2].exposureTime = 96;
658141cc406Sopenharmony_ci	    posScan[2].xStepTime    = 24;
659141cc406Sopenharmony_ci	    posScan[3].exposureTime = 96;
660141cc406Sopenharmony_ci	    posScan[3].xStepTime    = 48;
661141cc406Sopenharmony_ci	    posScan[4].exposureTime = 96;
662141cc406Sopenharmony_ci	    posScan[4].xStepTime    = 96;
663141cc406Sopenharmony_ci
664141cc406Sopenharmony_ci	    /* Reset shading Exposure Time & xStep Time */
665141cc406Sopenharmony_ci	    ps->Shade.wExposure = posScan[ps->Scan.dpiIdx].exposureTime;
666141cc406Sopenharmony_ci	    ps->Shade.wXStep    = posScan[ps->Scan.dpiIdx].xStepTime;
667141cc406Sopenharmony_ci	}
668141cc406Sopenharmony_ci	else if( ps->DataInf.dwScanFlag & _SCANDEF_Negative) {
669141cc406Sopenharmony_ci        ps->Scan.negScan[1].exposureTime = 96;
670141cc406Sopenharmony_ci        ps->Scan.negScan[1].xStepTime    = 12;
671141cc406Sopenharmony_ci        ps->Scan.negScan[2].exposureTime = 96;
672141cc406Sopenharmony_ci        ps->Scan.negScan[2].xStepTime    = 24;
673141cc406Sopenharmony_ci        ps->Scan.negScan[3].exposureTime = 96;
674141cc406Sopenharmony_ci        ps->Scan.negScan[3].xStepTime    = 48;
675141cc406Sopenharmony_ci        ps->Scan.negScan[4].exposureTime = 96;
676141cc406Sopenharmony_ci        ps->Scan.negScan[4].xStepTime    = 96;
677141cc406Sopenharmony_ci
678141cc406Sopenharmony_ci	    /* Reset shading Exposure Time & xStep Time */
679141cc406Sopenharmony_ci    	ps->Shade.wExposure = ps->Scan.negScan[ps->Scan.dpiIdx].exposureTime;
680141cc406Sopenharmony_ci		ps->Shade.wXStep    = ps->Scan.negScan[ps->Scan.dpiIdx].xStepTime;
681141cc406Sopenharmony_ci    }
682141cc406Sopenharmony_ci#endif
683141cc406Sopenharmony_ci	return SANE_STATUS_GOOD;
684141cc406Sopenharmony_ci}
685141cc406Sopenharmony_ci
686141cc406Sopenharmony_ci/**
687141cc406Sopenharmony_ci */
688141cc406Sopenharmony_cistatic SANE_Bool u12image_DataIsReady( U12_Device *dev, void* buf )
689141cc406Sopenharmony_ci{
690141cc406Sopenharmony_ci	DBG( _DBG_READ, "* DataIsReady()\n" );
691141cc406Sopenharmony_ci
692141cc406Sopenharmony_ci	if( dev->scan.bDiscardAll ) {
693141cc406Sopenharmony_ci		dev->scan.bDiscardAll--;
694141cc406Sopenharmony_ci
695141cc406Sopenharmony_ci		if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
696141cc406Sopenharmony_ci			dev->regs.RD_ModeControl = _ModeFifoGSel;
697141cc406Sopenharmony_ci			u12io_ReadMonoData( dev, dev->bufs.b1.pReadBuf,
698141cc406Sopenharmony_ci			                            dev->DataInf.dwAsicBytesPerPlane );
699141cc406Sopenharmony_ci		} else {
700141cc406Sopenharmony_ci			u12io_ReadColorData( dev, dev->bufs.b1.pReadBuf,
701141cc406Sopenharmony_ci			                     dev->DataInf.dwAsicBytesPerPlane );
702141cc406Sopenharmony_ci		}
703141cc406Sopenharmony_ci		return SANE_FALSE;
704141cc406Sopenharmony_ci	}
705141cc406Sopenharmony_ci
706141cc406Sopenharmony_ci	if( dev->DataInf.wPhyDataType <= COLOR_256GRAY ) {
707141cc406Sopenharmony_ci
708141cc406Sopenharmony_ci		dev->regs.RD_ModeControl = _ModeFifoGSel;
709141cc406Sopenharmony_ci		u12io_ReadMonoData( dev, buf, dev->DataInf.dwAsicBytesPerPlane );
710141cc406Sopenharmony_ci
711141cc406Sopenharmony_ci	} else {
712141cc406Sopenharmony_ci
713141cc406Sopenharmony_ci		if( !dev->scan.DataRead( dev )) {
714141cc406Sopenharmony_ci			return SANE_FALSE;
715141cc406Sopenharmony_ci		}
716141cc406Sopenharmony_ci	}
717141cc406Sopenharmony_ci
718141cc406Sopenharmony_ci	if( dev->scan.DoSample( dev )) {
719141cc406Sopenharmony_ci
720141cc406Sopenharmony_ci		/* direct is done here without copying...*/
721141cc406Sopenharmony_ci		if( fnDataDirect != dev->scan.DataProcess ) {
722141cc406Sopenharmony_ci			(*dev->scan.DataProcess)(dev, buf, (void*)(dev->scan.BufPut.red.bp),
723141cc406Sopenharmony_ci                                        dev->DataInf.dwAppPhyBytesPerLine);
724141cc406Sopenharmony_ci		}
725141cc406Sopenharmony_ci		return SANE_TRUE;
726141cc406Sopenharmony_ci	}
727141cc406Sopenharmony_ci	return SANE_FALSE;
728141cc406Sopenharmony_ci}
729141cc406Sopenharmony_ci
730141cc406Sopenharmony_ci/**
731141cc406Sopenharmony_ci */
732141cc406Sopenharmony_cistatic SANE_Status u12image_ReadOneImageLine( U12_Device *dev, void* buf )
733141cc406Sopenharmony_ci{
734141cc406Sopenharmony_ci	SANE_Byte  b, state;
735141cc406Sopenharmony_ci	TimerDef  timer, t2;
736141cc406Sopenharmony_ci
737141cc406Sopenharmony_ci	DBG( _DBG_READ, "u12image_ReadOneImageLine()\n" );
738141cc406Sopenharmony_ci
739141cc406Sopenharmony_ci	u12io_StartTimer( &timer, _LINE_TIMEOUT );
740141cc406Sopenharmony_ci	u12io_StartTimer( &t2, _SECOND*2 );
741141cc406Sopenharmony_ci	do {
742141cc406Sopenharmony_ci
743141cc406Sopenharmony_ci		state = u12io_GetScanState( dev );
744141cc406Sopenharmony_ci		dev->scan.bNowScanState = (state & _SCANSTATE_MASK);
745141cc406Sopenharmony_ci
746141cc406Sopenharmony_ci		if( state & _SCANSTATE_STOP ) {
747141cc406Sopenharmony_ci
748141cc406Sopenharmony_ci			DBG( _DBG_READ, "* SCANSTATE_STOP\n" );
749141cc406Sopenharmony_ci			u12motor_ModuleForwardBackward( dev );
750141cc406Sopenharmony_ci
751141cc406Sopenharmony_ci			if( u12io_GetFifoLength( dev ) >= dev->scan.dwMinReadFifo )
752141cc406Sopenharmony_ci				if( u12image_DataIsReady( dev, buf ))
753141cc406Sopenharmony_ci					return SANE_STATUS_GOOD;
754141cc406Sopenharmony_ci
755141cc406Sopenharmony_ci		} else {
756141cc406Sopenharmony_ci
757141cc406Sopenharmony_ci			dev->scan.bModuleState = _MotorInNormalState;
758141cc406Sopenharmony_ci			b = dev->scan.bNowScanState - dev->scan.oldScanState;
759141cc406Sopenharmony_ci
760141cc406Sopenharmony_ci			if((char) b < 0)
761141cc406Sopenharmony_ci				b += _NUMBER_OF_SCANSTEPS;
762141cc406Sopenharmony_ci
763141cc406Sopenharmony_ci			if( b >= dev->scan.bRefresh ) {
764141cc406Sopenharmony_ci
765141cc406Sopenharmony_ci				u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
766141cc406Sopenharmony_ci				dev->scan.oldScanState = u12io_GetScanState( dev );
767141cc406Sopenharmony_ci				dev->scan.oldScanState &= _SCANSTATE_MASK;
768141cc406Sopenharmony_ci			}
769141cc406Sopenharmony_ci
770141cc406Sopenharmony_ci			if( u12io_GetFifoLength( dev ) >= dev->scan.dwMaxReadFifo ) {
771141cc406Sopenharmony_ci
772141cc406Sopenharmony_ci				if( u12image_DataIsReady( dev, buf ))
773141cc406Sopenharmony_ci					return SANE_STATUS_GOOD;
774141cc406Sopenharmony_ci			}
775141cc406Sopenharmony_ci			else {
776141cc406Sopenharmony_ci
777141cc406Sopenharmony_ci				b = dev->scan.bNowScanState - dev->scan.oldScanState;
778141cc406Sopenharmony_ci
779141cc406Sopenharmony_ci				if((char) b < 0)
780141cc406Sopenharmony_ci					b += _NUMBER_OF_SCANSTEPS;
781141cc406Sopenharmony_ci
782141cc406Sopenharmony_ci				if( b >= dev->scan.bRefresh ) {
783141cc406Sopenharmony_ci
784141cc406Sopenharmony_ci					u12io_RegisterToScanner( dev, REG_REFRESHSCANSTATE );
785141cc406Sopenharmony_ci					dev->scan.oldScanState = u12io_GetScanState( dev );
786141cc406Sopenharmony_ci					dev->scan.oldScanState &= _SCANSTATE_MASK;
787141cc406Sopenharmony_ci				}
788141cc406Sopenharmony_ci
789141cc406Sopenharmony_ci				if( u12io_GetFifoLength( dev ) >= dev->scan.dwMinReadFifo ) {
790141cc406Sopenharmony_ci					if( u12image_DataIsReady( dev, buf ))
791141cc406Sopenharmony_ci						return SANE_STATUS_GOOD;
792141cc406Sopenharmony_ci				}
793141cc406Sopenharmony_ci			}
794141cc406Sopenharmony_ci		}
795141cc406Sopenharmony_ci
796141cc406Sopenharmony_ci	} while( !u12io_CheckTimer( &timer ));
797141cc406Sopenharmony_ci
798141cc406Sopenharmony_ci	DBG( _DBG_ERROR, "Timeout - Scanner malfunction !!\n" );
799141cc406Sopenharmony_ci	u12motor_ToHomePosition( dev, SANE_TRUE );
800141cc406Sopenharmony_ci
801141cc406Sopenharmony_ci	/* timed out, scanner malfunction */
802141cc406Sopenharmony_ci	return SANE_STATUS_IO_ERROR;
803141cc406Sopenharmony_ci}
804141cc406Sopenharmony_ci
805141cc406Sopenharmony_ci/**
806141cc406Sopenharmony_ci */
807141cc406Sopenharmony_cistatic void u12image_PrepareScaling( U12_Device *dev )
808141cc406Sopenharmony_ci{
809141cc406Sopenharmony_ci	int    step;
810141cc406Sopenharmony_ci	double ratio;
811141cc406Sopenharmony_ci
812141cc406Sopenharmony_ci	dev->scaleBuf = NULL;
813141cc406Sopenharmony_ci	DBG( _DBG_INFO, "APP-DPIX=%u, MAX-DPIX=%u\n",
814141cc406Sopenharmony_ci		             dev->DataInf.xyAppDpi.x, dev->dpi_max_x );
815141cc406Sopenharmony_ci
816141cc406Sopenharmony_ci	if( dev->DataInf.xyAppDpi.x > dev->dpi_max_x ) {
817141cc406Sopenharmony_ci
818141cc406Sopenharmony_ci		dev->scaleBuf = malloc( dev->DataInf.dwAppBytesPerLine );
819141cc406Sopenharmony_ci
820141cc406Sopenharmony_ci		ratio = (double)dev->DataInf.xyAppDpi.x/(double)dev->dpi_max_x;
821141cc406Sopenharmony_ci		dev->scaleIzoom = (int)(1.0/ratio * 1000);
822141cc406Sopenharmony_ci
823141cc406Sopenharmony_ci		switch( dev->DataInf.wAppDataType ) {
824141cc406Sopenharmony_ci
825141cc406Sopenharmony_ci			case COLOR_BW      : step = 0;  break;
826141cc406Sopenharmony_ci			case COLOR_256GRAY : step = 1;  break;
827141cc406Sopenharmony_ci			case COLOR_TRUE24  : step = 3;  break;
828141cc406Sopenharmony_ci			case COLOR_TRUE42  : step = 6;  break;
829141cc406Sopenharmony_ci			default			   : step = 99; break;
830141cc406Sopenharmony_ci		}
831141cc406Sopenharmony_ci		dev->scaleStep = step;
832141cc406Sopenharmony_ci
833141cc406Sopenharmony_ci		DBG( _DBG_INFO, "u12image_PrepareScaling: izoom=%i, step=%u\n",
834141cc406Sopenharmony_ci		                dev->scaleIzoom, step );
835141cc406Sopenharmony_ci	} else {
836141cc406Sopenharmony_ci
837141cc406Sopenharmony_ci		DBG( _DBG_INFO, "u12image_PrepareScaling: DISABLED\n" );
838141cc406Sopenharmony_ci	}
839141cc406Sopenharmony_ci}
840141cc406Sopenharmony_ci
841141cc406Sopenharmony_ci/** scaling picture data in x-direction, using a DDA algorithm
842141cc406Sopenharmony_ci *  (digital differential analyzer).
843141cc406Sopenharmony_ci */
844141cc406Sopenharmony_cistatic void u12image_ScaleX( U12_Device *dev, SANE_Byte *ib, SANE_Byte *ob )
845141cc406Sopenharmony_ci{
846141cc406Sopenharmony_ci	SANE_Byte tmp;
847141cc406Sopenharmony_ci	int       ddax;
848141cc406Sopenharmony_ci	u_long    i, j, x;
849141cc406Sopenharmony_ci
850141cc406Sopenharmony_ci	/* when not supported, only copy the data */
851141cc406Sopenharmony_ci	if( 99 == dev->scaleStep ) {
852141cc406Sopenharmony_ci		memcpy( ob, ib, dev->DataInf.dwAppBytesPerLine );
853141cc406Sopenharmony_ci		return;
854141cc406Sopenharmony_ci	}
855141cc406Sopenharmony_ci
856141cc406Sopenharmony_ci	/* now scale... */
857141cc406Sopenharmony_ci	if( 0 == dev->scaleStep ) {
858141cc406Sopenharmony_ci
859141cc406Sopenharmony_ci		/* binary scaling */
860141cc406Sopenharmony_ci		ddax = 0;
861141cc406Sopenharmony_ci		x    = 0;
862141cc406Sopenharmony_ci		memset( ob, 0, dev->DataInf.dwAppBytesPerLine );
863141cc406Sopenharmony_ci
864141cc406Sopenharmony_ci		for( i = 0; i < dev->DataInf.dwPhysBytesPerLine*8; i++ ) {
865141cc406Sopenharmony_ci
866141cc406Sopenharmony_ci			ddax -= 1000;
867141cc406Sopenharmony_ci
868141cc406Sopenharmony_ci			while( ddax < 0 ) {
869141cc406Sopenharmony_ci
870141cc406Sopenharmony_ci				tmp = ib[(i>>3)];
871141cc406Sopenharmony_ci
872141cc406Sopenharmony_ci				if((x>>3) < dev->DataInf.dwAppBytesPerLine ) {
873141cc406Sopenharmony_ci					if( 0 != (tmp &= (1 << ((~(i & 0x7))&0x7))))
874141cc406Sopenharmony_ci						ob[x>>3] |= (1 << ((~(x & 0x7))&0x7));
875141cc406Sopenharmony_ci				}
876141cc406Sopenharmony_ci				x++;
877141cc406Sopenharmony_ci				ddax += dev->scaleIzoom;
878141cc406Sopenharmony_ci			}
879141cc406Sopenharmony_ci		}
880141cc406Sopenharmony_ci
881141cc406Sopenharmony_ci	} else {
882141cc406Sopenharmony_ci
883141cc406Sopenharmony_ci		/* color and gray scaling */
884141cc406Sopenharmony_ci		ddax = 0;
885141cc406Sopenharmony_ci		x    = 0;
886141cc406Sopenharmony_ci		for( i = 0; i < dev->DataInf.dwPhysBytesPerLine*dev->scaleStep;
887141cc406Sopenharmony_ci		                                                  i+=dev->scaleStep ) {
888141cc406Sopenharmony_ci
889141cc406Sopenharmony_ci			ddax -= 1000;
890141cc406Sopenharmony_ci
891141cc406Sopenharmony_ci			while( ddax < 0 ) {
892141cc406Sopenharmony_ci
893141cc406Sopenharmony_ci				for( j = 0; j < (u_long)dev->scaleStep; j++ ) {
894141cc406Sopenharmony_ci
895141cc406Sopenharmony_ci					if((x+j) < dev->DataInf.dwAppBytesPerLine ) {
896141cc406Sopenharmony_ci						ob[x+j] = ib[i+j];
897141cc406Sopenharmony_ci					}
898141cc406Sopenharmony_ci				}
899141cc406Sopenharmony_ci				x    += dev->scaleStep;
900141cc406Sopenharmony_ci				ddax += dev->scaleIzoom;
901141cc406Sopenharmony_ci			}
902141cc406Sopenharmony_ci		}
903141cc406Sopenharmony_ci	}
904141cc406Sopenharmony_ci}
905141cc406Sopenharmony_ci
906141cc406Sopenharmony_ci/* END U12_IMAGE.C ..........................................................*/
907