1141cc406Sopenharmony_ci/* sane - Scanner Access Now Easy.
2141cc406Sopenharmony_ci   Copyright (C) Marian Eichholz 2001
3141cc406Sopenharmony_ci   This file is part of the SANE package.
4141cc406Sopenharmony_ci
5141cc406Sopenharmony_ci   This program is free software; you can redistribute it and/or
6141cc406Sopenharmony_ci   modify it under the terms of the GNU General Public License as
7141cc406Sopenharmony_ci   published by the Free Software Foundation; either version 2 of the
8141cc406Sopenharmony_ci   License, or (at your option) any later version.
9141cc406Sopenharmony_ci
10141cc406Sopenharmony_ci   This program is distributed in the hope that it will be useful, but
11141cc406Sopenharmony_ci   WITHOUT ANY WARRANTY; without even the implied warranty of
12141cc406Sopenharmony_ci   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13141cc406Sopenharmony_ci   General Public License for more details.
14141cc406Sopenharmony_ci
15141cc406Sopenharmony_ci   You should have received a copy of the GNU General Public License
16141cc406Sopenharmony_ci   along with this program.  If not, see <https://www.gnu.org/licenses/>.
17141cc406Sopenharmony_ci
18141cc406Sopenharmony_ci   As a special exception, the authors of SANE give permission for
19141cc406Sopenharmony_ci   additional uses of the libraries contained in this release of SANE.
20141cc406Sopenharmony_ci
21141cc406Sopenharmony_ci   The exception is that, if you link a SANE library with other files
22141cc406Sopenharmony_ci   to produce an executable, this does not by itself cause the
23141cc406Sopenharmony_ci   resulting executable to be covered by the GNU General Public
24141cc406Sopenharmony_ci   License.  Your use of that executable is in no way restricted on
25141cc406Sopenharmony_ci   account of linking the SANE library code into it.
26141cc406Sopenharmony_ci
27141cc406Sopenharmony_ci   This exception does not, however, invalidate any other reasons why
28141cc406Sopenharmony_ci   the executable file might be covered by the GNU General Public
29141cc406Sopenharmony_ci   License.
30141cc406Sopenharmony_ci
31141cc406Sopenharmony_ci   If you submit changes to SANE to the maintainers to be included in
32141cc406Sopenharmony_ci   a subsequent release, you agree by submitting the changes that
33141cc406Sopenharmony_ci   those changes may be distributed with this exception intact.
34141cc406Sopenharmony_ci
35141cc406Sopenharmony_ci   If you write modifications of your own for SANE, it is your choice
36141cc406Sopenharmony_ci   whether to permit this exception to apply to your modifications.
37141cc406Sopenharmony_ci   If you do not wish that, delete this exception notice.
38141cc406Sopenharmony_ci*/
39141cc406Sopenharmony_ci
40141cc406Sopenharmony_ci/* ======================================================================
41141cc406Sopenharmony_ci
42141cc406Sopenharmony_ciUserspace scan tool for the Microtek 3600 scanner
43141cc406Sopenharmony_ci
44141cc406Sopenharmony_ci====================================================================== */
45141cc406Sopenharmony_ci
46141cc406Sopenharmony_ci#include <stdarg.h>
47141cc406Sopenharmony_ci#include <unistd.h>
48141cc406Sopenharmony_ci#include "sm3600-scantool.h"
49141cc406Sopenharmony_ci
50141cc406Sopenharmony_ci/* **********************************************************************
51141cc406Sopenharmony_ci
52141cc406Sopenharmony_cidprintf(DEBUG_XXXX, format, ...)
53141cc406Sopenharmony_ci
54141cc406Sopenharmony_ciPut a debug message on STDERR (or whatever). The message is prefixed with
55141cc406Sopenharmony_cia "debug:" and given, if the current debugging flags contain the given
56141cc406Sopenharmony_ciflag "ulType".
57141cc406Sopenharmony_ci
58141cc406Sopenharmony_ci********************************************************************** */
59141cc406Sopenharmony_ci
60141cc406Sopenharmony_ci#ifdef INSANE_VERSION
61141cc406Sopenharmony_civoid DBG(int nLevel, const char *szFormat, ...)
62141cc406Sopenharmony_ci{
63141cc406Sopenharmony_ci  szFormat++;
64141cc406Sopenharmony_ci}
65141cc406Sopenharmony_ci#endif
66141cc406Sopenharmony_ci
67141cc406Sopenharmony_ci__SM3600EXPORT__
68141cc406Sopenharmony_civoid debug_printf(unsigned long ulType, const char *szFormat, ...)
69141cc406Sopenharmony_ci{
70141cc406Sopenharmony_ci  va_list ap;
71141cc406Sopenharmony_ci  if ((ulDebugMask & ulType)!=ulType) return;
72141cc406Sopenharmony_ci  if (*szFormat=='~')
73141cc406Sopenharmony_ci    szFormat++;
74141cc406Sopenharmony_ci  else
75141cc406Sopenharmony_ci    fprintf(stderr,"debug:");
76141cc406Sopenharmony_ci  va_start(ap,szFormat);
77141cc406Sopenharmony_ci  vfprintf(stderr,szFormat,ap);
78141cc406Sopenharmony_ci  va_end(ap);
79141cc406Sopenharmony_ci}
80141cc406Sopenharmony_ci
81141cc406Sopenharmony_ci/* **********************************************************************
82141cc406Sopenharmony_ci
83141cc406Sopenharmony_ciSetError(error, format, ...)
84141cc406Sopenharmony_ci
85141cc406Sopenharmony_ciThe program is aborted, all handles and resources are freed (this
86141cc406Sopenharmony_cibeing global) and the user gets a nice panic screen :-)
87141cc406Sopenharmony_ci
88141cc406Sopenharmony_ci********************************************************************** */
89141cc406Sopenharmony_ci
90141cc406Sopenharmony_ci__SM3600EXPORT__
91141cc406Sopenharmony_ciint SetError(TInstance *this, int nError, const char *szFormat, ...)
92141cc406Sopenharmony_ci{
93141cc406Sopenharmony_ci  va_list ap;
94141cc406Sopenharmony_ci  if (this->nErrorState) return 0; /* do not overwrite error state */
95141cc406Sopenharmony_ci  this->nErrorState=nError;
96141cc406Sopenharmony_ci  this->szErrorReason=malloc(500);
97141cc406Sopenharmony_ci
98141cc406Sopenharmony_ci  if (szFormat!=NULL && this->szErrorReason)
99141cc406Sopenharmony_ci    {
100141cc406Sopenharmony_ci      va_start(ap,szFormat);
101141cc406Sopenharmony_ci      vsnprintf(this->szErrorReason,499,szFormat,ap);
102141cc406Sopenharmony_ci      va_end(ap);
103141cc406Sopenharmony_ci      this->szErrorReason[499]='\0';
104141cc406Sopenharmony_ci    }
105141cc406Sopenharmony_ci  return nError;
106141cc406Sopenharmony_ci}
107141cc406Sopenharmony_ci
108141cc406Sopenharmony_ci#ifdef INSANE_VERSION
109141cc406Sopenharmony_ci
110141cc406Sopenharmony_ci/* **********************************************************************
111141cc406Sopenharmony_ci
112141cc406Sopenharmony_ciDumpBuffer(fh,pch,cch)
113141cc406Sopenharmony_ci
114141cc406Sopenharmony_ci********************************************************************** */
115141cc406Sopenharmony_ci
116141cc406Sopenharmony_ci__SM3600EXPORT__
117141cc406Sopenharmony_civoid DumpBuffer(FILE *fh, const char *pch, int cch)
118141cc406Sopenharmony_ci{
119141cc406Sopenharmony_ci  int i=0;
120141cc406Sopenharmony_ci  while (i<cch)
121141cc406Sopenharmony_ci    {
122141cc406Sopenharmony_ci      if (!(i & 15))
123141cc406Sopenharmony_ci	{
124141cc406Sopenharmony_ci	  if (i) fprintf(fh,"\n");
125141cc406Sopenharmony_ci	  fprintf(fh,"%04X:",i);
126141cc406Sopenharmony_ci	}
127141cc406Sopenharmony_ci      fprintf(fh," %02X",(unsigned char)pch[i]);
128141cc406Sopenharmony_ci      i++;
129141cc406Sopenharmony_ci    }
130141cc406Sopenharmony_ci  fprintf(fh,"\n");
131141cc406Sopenharmony_ci}
132141cc406Sopenharmony_ci
133141cc406Sopenharmony_ci#endif
134141cc406Sopenharmony_ci
135141cc406Sopenharmony_ci/* **********************************************************************
136141cc406Sopenharmony_ci
137141cc406Sopenharmony_ciFreeState()
138141cc406Sopenharmony_ci
139141cc406Sopenharmony_ciFrees all dynamical memory for scan buffering.
140141cc406Sopenharmony_ci
141141cc406Sopenharmony_ci********************************************************************** */
142141cc406Sopenharmony_ci
143141cc406Sopenharmony_ci__SM3600EXPORT__
144141cc406Sopenharmony_ciTState FreeState(TInstance *this, TState nReturn)
145141cc406Sopenharmony_ci{
146141cc406Sopenharmony_ci  if (this->state.ppchLines)
147141cc406Sopenharmony_ci    {
148141cc406Sopenharmony_ci      int i;
149141cc406Sopenharmony_ci      for (i=0; i<this->state.cBacklog; i++)
150141cc406Sopenharmony_ci	{
151141cc406Sopenharmony_ci	  if (this->state.ppchLines[i])
152141cc406Sopenharmony_ci	    free(this->state.ppchLines[i]);
153141cc406Sopenharmony_ci	}
154141cc406Sopenharmony_ci      free(this->state.ppchLines);
155141cc406Sopenharmony_ci    }
156141cc406Sopenharmony_ci  if (this->state.pchLineOut) free(this->state.pchLineOut);
157141cc406Sopenharmony_ci  if (this->state.pchBuf)     free(this->state.pchBuf);
158141cc406Sopenharmony_ci  this->state.pchBuf    =NULL;
159141cc406Sopenharmony_ci  this->state.pchLineOut=NULL;
160141cc406Sopenharmony_ci  this->state.ppchLines =NULL;
161141cc406Sopenharmony_ci  return nReturn;
162141cc406Sopenharmony_ci}
163141cc406Sopenharmony_ci
164141cc406Sopenharmony_ci/* ======================================================================
165141cc406Sopenharmony_ci
166141cc406Sopenharmony_ciEndScan()
167141cc406Sopenharmony_ci
168141cc406Sopenharmony_ci====================================================================== */
169141cc406Sopenharmony_ci
170141cc406Sopenharmony_ci__SM3600EXPORT__
171141cc406Sopenharmony_ciTState EndScan(TInstance *this)
172141cc406Sopenharmony_ci{
173141cc406Sopenharmony_ci  if (!this->state.bScanning) return SANE_STATUS_GOOD;
174141cc406Sopenharmony_ci  /* move slider back to start */
175141cc406Sopenharmony_ci  this->state.bScanning=false;
176141cc406Sopenharmony_ci  FreeState(this,0);
177141cc406Sopenharmony_ci  INST_ASSERT();
178141cc406Sopenharmony_ci  return DoJog(this,-this->state.cyTotalPath);
179141cc406Sopenharmony_ci}
180141cc406Sopenharmony_ci
181141cc406Sopenharmony_ci/* ======================================================================
182141cc406Sopenharmony_ci
183141cc406Sopenharmony_ciTState CancelScan(TInstance *this)
184141cc406Sopenharmony_ci
185141cc406Sopenharmony_ci====================================================================== */
186141cc406Sopenharmony_ci
187141cc406Sopenharmony_ci__SM3600EXPORT__
188141cc406Sopenharmony_ciTState CancelScan(TInstance *this)
189141cc406Sopenharmony_ci{
190141cc406Sopenharmony_ci  TBool bCanceled;
191141cc406Sopenharmony_ci  DBG(DEBUG_INFO,"CancelScan() called\n");
192141cc406Sopenharmony_ci
193141cc406Sopenharmony_ci  this->state.cyTotalPath-=RegRead(this,R_POS,2);
194141cc406Sopenharmony_ci  DBG(DEBUG_JUNK,"stepping back %d steps\n",this->state.cyTotalPath);
195141cc406Sopenharmony_ci  /* this->state.cyTotalPath=0; */
196141cc406Sopenharmony_ci
197141cc406Sopenharmony_ci  usleep(200);
198141cc406Sopenharmony_ci  DoReset(this);
199141cc406Sopenharmony_ci  EndScan(this); /* and step back! */
200141cc406Sopenharmony_ci
201141cc406Sopenharmony_ci  DBG(DEBUG_JUNK,"cs4: %d\n",(int)this->nErrorState);
202141cc406Sopenharmony_ci  bCanceled=this->state.bCanceled;
203141cc406Sopenharmony_ci  this->state.bCanceled=false; /* re-enable Origination! */
204141cc406Sopenharmony_ci  if (!this->bOptSkipOriginate)
205141cc406Sopenharmony_ci    DoOriginate(this,false); /* have an error here... */
206141cc406Sopenharmony_ci  this->state.bCanceled=bCanceled;
207141cc406Sopenharmony_ci  DBG(DEBUG_JUNK,"cs5: %d\n",(int)this->nErrorState);
208141cc406Sopenharmony_ci  INST_ASSERT();
209141cc406Sopenharmony_ci  DBG(DEBUG_INFO,"cs6: ok.\n");
210141cc406Sopenharmony_ci  return SANE_STATUS_CANCELLED; /* or shall be say GOOD? */
211141cc406Sopenharmony_ci}
212141cc406Sopenharmony_ci
213141cc406Sopenharmony_ci
214141cc406Sopenharmony_ci/* ======================================================================
215141cc406Sopenharmony_ci
216141cc406Sopenharmony_ciReadChunk()
217141cc406Sopenharmony_ci
218141cc406Sopenharmony_ci====================================================================== */
219141cc406Sopenharmony_ci
220141cc406Sopenharmony_ci__SM3600EXPORT__
221141cc406Sopenharmony_ciTState ReadChunk(TInstance *this, unsigned char *achOut,
222141cc406Sopenharmony_ci		 int cchMax, int *pcchRead)
223141cc406Sopenharmony_ci{
224141cc406Sopenharmony_ci  /* have we to copy more than we have? */
225141cc406Sopenharmony_ci  /* can the current line fill the buffer ? */
226141cc406Sopenharmony_ci  int rc;
227141cc406Sopenharmony_ci  *pcchRead=0;
228141cc406Sopenharmony_ci  INST_ASSERT();
229141cc406Sopenharmony_ci  if (!this->state.bScanning)
230141cc406Sopenharmony_ci    return SANE_STATUS_CANCELLED; /* deferred cancel? */
231141cc406Sopenharmony_ci  if (this->state.bCanceled) /* deferred cancellation? */
232141cc406Sopenharmony_ci    return CancelScan(this);
233141cc406Sopenharmony_ci  INST_ASSERT();
234141cc406Sopenharmony_ci  /* 22.4.2001: This took me hard, harder, hardest:*/
235141cc406Sopenharmony_ci
236141cc406Sopenharmony_ci  /*   We need to fill the line buffer with at least a *rest* of a
237141cc406Sopenharmony_ci       line. A single line will do. */
238141cc406Sopenharmony_ci  /*     Thus, "iLine>0" is a suitable condition. */
239141cc406Sopenharmony_ci  /*   Without the preread, there will a dummy line be read, if the
240141cc406Sopenharmony_ci       target buffer is large enough.*/
241141cc406Sopenharmony_ci  if (this->state.iLine)
242141cc406Sopenharmony_ci    rc=SANE_STATUS_GOOD;
243141cc406Sopenharmony_ci  else
244141cc406Sopenharmony_ci    rc=(*(this->state.ReadProc))(this); /* preread one line */
245141cc406Sopenharmony_ci  if (rc!=SANE_STATUS_GOOD) return rc;
246141cc406Sopenharmony_ci  dprintf(DEBUG_BUFFER,"Chunk-Init: cchMax = %d\n",cchMax);
247141cc406Sopenharmony_ci  while (this->state.iReadPos + cchMax > this->state.cchLineOut)
248141cc406Sopenharmony_ci    {
249141cc406Sopenharmony_ci      int cch;
250141cc406Sopenharmony_ci      /* copy rest of the line into target */
251141cc406Sopenharmony_ci      cch = this->state.cchLineOut - this->state.iReadPos;
252141cc406Sopenharmony_ci      memcpy(achOut,
253141cc406Sopenharmony_ci	     this->state.pchLineOut+this->state.iReadPos,
254141cc406Sopenharmony_ci	     cch);
255141cc406Sopenharmony_ci      cchMax-=cch; /* advance parameters */
256141cc406Sopenharmony_ci      achOut+=cch;
257141cc406Sopenharmony_ci      (*pcchRead)+=cch;
258141cc406Sopenharmony_ci      this->state.iReadPos=0;
259141cc406Sopenharmony_ci      rc=(*(this->state.ReadProc))(this);
260141cc406Sopenharmony_ci      dprintf(DEBUG_BUFFER,"Chunk-Read: cchMax = %d\n",cchMax);
261141cc406Sopenharmony_ci      if (rc!=SANE_STATUS_GOOD)
262141cc406Sopenharmony_ci	return rc; /* should be NOT(!) EOF, but then: good and away! */
263141cc406Sopenharmony_ci    }
264141cc406Sopenharmony_ci  dprintf(DEBUG_BUFFER,"Chunk-Exit: cchMax = %d\n",cchMax);
265141cc406Sopenharmony_ci  if (!cchMax) return SANE_STATUS_GOOD; /* now everything fits! */
266141cc406Sopenharmony_ci  (*pcchRead) += cchMax;
267141cc406Sopenharmony_ci  memcpy(achOut,
268141cc406Sopenharmony_ci	 this->state.pchLineOut+this->state.iReadPos,
269141cc406Sopenharmony_ci	 cchMax);
270141cc406Sopenharmony_ci  this->state.iReadPos += cchMax;
271141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
272141cc406Sopenharmony_ci}
273141cc406Sopenharmony_ci
274141cc406Sopenharmony_ci/* ======================================================================
275141cc406Sopenharmony_ci
276141cc406Sopenharmony_ciGetAreaSize()
277141cc406Sopenharmony_ci
278141cc406Sopenharmony_ci====================================================================== */
279141cc406Sopenharmony_ci
280141cc406Sopenharmony_ci__SM3600EXPORT__
281141cc406Sopenharmony_civoid GetAreaSize(TInstance *this)
282141cc406Sopenharmony_ci{
283141cc406Sopenharmony_ci  /* this->state.cxPixel : pixels, we *want* (after interpolation)
284141cc406Sopenharmony_ci     this->state.cxMax   : pixels, we *need* (before interpolation) */
285141cc406Sopenharmony_ci  int nRefResX,nRefResY;
286141cc406Sopenharmony_ci  nRefResX=nRefResY=this->param.res;
287141cc406Sopenharmony_ci  switch (this->param.res)
288141cc406Sopenharmony_ci    {
289141cc406Sopenharmony_ci    case 75:  nRefResX=100; this->state.nFixAspect=75; break;
290141cc406Sopenharmony_ci    default: this->state.nFixAspect=100; break;
291141cc406Sopenharmony_ci    }
292141cc406Sopenharmony_ci  this->state.cxPixel   =this->param.cx*this->param.res/1200;
293141cc406Sopenharmony_ci  this->state.cyPixel   =this->param.cy*this->param.res/1200;
294141cc406Sopenharmony_ci  this->state.cxMax     =this->state.cxPixel*100/this->state.nFixAspect;
295141cc406Sopenharmony_ci  this->state.cxWindow  =this->state.cxMax*600/nRefResX;
296141cc406Sopenharmony_ci  this->state.cyWindow  =this->state.cyPixel*600/nRefResY;
297141cc406Sopenharmony_ci  dprintf(DEBUG_SCAN,"requesting %d[600] %d[real] %d[raw]\n",
298141cc406Sopenharmony_ci	  this->state.cxWindow,this->state.cxPixel,this->state.cxMax);
299141cc406Sopenharmony_ci}
300141cc406Sopenharmony_ci
301141cc406Sopenharmony_ci/* ======================================================================
302141cc406Sopenharmony_ci
303141cc406Sopenharmony_ciResetCalibration()
304141cc406Sopenharmony_ci
305141cc406Sopenharmony_ciFree calibration data. The Instance can be safely released afterwards.
306141cc406Sopenharmony_ci
307141cc406Sopenharmony_ci====================================================================== */
308141cc406Sopenharmony_ci
309141cc406Sopenharmony_ci__SM3600EXPORT__
310141cc406Sopenharmony_civoid ResetCalibration(TInstance *this)
311141cc406Sopenharmony_ci{
312141cc406Sopenharmony_ci  if (this->calibration.achStripeY)
313141cc406Sopenharmony_ci    free(this->calibration.achStripeY);
314141cc406Sopenharmony_ci  if (this->calibration.achStripeR)
315141cc406Sopenharmony_ci    free(this->calibration.achStripeR);
316141cc406Sopenharmony_ci  if (this->calibration.achStripeG)
317141cc406Sopenharmony_ci    free(this->calibration.achStripeG);
318141cc406Sopenharmony_ci  if (this->calibration.achStripeB)
319141cc406Sopenharmony_ci    free(this->calibration.achStripeB);
320141cc406Sopenharmony_ci  /* reset all handles, pointers, flags */
321141cc406Sopenharmony_ci  memset(&(this->calibration),0,sizeof(this->calibration));
322141cc406Sopenharmony_ci  /* TODO: type specific margins */
323141cc406Sopenharmony_ci  this->calibration.xMargin=200;
324141cc406Sopenharmony_ci  this->calibration.yMargin=0x019D;
325141cc406Sopenharmony_ci  this->calibration.nHoleGray=10;
326141cc406Sopenharmony_ci  this->calibration.rgbBias=0x888884;
327141cc406Sopenharmony_ci  this->calibration.nBarGray=0xC0;
328141cc406Sopenharmony_ci}
329141cc406Sopenharmony_ci
330141cc406Sopenharmony_ci/* ======================================================================
331141cc406Sopenharmony_ci
332141cc406Sopenharmony_ciInitGammaTables()
333141cc406Sopenharmony_ci
334141cc406Sopenharmony_ciInit gammy tables and gain tables within controller memory.
335141cc406Sopenharmony_ci
336141cc406Sopenharmony_ci====================================================================== */
337141cc406Sopenharmony_ci
338141cc406Sopenharmony_ci__SM3600EXPORT__
339141cc406Sopenharmony_ciTState InitGammaTables(TInstance *this, int nBrightness, int nContrast)
340141cc406Sopenharmony_ci{
341141cc406Sopenharmony_ci  long          i;
342141cc406Sopenharmony_ci  long          lOffset;
343141cc406Sopenharmony_ci  long          lScale;
344141cc406Sopenharmony_ci  /* the rescaling is done with temporary zero translation to 2048 */
345141cc406Sopenharmony_ci  lOffset=(nBrightness-128)*16; /* signed! */
346141cc406Sopenharmony_ci  lScale=(nContrast+128)*100;  /* in percent */
347141cc406Sopenharmony_ci  for (i=0; i<4096; i++)
348141cc406Sopenharmony_ci    {
349141cc406Sopenharmony_ci      int n=(int)((i+lOffset)*lScale/12800L+2048L);
350141cc406Sopenharmony_ci      if (n<0) n=0;
351141cc406Sopenharmony_ci      else if (n>4095) n=4095;
352141cc406Sopenharmony_ci      this->agammaY[i]=n;
353141cc406Sopenharmony_ci      this->agammaR[i]=n;
354141cc406Sopenharmony_ci      this->agammaG[i]=n;
355141cc406Sopenharmony_ci      this->agammaB[i]=n;
356141cc406Sopenharmony_ci    }
357141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
358141cc406Sopenharmony_ci}
359141cc406Sopenharmony_ci
360141cc406Sopenharmony_ci#ifdef INSANE_VERSION
361141cc406Sopenharmony_ci
362141cc406Sopenharmony_ci/* ======================================================================
363141cc406Sopenharmony_ci
364141cc406Sopenharmony_ciDoScanFile()
365141cc406Sopenharmony_ci
366141cc406Sopenharmony_ciTop level caller for scantool.
367141cc406Sopenharmony_ci
368141cc406Sopenharmony_ci====================================================================== */
369141cc406Sopenharmony_ci
370141cc406Sopenharmony_ci#define APP_CHUNK_SIZE   0x8000
371141cc406Sopenharmony_ci
372141cc406Sopenharmony_ci__SM3600EXPORT__
373141cc406Sopenharmony_ciTState DoScanFile(TInstance *this)
374141cc406Sopenharmony_ci{
375141cc406Sopenharmony_ci  int    cx,cy;
376141cc406Sopenharmony_ci  long   lcchRead;
377141cc406Sopenharmony_ci  TState rc;
378141cc406Sopenharmony_ci  char   *achBuf;
379141cc406Sopenharmony_ci
380141cc406Sopenharmony_ci  achBuf=malloc(APP_CHUNK_SIZE);
381141cc406Sopenharmony_ci  rc=SANE_STATUS_GOOD; /* make compiler happy */
382141cc406Sopenharmony_ci  rc=InitGammaTables(this, this->param.nBrightness, this->param.nContrast);
383141cc406Sopenharmony_ci  if (rc!=SANE_STATUS_GOOD) return rc;
384141cc406Sopenharmony_ci  if (this->mode==color)
385141cc406Sopenharmony_ci    rc=StartScanColor(this);
386141cc406Sopenharmony_ci  else
387141cc406Sopenharmony_ci    rc=StartScanGray(this);
388141cc406Sopenharmony_ci  cx=this->state.cxPixel;
389141cc406Sopenharmony_ci  cy=this->state.cyPixel;
390141cc406Sopenharmony_ci  if (this->bVerbose)
391141cc406Sopenharmony_ci    fprintf(stderr,"scanning %d by %d\n",cx,cy);
392141cc406Sopenharmony_ci  if (this->fhScan && !this->bWriteRaw && !this->pchPageBuffer)
393141cc406Sopenharmony_ci   {
394141cc406Sopenharmony_ci      switch (this->mode)
395141cc406Sopenharmony_ci	{
396141cc406Sopenharmony_ci	case color: fprintf(this->fhScan,"P6\n%d %d\n255\n",cx,cy);
397141cc406Sopenharmony_ci	            break;
398141cc406Sopenharmony_ci	case gray:  fprintf(this->fhScan,"P5\n%d %d\n255\n",cx,cy);
399141cc406Sopenharmony_ci                    break;
400141cc406Sopenharmony_ci	default:    fprintf(this->fhScan,"P4\n%d %d\n",cx,cy);
401141cc406Sopenharmony_ci                    break;
402141cc406Sopenharmony_ci	}
403141cc406Sopenharmony_ci    }
404141cc406Sopenharmony_ci  lcchRead=0L;
405141cc406Sopenharmony_ci  while (!rc)
406141cc406Sopenharmony_ci    {
407141cc406Sopenharmony_ci      int cch;
408141cc406Sopenharmony_ci      cch=0;
409141cc406Sopenharmony_ci      rc=ReadChunk(this,achBuf,APP_CHUNK_SIZE,&cch);
410141cc406Sopenharmony_ci      if (cch>0 && this->fhScan && cch<=APP_CHUNK_SIZE)
411141cc406Sopenharmony_ci	{
412141cc406Sopenharmony_ci	  if (this->pchPageBuffer)
413141cc406Sopenharmony_ci	    {
414141cc406Sopenharmony_ci#ifdef SM3600_DEBUGPAGEBUFFER
415141cc406Sopenharmony_ci	      if (this->bVerbose)
416141cc406Sopenharmony_ci		fprintf(stderr,"ichPageBuffer:%d, cch:%d, cchPageBuffer:%d\n",
417141cc406Sopenharmony_ci			this->ichPageBuffer,cch,this->cchPageBuffer);
418141cc406Sopenharmony_ci#endif
419141cc406Sopenharmony_ci	      CHECK_ASSERTION(this->ichPageBuffer+cch<=this->cchPageBuffer);
420141cc406Sopenharmony_ci	      memcpy(this->pchPageBuffer+this->ichPageBuffer,
421141cc406Sopenharmony_ci		     achBuf,cch);
422141cc406Sopenharmony_ci	      this->ichPageBuffer+=cch;
423141cc406Sopenharmony_ci	    }
424141cc406Sopenharmony_ci	  else if (!this->bWriteRaw)
425141cc406Sopenharmony_ci	    fwrite(achBuf,1,cch,this->fhScan);
426141cc406Sopenharmony_ci	  lcchRead+=cch;
427141cc406Sopenharmony_ci	}
428141cc406Sopenharmony_ci     }
429141cc406Sopenharmony_ci  free(achBuf);
430141cc406Sopenharmony_ci  if (this->bVerbose)
431141cc406Sopenharmony_ci    fprintf(stderr,"read %ld image byte(s)\n",lcchRead);
432141cc406Sopenharmony_ci  EndScan(this);
433141cc406Sopenharmony_ci  INST_ASSERT();
434141cc406Sopenharmony_ci  return SANE_STATUS_GOOD;
435141cc406Sopenharmony_ci}
436141cc406Sopenharmony_ci
437141cc406Sopenharmony_ci#endif
438