1 /*
2    SANE EPSON backend
3    Copyright (C) 2001, 2005, 2008  SEIKO EPSON Corporation
4 
5    Date         Author      Reason
6    06/01/2001   N.Sasaki    New
7 
8    This file is part of the `iscan' program.
9 
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 
24    As a special exception, the copyright holders give permission
25    to link the code of this program with the esmod library and
26    distribute linked combinations including the two.  You must obey
27    the GNU General Public License in all respects for all of the
28    code used other then esmod.
29 */
30 
31 /*------------------------------------------------------------*/
32 #include <assert.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <new>
37 using std::bad_alloc;
38 
39 #include "filter.hh"
40 
41 /*------------------------------------------------------------*/
42 #include "pisa_scan_manager.h"
43 #include "pisa_error.h"
44 #include "pisa_scan_tool.h"
45 #include "pisa_change_unit.h"
46 
47 /*------------------------------------------------------------*/
open_device(char * name)48 void scan_manager::open_device ( char * name )
49 {
50   sane_scan::init ( );
51 
52   m_resize_cls	= 0;
53   m_moire_cls	= 0;
54   m_sharp_cls	= 0;
55   m_resize_img_info = 0;
56   m_moire_img_info  = 0;
57   m_sharp_img_info  = 0;
58 
59   sane_scan::open_device (name);
60   max_descreen_resolution = get_max_resolution (is_dumb () ? 600 : 800);
61 }
62 
63 void
init_scan(int * width,int * height,bool reset_params)64 scan_manager::init_scan (int *width, int *height, bool reset_params)
65 {
66   if (reset_params)
67     {
68       for (int i = 0; i < 2; ++i)
69 	{
70 	  adjust_scan_param (&param.resolution[i], &param.zoom[i]);
71 	}
72 
73       init_img_process_info (param);
74       sane_scan::set_scan_parameter (param);
75     }
76 
77   if (area_is_too_large (param))
78     {
79       if (getenv ("ISCAN_DEBUG"))
80 	{
81 	  fprintf (stderr, "Backend will try to scan with these settings\n");
82 	  fprintf (stderr, "Resolution (main,sub): %ld,%ld\n",
83 		   param.resolution[0], param.resolution[1]);
84 	  fprintf (stderr, "Zoom       (main,sub): %ld,%ld\n",
85 		   param.zoom[0], param.zoom[1]);
86 	  fprintf (stderr, "Offset     (main,sub): %ld,%ld\n",
87 		   inch2pixel (param.offset[0], param.resolution[0],
88 			       param.zoom[0]),
89 		   inch2pixel (param.offset[1], param.resolution[1],
90 			       param.zoom[1]));
91 	  fprintf (stderr, "Area       (main,sub): %ld,%ld\n",
92 		   inch2pixel (true,
93 			       param.area[0], param.resolution[0],
94 			       param.zoom[0]),
95 		   inch2pixel (false,
96 			       param.area[1], param.resolution[1],
97 			       param.zoom[1]));
98 	}
99 
100       throw pisa_error (PISA_ERR_AREALARGE);
101     }
102 
103   sane_scan::start_scan ( width, height );
104 
105   modify_img_info ( width, height );
106 
107   create_img_cls ( );
108 }
109 
110 /*------------------------------------------------------------*/
acquire_image(unsigned char * img,int row_bytes,int height,int cancel)111 void scan_manager::acquire_image ( unsigned char * img,
112 				   int row_bytes,
113 				   int height,
114 				   int cancel )
115 {
116   if ( m_resize || m_moire || m_sharp )
117     {
118       int in_rowbytes = 0, in_line;
119       unsigned char * in_img = 0;
120 
121       if ( m_sharp )
122 	in_rowbytes = m_sharp_info.in_rowbytes;
123       if ( m_moire )
124 	in_rowbytes = m_moire_info.in_rowbytes;
125       if ( m_resize )
126 	in_rowbytes = m_resize_info.in_rowbytes;
127 
128       if ( cancel || img == 0 )
129 	{
130 	  sane_scan::acquire_image ( 0, 0, 1, 1 );
131 	}
132       else
133 	{
134 	  in_line = get_send_in_line ( 1 );
135 
136 	  if ( 0 < in_line )
137 	    {
138 	      int buf_size = in_line * in_rowbytes;
139 
140 	      in_img = new unsigned char [ buf_size + in_rowbytes ];
141 
142 	      if ( in_img == 0 )
143 		{
144 		  sane_scan::acquire_image ( 0, 0, 1, 1 );
145 
146 		  throw pisa_error ( PISA_ERR_OUTOFMEMORY );
147 		}
148 
149 	      sane_scan::acquire_image ( in_img,
150 					 in_rowbytes,
151 					 in_line,
152 					 cancel );
153 	    }
154 	}
155 
156       ::memset ( img, 128, row_bytes );
157       if ( cancel == 0 && PISA_ERR_SUCCESS != image_process ( in_img, img ) )
158 	{
159 	  delete [ ] in_img;
160 	  sane_scan::acquire_image ( 0, 0, 1, 1 );
161 	  throw pisa_error ( PISA_ERR_OUTOFMEMORY );
162 	}
163 
164       if ( in_img )
165 	delete [ ] in_img;
166     }
167   else
168     sane_scan::acquire_image ( img, row_bytes, height, cancel );
169 }
170 
171 void
finish_acquire(void)172 scan_manager::finish_acquire (void)
173 {
174   sane_scan::finish_acquire ();
175   release_memory ();
176 }
177 
178 int
init_img_process_info(scan_parameter & param)179 scan_manager::init_img_process_info (scan_parameter& param)
180 {
181   // set flag
182   if (!has_zoom ())
183     m_resize = 1;
184   else
185     m_resize = 0;
186 
187   if ( param.de_screening )	// color or B/W document
188     {
189       m_moire = 1;
190       m_resize = 0;
191     }
192   else
193     m_moire = 0;
194 
195   m_sharp = param.usm;
196 
197   if ( m_resize )
198     init_zoom ( & m_resize_info, param );
199 
200   if ( m_moire )
201     init_moire ( & m_moire_info, param );
202 
203   if ( m_sharp )
204     init_sharp ( & m_sharp_info, param );
205 
206   return PISA_ERR_PARAMETER;
207 }
208 
209 int
init_zoom(resize_img_info * info,scan_parameter & param)210 scan_manager::init_zoom (resize_img_info *info, scan_parameter& param)
211 {
212   long act_res[2];
213 
214   info->resolution = param.resolution[0];
215 
216   for (int i = 0; i < 2; ++i)
217     {
218       act_res[i] = param.resolution[i] * param.zoom[i] / 100;
219     }
220 
221   info->out_width	= ::inch2width ( param.area [ 0 ],
222 					 act_res [ 0 ] );
223   info->out_height	= ::inch2height ( param.area [ 1 ],
224 					 act_res [ 1 ] );
225   info->out_rowbytes	= calc_rowbytes ( info->out_width,
226 					  static_cast <pisa_pixel_type>
227 					  ( param.pixeltype ) );
228 
229   for (int i = 0; i < 2; ++i)
230     {
231       param.resolution[i] = act_res[i];
232       param.zoom[i] = 100;
233     }
234 
235   try
236     {
237       get_valid_resolution (&param.resolution[0], &param.resolution[1], true);
238     }
239   catch (const pisa_error& e)
240     {
241       if (pisa_error (PISA_STATUS_UNSUPPORTED) != e)
242 	throw (e);
243     }
244 
245   if (   act_res[0] == param.resolution[0]
246       && act_res[1] == param.resolution[1])
247     {
248       m_resize = 0;
249       return PISA_ERR_SUCCESS;
250     }
251 
252   info->in_width	= ::inch2width ( param.area [ 0 ],
253 					 param.resolution [ 0 ] );
254   info->in_height	= ::inch2height ( param.area [ 1 ],
255 					 param.resolution [ 1 ] );
256   info->in_rowbytes	= calc_rowbytes ( info->in_width,
257 					  static_cast <pisa_pixel_type>
258 					  ( param.pixeltype ) );
259 
260   info->bits_per_pixel	= calc_bitperpix ( static_cast <pisa_pixel_type>
261 					   ( param.pixeltype ),
262 					   static_cast <pisa_bitdepth_type>
263 					   ( param.bitdepth ) );
264 
265   if ( param.pixeltype == PISA_PT_BW )
266     info->resize_flag	= PISA_RS_NN;
267   else
268     info->resize_flag	= PISA_RS_BC;
269 
270   return PISA_ERR_SUCCESS;
271 }
272 
273 int
init_moire(moire_img_info * info,scan_parameter & param)274 scan_manager::init_moire (moire_img_info *info, scan_parameter& param)
275 {
276   info->resolution = param.resolution [ 0 ] * param.zoom [ 0 ] / 100;
277 
278   param.resolution [ 0 ] =
279   param.resolution [ 1 ] =
280     iscan::moire::get_res_quote (info->resolution, is_dumb ());
281 
282   if (!has_zoom ())
283     {
284       try
285 	{
286 	  get_valid_resolution (&param.resolution[0],
287 				&param.resolution[1]);
288 	}
289       catch (const pisa_error& e)
290 	{
291 	  if (pisa_error (PISA_STATUS_UNSUPPORTED) != e)
292 	    throw (e);
293 	  // else do nothing
294 	}
295     }
296 
297   info->in_resolution = param.resolution [ 0 ];
298 
299   param.zoom [ 0 ] = 100;
300   param.zoom [ 1 ] = 100;
301 
302   info->in_width	= ::inch2width ( param.area [ 0 ],
303 					 param.resolution [ 0 ] );
304   info->in_height	= ::inch2height ( param.area [ 1 ],
305 					 param.resolution [ 1 ] );
306   info->in_rowbytes	= calc_rowbytes ( info->in_width,
307 					  static_cast <pisa_pixel_type>
308 					  ( param.pixeltype ) );
309 
310   info->out_width	= ::inch2width ( param.area [ 0 ],
311 					 info->resolution );
312   info->out_height	= ::inch2height ( param.area [ 1 ],
313 					 info->resolution );
314   info->out_rowbytes	= calc_rowbytes ( info->out_width,
315 					  static_cast <pisa_pixel_type>
316 					  (param.pixeltype ) );
317 
318   info->bits_per_pixel	= calc_bitperpix ( static_cast <pisa_pixel_type>
319 					   ( param.pixeltype ),
320 					   static_cast <pisa_bitdepth_type>
321 					   ( param.bitdepth ) );
322 
323   return PISA_ERR_SUCCESS;
324 }
325 
326 /*------------------------------------------------------------*/
327 int
init_sharp(sharp_img_info * info,scan_parameter & param)328 scan_manager::init_sharp (sharp_img_info *info, scan_parameter& param)
329 {
330   long resolution;
331 
332   if ( m_resize )
333     {
334       info->in_width	= m_resize_info.out_width;
335       info->in_height	= m_resize_info.out_height;
336 
337       resolution	= m_resize_info.resolution;
338     }
339   else if ( m_moire )
340     {
341       info->in_width	= m_moire_info.out_width;
342       info->in_height	= m_moire_info.out_height;
343 
344       resolution	= m_moire_info.resolution;
345     }
346   else
347     {
348       info->in_width	= ::inch2width ( param.area [ 0 ],
349 					 param.resolution [ 0 ],
350 					 param.zoom [ 0 ] );
351       info->in_height	= ::inch2height ( param.area [ 1 ],
352 					 param.resolution [ 1 ],
353 					 param.zoom [ 1 ] );
354 
355       resolution	= param.resolution [ 0 ];
356     }
357 
358   info->in_rowbytes	= calc_rowbytes ( info->in_width,
359 					  static_cast <pisa_pixel_type>
360 					  ( param.pixeltype ) );
361 
362   info->bits_per_pixel	= calc_bitperpix ( static_cast <pisa_pixel_type>
363 					   ( param.pixeltype ),
364 					   static_cast <pisa_bitdepth_type>
365 					   ( param.bitdepth ) );
366 
367   info->out_width	= info->in_width;
368   info->out_height	= info->in_height;
369   info->out_rowbytes	= info->in_rowbytes;
370 
371   m_sharp_cls->set_parms (resolution,
372 			  param.film == PISA_FT_NEGA
373 			  || param.film == PISA_FT_POSI,
374 			  is_dumb (),
375 			  & info->strength,
376 			  & info->radius,
377 			  & info->clipping);
378 
379   info->sharp_flag	= PISA_SH_UMASK;
380 
381   return PISA_ERR_SUCCESS;
382 }
383 
384 /*------------------------------------------------------------*/
modify_img_info(int * width,int * height)385 int scan_manager::modify_img_info ( int * width, int * height )
386 {
387   // resize
388   if ( m_resize )
389     {
390       if ( m_resize_info.in_width == m_resize_info.out_width )
391 	{
392 	  m_resize_info.out_width = * width;
393 	  m_resize_info.out_rowbytes = ( m_resize_info.out_width *
394 					 m_resize_info.bits_per_pixel +
395 					 7 ) / 8;
396 	}
397 
398       m_resize_info.in_width	= * width;
399       m_resize_info.in_rowbytes	= ( m_resize_info.in_width *
400 				    m_resize_info.bits_per_pixel +
401 				    7 ) / 8;
402 
403       if ( m_resize_info.in_height == m_resize_info.out_height )
404 	{
405 	  m_resize_info.out_height = * height;
406 	}
407 
408       m_resize_info.in_height	= * height;
409     }
410 
411   if ( m_sharp )
412     {
413       m_sharp_info.in_width	= * width;
414       m_sharp_info.in_height	= * height;
415       m_sharp_info.in_rowbytes	= ( m_sharp_info.in_width *
416 				    m_sharp_info.bits_per_pixel +
417 				    7 ) / 8;
418 
419       if ( m_resize )
420 	{
421 	  m_sharp_info.in_width		= m_resize_info.out_width;
422 	  m_sharp_info.in_height	= m_resize_info.out_height;
423 	  m_sharp_info.in_rowbytes	= m_resize_info.out_rowbytes;
424 	}
425 
426       if ( m_moire )
427 	{
428 	  m_sharp_info.in_width		= m_moire_info.out_width;
429 	  m_sharp_info.in_height	= m_moire_info.out_height;
430 	  m_sharp_info.in_rowbytes	= m_moire_info.out_rowbytes;
431 	}
432 
433       m_sharp_info.out_width	= m_sharp_info.in_width;
434       m_sharp_info.out_height	= m_sharp_info.in_height;
435       m_sharp_info.out_rowbytes	= m_sharp_info.in_rowbytes;
436     }
437 
438   // update width and height
439   if ( m_resize )
440     {
441       * width	= m_resize_info.out_width;
442       * height	= m_resize_info.out_height;
443     }
444 
445   if ( m_moire )
446     {
447       * width	= m_moire_info.out_width;
448       * height	= m_moire_info.out_height;
449     }
450 
451   if ( m_sharp )
452     {
453       * width	= m_sharp_info.out_width;
454       * height	= m_sharp_info.out_height;
455     }
456 
457 
458   return PISA_ERR_SUCCESS;
459 }
460 
461 /*------------------------------------------------------------*/
create_img_cls(void)462 int scan_manager::create_img_cls ( void )
463 {
464   release_memory ();
465 
466   if (m_sharp)
467     {
468       m_sharp_img_info = new IMAGE_INFO [ 2 ];
469 
470       set_img_info ( & m_sharp_img_info [ _IN ],
471 		     & m_sharp_img_info [ _OUT ],
472 		     m_sharp_info );
473 
474       m_sharp_cls = new iscan::focus (m_sharp_info);
475     }
476 
477   if ( m_moire )
478     {
479       m_moire_img_info = new IMAGE_INFO [ 2 ];
480 
481       set_img_info ( & m_moire_img_info [ _IN ],
482 		     & m_moire_img_info [ _OUT ],
483 		     m_moire_info );
484 
485       m_moire_cls = new iscan::moire (m_moire_info, is_dumb ());
486     }
487 
488   if ( m_resize )
489     {
490       m_resize_img_info = new IMAGE_INFO [ 2 ];
491 
492       set_img_info ( & m_resize_img_info [ _IN ],
493 		     & m_resize_img_info [ _OUT ],
494 		     m_resize_info );
495 
496       m_resize_cls = new iscan::scale (m_resize_info);
497     }
498 
499   return PISA_ERR_SUCCESS;
500 }
501 
502 /*------------------------------------------------------------*/
release_memory(void)503 int scan_manager::release_memory ( void )
504 {
505   if ( m_resize_cls )
506     delete m_resize_cls;
507   m_resize_cls = 0;
508 
509   if ( m_moire_cls )
510     delete m_moire_cls;
511   m_moire_cls = 0;
512 
513   if ( m_sharp_cls )
514     delete m_sharp_cls;
515   m_sharp_cls = 0;
516 
517   if ( m_resize_img_info )
518     delete m_resize_img_info;
519   m_resize_img_info = 0;
520 
521   if ( m_moire_img_info )
522     delete m_moire_img_info;
523   m_moire_img_info = 0;
524 
525   if ( m_sharp_img_info )
526     delete m_sharp_img_info;
527   m_sharp_img_info = 0;
528 
529   return PISA_ERR_SUCCESS;
530 }
531 
532 /*------------------------------------------------------------*/
set_img_info(LPIMAGE_INFO in_img_info,LPIMAGE_INFO out_img_info,const img_size & size)533 void scan_manager::set_img_info ( LPIMAGE_INFO in_img_info,
534 				  LPIMAGE_INFO out_img_info,
535 				  const img_size & size )
536 {
537   in_img_info->pImg_Buf		= 0;
538   in_img_info->Img_Width	= size.in_width;
539   in_img_info->Img_Height	= size.in_height;
540   in_img_info->Img_RowBytes	= size.in_rowbytes;
541   in_img_info->BitsPerPixel	= size.bits_per_pixel;
542 
543   out_img_info->pImg_Buf	= 0;
544   out_img_info->Img_Width	= size.out_width;
545   out_img_info->Img_Height	= size.out_height;
546   out_img_info->Img_RowBytes	= size.out_rowbytes;
547   out_img_info->BitsPerPixel	= size.bits_per_pixel;
548 }
549 
550 /*------------------------------------------------------------*/
get_send_in_line(int out_line)551 int scan_manager::get_send_in_line ( int out_line )
552 {
553   size_t quote = out_line;
554 
555   if (m_sharp)
556     {
557       m_sharp_img_info [ _OUT ].Img_Height = quote;
558       quote = m_sharp_cls->get_line_quote (quote);
559       m_sharp_img_info [ _IN ].Img_Height  = quote;
560     }
561   if (m_moire)
562     {
563       m_moire_img_info [ _OUT ].Img_Height = quote;
564       quote = m_moire_cls->get_line_quote (quote);
565       m_moire_img_info [ _IN ].Img_Height  = quote;
566     }
567   if (m_resize)
568     {
569       m_resize_img_info [ _OUT ].Img_Height = quote;
570       quote = m_resize_cls->get_line_quote (quote);
571       m_resize_img_info [ _IN ].Img_Height  = quote;
572     }
573 
574   return quote;
575 }
576 
577 /*------------------------------------------------------------*/
image_process(unsigned char * in_img,unsigned char * out_img)578 int scan_manager::image_process ( unsigned char * in_img,
579 				  unsigned char * out_img )
580 {
581   unsigned char *inbuf, *outbuf;
582   size_t         in_sz,  out_sz;
583 
584   unsigned char *tmpbuf = NULL;
585   size_t         tmp_sz = 0;
586   bool           zapbuf = false;
587 
588   try
589     {
590       if (m_resize)
591 	{
592 	  in_sz = m_resize_img_info [ _IN ].Img_Height * m_resize_img_info [ _IN].Img_RowBytes;
593 	  inbuf = in_img;
594 
595 	  if (m_sharp)
596 	    {
597 	      out_sz = tmp_sz = (m_resize_img_info [ _OUT ].Img_Height
598 				 * m_resize_img_info [ _OUT ].Img_RowBytes);
599 	      outbuf = tmpbuf = new unsigned char [out_sz];
600 	      zapbuf = true;
601 	    }
602 	  else
603 	    {
604 	      out_sz = m_resize_img_info [ _OUT ].Img_Height * m_resize_img_info [ _OUT ].Img_RowBytes;
605 	      outbuf = out_img;
606 	    }
607 	  m_resize_cls->exec (inbuf, in_sz, outbuf, out_sz);
608 	}
609 
610       if (m_moire)
611 	{
612 	  in_sz = m_moire_img_info [ _IN ].Img_Height * m_moire_img_info [ _IN ].Img_RowBytes;
613 	  inbuf = in_img;
614 
615 	  if (m_sharp)
616 	    {
617 	      out_sz = tmp_sz = (m_moire_img_info [ _OUT ].Img_Height
618 				 * m_moire_img_info [ _OUT ].Img_RowBytes);
619 	      outbuf = tmpbuf = new unsigned char [out_sz];
620 	      zapbuf = true;
621 	    }
622 	  else
623 	    {
624 	      out_sz = m_moire_img_info [ _OUT ].Img_Height * m_moire_img_info [ _OUT ].Img_RowBytes;
625 	      outbuf = out_img;
626 	    }
627 	  m_moire_cls->exec (inbuf, in_sz, outbuf, out_sz);
628 	}
629 
630       if (m_sharp)
631 	{
632 	  out_sz = m_sharp_img_info [ _OUT ].Img_Height * m_sharp_img_info [ _OUT ].Img_RowBytes;
633 	  outbuf = out_img;
634 
635 	  if (m_resize || m_moire)
636 	    {
637 	      in_sz = tmp_sz;
638 	      inbuf = tmpbuf;
639 	    }
640 	  else
641 	    {
642 	      in_sz = m_sharp_img_info [ _IN ].Img_Height * m_sharp_img_info [ _IN ].Img_RowBytes;
643 	      inbuf = in_img;
644 	    }
645 	  m_sharp_cls->exec (inbuf, in_sz, outbuf, out_sz);
646 	}
647 
648       if (zapbuf)
649 	{
650 	  delete [] tmpbuf;
651 	}
652     }
653   catch (bad_alloc& oops)
654     {
655       if (zapbuf)
656 	{
657 	  delete [] tmpbuf;
658 	}
659       return PISA_ERR_OUTOFMEMORY;
660     }
661 
662   return PISA_ERR_SUCCESS;
663 }
664 
665 void
adjust_scan_param(long * resolution,long * scale) const666 scan_manager::adjust_scan_param (long *resolution, long *scale) const
667 {
668   int min_res   = 50;
669   int max_res   = get_max_resolution ();
670   int adj_res   = *resolution;
671 
672   int min_scale =  50;
673   int max_scale = 200;
674   int adj_scale = 100;		// assume no scaling is needed
675 
676   if (adj_res < min_res)
677     {
678       adj_scale = adj_res * 100 / min_res;
679 
680       if (adj_scale < min_scale)
681 	{
682 	  adj_scale = min_scale;
683 	}
684       adj_res = min_res;
685     }
686 
687   if (max_res < adj_res)
688     {
689       adj_scale = adj_res * 100 / max_res;
690 
691       if (adj_scale > max_scale)
692 	{
693 	  adj_scale = max_scale;
694 	}
695       adj_res = max_res;
696     }
697 
698   *resolution = adj_res;
699   *scale      = adj_scale;
700 }
701 
702 /*!  Sets main and sub resolutions to the best available value.
703 
704      The best available value is the first resolution not smaller than
705      the value passed.  If no such value is available, the largest
706      available resolution will be used unless \a use_max is \c false.
707 
708      In the latter case an exception will be thrown instead.
709  */
710 void
get_valid_resolution(long int * x_res,long int * y_res,bool use_max) const711 scan_manager::get_valid_resolution (long int *x_res, long int *y_res,
712 				    bool use_max) const
713 {
714   if (!x_res || !y_res)
715     throw pisa_error (PISA_ERR_PARAMETER);
716 
717   SANE_Int res_x = get_resolution (SANE_NAME_SCAN_X_RESOLUTION, *x_res);
718   SANE_Int res_y = get_resolution (SANE_NAME_SCAN_Y_RESOLUTION, *y_res);
719 
720   if (0 == res_x || 0 == res_y)
721     {
722       if (!use_max)
723 	throw pisa_error (PISA_STATUS_UNSUPPORTED);
724       if (0 == res_x)
725 	res_x = get_max_resolution (SANE_NAME_SCAN_X_RESOLUTION);
726       if (0 == res_y)
727 	res_y = get_max_resolution (SANE_NAME_SCAN_Y_RESOLUTION);
728     }
729 
730   *x_res = res_x;
731   *y_res = res_y;
732 }
733 
734 void
set_option(pisa_option_type option)735 scan_manager::set_option (pisa_option_type option)
736 {
737   sane_scan::set_option (option);
738   max_descreen_resolution = get_max_resolution (is_dumb () ? 600 : 800);
739 }
740 
741 pisa_error_id
set_scan_parameters(const settings & set,const marquee & marq)742 scan_manager::set_scan_parameters (const settings& set, const marquee& marq)
743 {
744   memset (&param, 0, sizeof (scan_parameter));
745 
746   param.option	= set.option;
747   param.film	= set.film;
748 
749   param.pixeltype	= set.imgtype.pixeltype;
750   param.bitdepth	= set.imgtype.bitdepth;
751   param.scanspeed	= set.imgtype.scanspeed;
752   param.dropout		= set.imgtype.dropout;
753   param.monoopt		= set.imgtype.monoopt;
754   param.halftone	= set.imgtype.halftone;
755 
756   param.offset[0]	= marq.offset.x;
757   param.offset[1]	= marq.offset.y;
758   param.area[0]		= marq.area.x;
759   param.area[1]		= marq.area.y;
760   param.resolution[0]	= (set.resolution * marq.scale + 50) / 100;
761   param.resolution[1]	= (set.resolution * marq.scale + 50) / 100;
762   param.zoom[0]		= 100;
763   param.zoom[1]		= 100;
764 
765   for (int i = 0; i < 256; ++i)
766     {
767       param.gamma.gamma_r[i] = marq.lut.gamma_r[i];
768       param.gamma.gamma_g[i] = marq.lut.gamma_g[i];
769       param.gamma.gamma_b[i] = marq.lut.gamma_b[i];
770     }
771 
772   if (set.imgtype.pixeltype == PISA_PT_RGB)
773     {
774       generate_color_coef (param.coef, set.coef, marq.saturation);
775     }
776   else			// use identity matrix
777     {			// FIXME: fold into generate_color_coef()
778       for (int i = 0; i < 9; ++i)
779 	param.coef[i] = 0.0;
780 
781       param.coef[0] = 1.0;
782       param.coef[4] = 1.0;
783       param.coef[8] = 1.0;
784     }
785 
786   param.threshold = marq.threshold;
787   param.speed	= 0;
788   param.focus	= marq.focus;
789 
790   if (PISA_PT_BW == set.imgtype.pixeltype)
791     param.usm = 0;
792   else
793     param.usm = set.usm;
794 
795   if (PISA_DESCREEN_ON == set.imgtype.de_screening)
796     param.de_screening = 1;
797   else
798     param.de_screening = 0;
799 
800 
801   // check for error conditions
802   pisa_error_id err = PISA_ERR_SUCCESS;
803 
804   if (area_is_too_large (param))
805     err = PISA_ERR_AREALARGE;
806 
807   if (set.imgtype.de_screening == PISA_DESCREEN_ON)
808     {
809       if (   param.resolution[0] > max_descreen_resolution
810 	  || param.resolution[1] > max_descreen_resolution)
811 	err = PISA_ERR_MRRESTOOHIGH;
812     }
813   return err;
814 }
815 
816 #include "pisa_view_manager.h"
817 pisa_error_id
set_scan_parameters(const settings & set,const marquee & marq,pisa_preview_type type,int resolution)818 scan_manager::set_scan_parameters (const settings& set, const marquee& marq,
819 				   pisa_preview_type type, int resolution)
820 {
821   memset (&param, 0, sizeof (scan_parameter));
822 
823   param.option		= set.option;
824   param.film		= set.film;
825 
826   param.pixeltype	= PISA_PT_RGB;
827   param.bitdepth	= PISA_BD_8;
828   param.scanspeed	= PISA_SS_DRAFT;
829   param.dropout		= PISA_DO_NONE;
830   param.monoopt		= PISA_MO_NONE;
831   param.halftone	= PISA_HT_NONE;
832 
833   param.offset[0]	= marq.offset.x;
834   param.offset[1]	= marq.offset.y;
835   param.area[0]		= marq.area.x;
836   param.area[1]		= marq.area.y;
837   param.resolution[0]	= resolution;
838   param.resolution[1]	= resolution;
839   param.zoom[0]		= 100;
840   param.zoom[1]		= 100;
841 
842   // gamma table
843   for (int i = 0; i < 256; ++i)
844     {
845       param.gamma.gamma_r[i] = i;
846       param.gamma.gamma_g[i] = i;
847       param.gamma.gamma_b[i] = i;
848     }
849 
850   // profile matrix
851   for (int i = 0; i < 9; ++i)
852     param.coef[i] = 0.0;
853 
854   param.coef[0] = 1.0;
855   param.coef[4] = 1.0;
856   param.coef[8] = 1.0;
857 
858   param.threshold	= 0;
859   param.speed		= 1;
860   param.focus		= marq.focus;
861   param.usm		= 0;
862   param.de_screening	= 0;
863 
864   return PISA_ERR_SUCCESS;
865 }
866