1/* sane - Scanner Access Now Easy.
2
3   pieusb_specific.c
4
5   Copyright (C) 2012-2015 Jan Vleeshouwers, Michael Rickmann, Klaus Kaempf
6
7   This file is part of the SANE package.
8
9   This program is free software; you can redistribute it and/or
10   modify it under the terms of the GNU General Public License as
11   published by the Free Software Foundation; either version 2 of the
12   License, or (at your option) any later version.
13
14   This program is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   General Public License for more details.
18
19   You should have received a copy of the GNU General Public License
20   along with this program.  If not, see <https://www.gnu.org/licenses/>.
21
22   As a special exception, the authors of SANE give permission for
23   additional uses of the libraries contained in this release of SANE.
24
25   The exception is that, if you link a SANE library with other files
26   to produce an executable, this does not by itself cause the
27   resulting executable to be covered by the GNU General Public
28   License.  Your use of that executable is in no way restricted on
29   account of linking the SANE library code into it.
30
31   This exception does not, however, invalidate any other reasons why
32   the executable file might be covered by the GNU General Public
33   License.
34
35   If you submit changes to SANE to the maintainers to be included in
36   a subsequent release, you agree by submitting the changes that
37   those changes may be distributed with this exception intact.
38
39   If you write modifications of your own for SANE, it is your choice
40   whether to permit this exception to apply to your modifications.
41   If you do not wish that, delete this exception notice.  */
42
43/* =========================================================================
44 *
45 * Various Pieusb backend specific functions
46 *
47 * Option handling, configuration file handling, post-processing
48 *
49 * ========================================================================= */
50
51#define DEBUG_DECLARE_ONLY
52#include "pieusb.h"
53
54#include <stdlib.h>
55#include <unistd.h>
56#include <string.h>
57#include "../include/sane/sane.h"
58#include "../include/sane/saneopts.h"
59#include "../include/sane/sanei_config.h"
60
61#include <errno.h>
62#include <math.h>
63#include <time.h>
64
65#include "pieusb_usb.h"
66#include "pieusb_scancmd.h"
67#include "pieusb_buffer.h"
68#include "pieusb_specific.h"
69
70/* Pieusb specific */
71
72/* sub to sanei_pieusb_find_device_callback() */
73static SANE_Status pieusb_initialize_device_definition (Pieusb_Device_Definition* dev, Pieusb_Scanner_Properties* inq, const char* devicename, SANE_Word vendor_id, SANE_Word product_id);
74static void pieusb_print_inquiry (Pieusb_Device_Definition * dev);
75
76/* sub to sane_start() */
77static void pieusb_calculate_shading(struct Pieusb_Scanner *scanner, SANE_Byte* buffer);
78
79/* MR */
80/* sub to sanei_pieusb_post() */
81static SANE_Status pieusb_write_pnm_file (char *filename, uint16_t *data, int depth, int channels, int pixels_per_line, int lines);
82
83/* Auxiliary */
84static size_t max_string_size (SANE_String_Const const strings[]);
85static double getGain(int gain);
86static int getGainSetting(double gain);
87/*
88static void updateGain(Pieusb_Scanner *scanner, int color_index);
89*/
90static void updateGain2(Pieusb_Scanner *scanner, int color_index, double gain_increase);
91
92/* --------------------------------------------------------------------------
93 *
94 * SPECIFIC PIEUSB
95 *
96 * --------------------------------------------------------------------------*/
97
98/* Settings for byte order */
99#define SCAN_IMG_FMT_OKLINE          0x08
100#define SCAN_IMG_FMT_BLK_ONE         0x04
101#define SCAN_IMG_FMT_MOTOROLA        0x02
102#define SCAN_IMG_FMT_INTEL           0x01
103
104/* Settings for scanner capabilities */
105#define SCAN_CAP_PWRSAV              0x80
106#define SCAN_CAP_EXT_CAL             0x40
107#define SCAN_CAP_FAST_PREVIEW        0x10
108#define SCAN_CAP_DISABLE_CAL         0x08
109#define SCAN_CAP_SPEEDS              0x07
110
111/* Available scanner options */
112#define SCAN_OPT_DEV_MPCL            0x80
113#define SCAN_OPT_DEV_TP1             0x04
114#define SCAN_OPT_DEV_TP              0x02
115#define SCAN_OPT_DEV_ADF             0x01
116
117/* Options */
118#define SANE_NAME_EXPOSURE_R         "exposure-time-r"
119#define SANE_TITLE_EXPOSURE_R        "Exposure time red"
120#define SANE_DESC_EXPOSURE_R         "The time the red color filter of the CCD is exposed"
121#define SANE_NAME_EXPOSURE_G         "exposure-time-g"
122#define SANE_TITLE_EXPOSURE_G        "Exposure time green"
123#define SANE_DESC_EXPOSURE_G         "The time the green color filter of the CCD is exposed"
124#define SANE_NAME_EXPOSURE_B         "exposure-time-b"
125#define SANE_TITLE_EXPOSURE_B        "Exposure time blue"
126#define SANE_DESC_EXPOSURE_B         "The time the blue color filter of the CCD is exposed"
127#define SANE_NAME_EXPOSURE_I         "exposure-time-i"
128#define SANE_TITLE_EXPOSURE_I        "Exposure time infrared"
129#define SANE_DESC_EXPOSURE_I         "The time the infrared color filter of the CCD is exposed"
130#define SANE_EXPOSURE_DEFAULT        DEFAULT_EXPOSURE
131#if 1
132#define SANE_NAME_GAIN_R               "gain-r"
133#define SANE_TITLE_GAIN_R              "Gain red"
134#define SANE_DESC_GAIN_R               "The gain of the signal processor for red"
135#define SANE_NAME_GAIN_G               "gain-g"
136#define SANE_TITLE_GAIN_G              "Gain green"
137#define SANE_DESC_GAIN_G               "The gain of the signal processor for green"
138#define SANE_NAME_GAIN_B               "gain-b"
139#define SANE_TITLE_GAIN_B              "Gain blue"
140#define SANE_DESC_GAIN_B               "The gain of the signal processor for blue"
141#define SANE_NAME_GAIN_I               "gain-i"
142#define SANE_TITLE_GAIN_I              "Gain infrared"
143#define SANE_DESC_GAIN_I               "The gain of the signal processor for infrared"
144#define SANE_GAIN_DEFAULT            DEFAULT_GAIN
145
146#define SANE_NAME_OFFSET_R             "offset-r"
147#define SANE_TITLE_OFFSET_R            "Offset red"
148#define SANE_DESC_OFFSET_R             "The offset of the signal processor for red"
149#define SANE_NAME_OFFSET_G             "offset-g"
150#define SANE_TITLE_OFFSET_G            "Offset greed"
151#define SANE_DESC_OFFSET_G             "The offset of the signal processor for green"
152#define SANE_NAME_OFFSET_B             "offset-b"
153#define SANE_TITLE_OFFSET_B            "Offset blue"
154#define SANE_DESC_OFFSET_B             "The offset of the signal processor for blue"
155#define SANE_NAME_OFFSET_I             "offset-i"
156#define SANE_TITLE_OFFSET_I            "Offset infrared"
157#define SANE_DESC_OFFSET_I             "The offset of the signal processor for infrared"
158#define SANE_OFFSET_DEFAULT          DEFAULT_OFFSET
159#else
160#define SANE_NAME_GAIN               "gain"
161#define SANE_TITLE_GAIN              "Gain"
162#define SANE_DESC_GAIN               "The gain of the signal processor for the 4 CCD color filters (R,G,B,I)"
163#define SANE_GAIN_DEFAULT            0x13
164
165#define SANE_NAME_OFFSET             "offset"
166#define SANE_TITLE_OFFSET            "Offset"
167#define SANE_DESC_OFFSET             "The offset of the signal processor for the 4 CCD color filters (R,G,B,I)"
168#define SANE_OFFSET_DEFAULT          0
169#endif
170#define min(a,b) (((a)<(b))?(a):(b))
171#define max(a,b) (((a)>(b))?(a):(b))
172
173static const SANE_Range percentage_range_100 = {
174  0 << SANE_FIXED_SCALE_SHIFT,	  /* minimum */
175  100 << SANE_FIXED_SCALE_SHIFT,  /* maximum */
176  0 << SANE_FIXED_SCALE_SHIFT	  /* quantization */
177};
178
179/* From the firmware disassembly */
180static const SANE_Range gain_range = {
181  0,	  /* minimum */
182  63,     /* maximum */
183  0	  /* quantization */
184};
185
186/* From the firmware disassembly */
187static const SANE_Range offset_range = {
188  0,      /* minimum */
189  255,    /* maximum */
190  0	  /* quantization */
191};
192
193static const double gains[] = {
1941.000, 1.075, 1.154, 1.251, 1.362, 1.491, 1.653, /*  0,  5, 10, 15, 20, 25, 30 */
1951.858, 2.115, 2.458, 2.935, 3.638, 4.627         /* 35, 40, 45, 50, 55, 60 */
196};
197
198/**
199 * Callback called whenever a connected USB device reports a supported vendor
200 * and product id combination.
201 * Used by sane_init() and by sane_open().
202 *
203 * @param name Device name which has required vendor and product id
204 * @return SANE_STATUS_GOOD
205 */
206SANE_Status
207sanei_pieusb_find_device_callback (const char *devicename)
208{
209    struct Pieusb_Command_Status status;
210    SANE_Status r;
211    Pieusb_Device_Definition *dev;
212    int device_number; /* index in usb devices list maintained by sani_usb */
213    Pieusb_Scanner_Properties inq;
214    int retry;
215
216    DBG (DBG_info_proc, "sanei_pieusb_find_device_callback: %s\n", devicename);
217
218    /* Check if device is present in the Pieusb device list */
219    for (dev = pieusb_definition_list_head; dev; dev = dev->next) {
220        if (strcmp (dev->sane.name, devicename) == 0) {
221	    return SANE_STATUS_GOOD;
222        }
223    }
224
225    /* If not, create a new device struct */
226    dev = malloc (sizeof (*dev));
227    if (!dev) {
228        return SANE_STATUS_NO_MEM;
229    }
230
231    /* Get device number: index of the device in the sanei_usb devices list */
232    r = sanei_usb_open (devicename, &device_number);
233    if (r != SANE_STATUS_GOOD) {
234        free (dev);
235        DBG (DBG_error, "sanei_pieusb_find_device_callback: sanei_usb_open failed for device %s: %s\n",devicename,sane_strstatus(r));
236        return r;
237    }
238
239    /* Get device properties */
240
241    retry = 2;
242    while (retry > 0) {
243      retry--;
244      /* get inquiry data length */
245      sanei_pieusb_cmd_inquiry (device_number, &inq, 5, &status);
246      if (status.pieusb_status == PIEUSB_STATUS_GOOD) {
247	break;
248      }
249      else if (status.pieusb_status == PIEUSB_STATUS_IO_ERROR) {
250	if (retry > 0) {
251	  DBG (DBG_info_proc, "inquiry failed, resetting usb\n");
252	  if (sanei_pieusb_usb_reset(device_number) == SANE_STATUS_GOOD) {
253	    continue; /* retry after IEEE1284 reset */
254	  }
255	  if (sanei_usb_reset(device_number) == SANE_STATUS_GOOD) {
256	    continue; /* retry after USB reset */
257	  }
258	}
259      }
260      free (dev);
261      DBG (DBG_error, "sanei_pieusb_find_device_callback: get scanner properties (5 bytes) failed with %d\n", status.pieusb_status);
262      sanei_usb_close (device_number);
263      return sanei_pieusb_convert_status (status.pieusb_status);
264    }
265    /* get full inquiry data */
266    sanei_pieusb_cmd_inquiry(device_number, &inq, inq.additionalLength+4, &status);
267    if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
268        free (dev);
269        DBG (DBG_error, "sanei_pieusb_find_device_callback: get scanner properties failed\n");
270        sanei_usb_close (device_number);
271        return sanei_pieusb_convert_status (status.pieusb_status);
272    }
273
274    /* Close the device again */
275    sanei_usb_close(device_number);
276
277    /* Initialize device definition */
278    r = pieusb_initialize_device_definition(dev, &inq, devicename, pieusb_supported_usb_device.vendor, pieusb_supported_usb_device.product);
279    if (r != SANE_STATUS_GOOD) {
280      return r;
281    }
282
283    /* Output */
284    pieusb_print_inquiry (dev);
285
286    /* Check model number */
287    if (inq.model != pieusb_supported_usb_device.model) {
288        free (dev);
289        DBG (DBG_error, "sanei_pieusb_find_device_callback: wrong model number %d\n", inq.model);
290        return SANE_STATUS_INVAL;
291    }
292
293    dev->flags = pieusb_supported_usb_device.flags;
294
295    /* Found a supported scanner, put it in the definitions list*/
296    DBG (DBG_info_proc, "sanei_pieusb_find_device_callback: success\n");
297    dev->next = pieusb_definition_list_head;
298    pieusb_definition_list_head = dev;
299    return SANE_STATUS_GOOD;
300}
301
302/**
303 * Full initialization of a Pieusb_Device structure from INQUIRY data.
304 * The function is used in find_device_callback(), so when sane_init() or
305 * sane_open() is called.
306 *
307 * @param dev
308 */
309static SANE_Status
310pieusb_initialize_device_definition (Pieusb_Device_Definition* dev, Pieusb_Scanner_Properties* inq, const char* devicename,
311        SANE_Word vendor_id, SANE_Word product_id)
312{
313    char *pp, *buf;
314
315    /* Initialize device definition */
316    dev->next = NULL;
317    dev->sane.name = strdup(devicename);
318
319    /* Create 0-terminated string without trailing spaces for vendor */
320    buf = malloc(9);
321    if (buf == NULL)
322      return SANE_STATUS_NO_MEM;
323    memcpy(buf, inq->vendor, 8);
324    pp = buf + 8;
325    *pp-- = '\0';
326    while (*pp == ' ') *pp-- = '\0';
327    dev->sane.vendor = buf;
328
329    /* Create 0-terminated string without trailing spaces for model */
330    buf = malloc(17);
331    if (buf == NULL)
332      return SANE_STATUS_NO_MEM;
333    memcpy(buf, inq->product, 16);
334    pp = buf + 16;
335    *pp-- = '\0';
336    while (*pp == ' ') *pp-- = '\0';
337    dev->sane.model = buf;
338
339    dev->sane.type = "film scanner";
340    dev->vendorId = vendor_id;
341    dev->productId = product_id;
342
343    /* Create 0-terminated strings without trailing spaces for revision */
344    buf = malloc(5);
345    if (buf == NULL)
346      return SANE_STATUS_NO_MEM;
347    memcpy(buf, inq->productRevision, 4);
348    pp = buf + 4;
349    *pp-- = '\0';
350    while (*pp == ' ') *pp-- = '\0';
351    dev->version = buf;
352
353    dev->model = inq->model;
354
355    /* Maximum resolution values */
356    dev->maximum_resolution_x = inq->maxResolutionX;
357    dev->maximum_resolution_y = inq->maxResolutionY;
358    if (dev->maximum_resolution_y < 256) {
359        /* y res is a multiplier */
360        dev->maximum_resolution = dev->maximum_resolution_x;
361        dev->maximum_resolution_x *= dev->maximum_resolution_y;
362        dev->maximum_resolution_y = dev->maximum_resolution_x;
363    } else {
364      /* y res really is resolution */
365      dev->maximum_resolution = min (dev->maximum_resolution_x, dev->maximum_resolution_y);
366    }
367
368    /* Geometry */
369    dev->scan_bed_width = (double) inq->maxScanWidth / dev->maximum_resolution;
370    dev->scan_bed_height = (double) inq->maxScanHeight / dev->maximum_resolution;
371    dev->slide_top_left_x = inq->x0;
372    dev->slide_top_left_y = inq->y0;
373    dev->slide_width = (double) (inq->x1 - inq->x0) / dev->maximum_resolution;
374    dev->slide_height = (double) (inq->y1 - inq->y0) / dev->maximum_resolution;
375
376    /* Integer and bit-encoded properties */
377    dev->halftone_patterns = inq->halftones & 0x0f;
378    dev->color_filters = inq->filters;
379    dev->color_depths = inq->colorDepths;
380    dev->color_formats = inq->colorFormat;
381    dev->image_formats = inq->imageFormat;
382    dev->scan_capabilities = inq->scanCapability;
383    dev->optional_devices = inq->optionalDevices;
384    dev->enhancements = inq->enhancements;
385    dev->gamma_bits = inq->gammaBits;
386    dev->fast_preview_resolution = inq->previewScanResolution;
387    dev->minimum_highlight = inq->minumumHighlight;
388    dev->maximum_shadow = inq->maximumShadow;
389    dev->calibration_equation = inq->calibrationEquation;
390    dev->minimum_exposure = inq->minimumExposure;
391    dev->maximum_exposure = inq->maximumExposure*4; /* *4 to solve the strange situation that the default value is out of range */
392
393    dev->x0 = inq->x0;
394    dev->y0 = inq->y0;
395    dev->x1 = inq->x1;
396    dev->y1 = inq->y1;
397    dev->production = strndup(inq->production, 4);
398    dev->timestamp = strndup(inq->timestamp, 20);
399    dev->signature = (char *)strndup((char *)inq->signature, 40);
400
401    /* Ranges for various quantities */
402    dev->x_range.min = SANE_FIX (0);
403    dev->x_range.quant = SANE_FIX (0);
404    dev->x_range.max = SANE_FIX (dev->scan_bed_width * MM_PER_INCH);
405
406    dev->y_range.min = SANE_FIX (0);
407    dev->y_range.quant = SANE_FIX (0);
408    dev->y_range.max = SANE_FIX (dev->scan_bed_height * MM_PER_INCH);
409
410    dev->dpi_range.min = SANE_FIX (25);
411    dev->dpi_range.quant = SANE_FIX (1);
412    dev->dpi_range.max = SANE_FIX (max (dev->maximum_resolution_x, dev->maximum_resolution_y));
413
414    dev->shadow_range.min = SANE_FIX (0);
415    dev->shadow_range.quant = SANE_FIX (1);
416    dev->shadow_range.max = SANE_FIX (dev->maximum_shadow);
417
418    dev->highlight_range.min = SANE_FIX (dev->minimum_highlight);
419    dev->highlight_range.quant = SANE_FIX (1);
420    dev->highlight_range.max = SANE_FIX (100);
421
422    dev->exposure_range.min = dev->minimum_exposure;
423    dev->exposure_range.quant = 1;
424    dev->exposure_range.max = dev->maximum_exposure;
425
426    dev->dust_range.min = 0;
427    dev->dust_range.quant = 1;
428    dev->dust_range.max = 100;
429
430    /* Enumerated ranges vor various quantities */
431    /*TODO: create from inq->filters */
432    dev->scan_mode_list[0] = SANE_VALUE_SCAN_MODE_LINEART;
433    dev->scan_mode_list[1] = SANE_VALUE_SCAN_MODE_HALFTONE;
434    dev->scan_mode_list[2] = SANE_VALUE_SCAN_MODE_GRAY;
435    dev->scan_mode_list[3] = SANE_VALUE_SCAN_MODE_COLOR;
436    dev->scan_mode_list[4] = SANE_VALUE_SCAN_MODE_RGBI;
437    dev->scan_mode_list[5] = 0;
438
439    dev->calibration_mode_list[0] = SCAN_CALIBRATION_DEFAULT;
440    dev->calibration_mode_list[1] = SCAN_CALIBRATION_AUTO;
441    dev->calibration_mode_list[2] = SCAN_CALIBRATION_PREVIEW;
442    dev->calibration_mode_list[3] = SCAN_CALIBRATION_OPTIONS;
443    dev->calibration_mode_list[4] = 0;
444
445    dev->gain_adjust_list[0] = SCAN_GAIN_ADJUST_03;
446    dev->gain_adjust_list[1] = SCAN_GAIN_ADJUST_05;
447    dev->gain_adjust_list[2] = SCAN_GAIN_ADJUST_08;
448    dev->gain_adjust_list[3] = SCAN_GAIN_ADJUST_10;
449    dev->gain_adjust_list[4] = SCAN_GAIN_ADJUST_12;
450    dev->gain_adjust_list[5] = SCAN_GAIN_ADJUST_16;
451    dev->gain_adjust_list[6] = SCAN_GAIN_ADJUST_19;
452    dev->gain_adjust_list[7] = SCAN_GAIN_ADJUST_24;
453    dev->gain_adjust_list[8] = SCAN_GAIN_ADJUST_30;
454    dev->gain_adjust_list[9] = 0;
455
456    /*TODO: create from inq->colorDepths? Maybe not: didn't experiment with
457     * 4 and 12 bit depths. Don;t know how they behave. */
458    dev->bpp_list[0] = 3; /* count */
459    dev->bpp_list[1] = 1;
460    dev->bpp_list[2] = 8;
461    dev->bpp_list[3] = 16;
462
463    /* Infrared */
464    dev->ir_sw_list[0] = "None";
465    dev->ir_sw_list[1] = "Reduce red overlap";
466    dev->ir_sw_list[2] = "Remove dirt";
467    dev->ir_sw_list[3] = 0;
468
469    dev->grain_sw_list[0] = 4;
470    dev->grain_sw_list[1] = 0;
471    dev->grain_sw_list[2] = 1;
472    dev->grain_sw_list[3] = 2;
473    dev->grain_sw_list[4] = 3;
474    dev->grain_sw_list[5] = 0;
475
476    dev->crop_sw_list[0] = "None";
477    dev->crop_sw_list[1] = "Outside";
478    dev->crop_sw_list[2] = "Inside";
479    dev->crop_sw_list[3] = 0;
480
481    /* halftone_list */
482    dev->halftone_list[0] = "53lpi 45d ROUND"; /* 8x8 pattern */
483    dev->halftone_list[1] = "70lpi 45d ROUND"; /* 6x6 pattern */
484    dev->halftone_list[2] = "75lpi Hori. Line"; /* 4x4 pattern */
485    dev->halftone_list[3] = "4X4 BAYER"; /* 4x4 pattern */
486    dev->halftone_list[4] = "4X4 SCROLL"; /* 4x4 pattern */
487    dev->halftone_list[5] = "5x5 26 Levels"; /* 5x5 pattern */
488    dev->halftone_list[6] = "4x4 SQUARE"; /* 4x4 pattern */
489    dev->halftone_list[7] = "5x5 TILE"; /* 5x5 pattern */
490    dev->halftone_list[8] = 0;
491
492    return SANE_STATUS_GOOD;
493}
494
495/**
496 * Output device definition.
497 * The function is used in find_device_callback(), so when sane_init() or
498 * sane_open() is called.
499 *
500 * @param dev Device to output
501 */
502static void
503pieusb_print_inquiry (Pieusb_Device_Definition * dev)
504{
505  DBG (DBG_inquiry, "INQUIRY:\n");
506  DBG (DBG_inquiry, "========\n");
507  DBG (DBG_inquiry, "\n");
508  DBG (DBG_inquiry, "vendor........................: '%s'\n", dev->sane.vendor);
509  DBG (DBG_inquiry, "product.......................: '%s'\n", dev->sane.model);
510  DBG (DBG_inquiry, "model  .......................: 0x%04x\n", dev->model);
511  DBG (DBG_inquiry, "version.......................: '%s'\n", dev->version);
512
513  DBG (DBG_inquiry, "X resolution..................: %d dpi\n",
514       dev->maximum_resolution_x);
515  DBG (DBG_inquiry, "Y resolution..................: %d dpi\n",
516       dev->maximum_resolution_y);
517  DBG (DBG_inquiry, "pixel resolution..............: %d dpi\n",
518       dev->maximum_resolution);
519  DBG (DBG_inquiry, "fb width......................: %f in\n",
520       dev->scan_bed_width);
521  DBG (DBG_inquiry, "fb length.....................: %f in\n",
522       dev->scan_bed_height);
523
524  DBG (DBG_inquiry, "transparency width............: %f in\n",
525       dev->slide_width);
526  DBG (DBG_inquiry, "transparency length...........: %f in\n",
527       dev->slide_height);
528  DBG (DBG_inquiry, "transparency offset...........: %d,%d\n",
529       dev->slide_top_left_x, dev->slide_top_left_y);
530
531  DBG (DBG_inquiry, "# of halftones................: %d\n",
532       dev->halftone_patterns);
533
534  DBG (DBG_inquiry, "One pass color................: %s\n",
535       dev->color_filters & SCAN_ONE_PASS_COLOR ? "yes" : "no");
536
537  DBG (DBG_inquiry, "Filters.......................: %s%s%s%s%s (%02x)\n",
538       dev->color_filters & SCAN_FILTER_INFRARED ? "Infrared " : "",
539       dev->color_filters & SCAN_FILTER_RED ? "Red " : "",
540       dev->color_filters & SCAN_FILTER_GREEN ? "Green " : "",
541       dev->color_filters & SCAN_FILTER_BLUE ? "Blue " : "",
542       dev->color_filters & SCAN_FILTER_NEUTRAL ? "Neutral " : "",
543       dev->color_filters);
544
545  DBG (DBG_inquiry, "Color depths..................: %s%s%s%s%s%s (%02x)\n",
546       dev->color_depths & SCAN_COLOR_DEPTH_16 ? "16 bit " : "",
547       dev->color_depths & SCAN_COLOR_DEPTH_12 ? "12 bit " : "",
548       dev->color_depths & SCAN_COLOR_DEPTH_10 ? "10 bit " : "",
549       dev->color_depths & SCAN_COLOR_DEPTH_8 ? "8 bit " : "",
550       dev->color_depths & SCAN_COLOR_DEPTH_4 ? "4 bit " : "",
551       dev->color_depths & SCAN_COLOR_DEPTH_1 ? "1 bit " : "",
552       dev->color_depths);
553
554  DBG (DBG_inquiry, "Color Format..................: %s%s%s (%02x)\n",
555       dev->color_formats & SCAN_COLOR_FORMAT_INDEX ? "Indexed " : "",
556       dev->color_formats & SCAN_COLOR_FORMAT_LINE ? "Line " : "",
557       dev->color_formats & SCAN_COLOR_FORMAT_PIXEL ? "Pixel " : "",
558       dev->color_formats);
559
560  DBG (DBG_inquiry, "Image Format..................: %s%s%s%s (%02x)\n",
561       dev->image_formats & SCAN_IMG_FMT_OKLINE ? "OKLine " : "",
562       dev->image_formats & SCAN_IMG_FMT_BLK_ONE ? "BlackOne " : "",
563       dev->image_formats & SCAN_IMG_FMT_MOTOROLA ? "Motorola " : "",
564       dev->image_formats & SCAN_IMG_FMT_INTEL ? "Intel" : "",
565       dev->image_formats);
566
567  DBG (DBG_inquiry,
568       "Scan Capability...............: %s%s%s%s%d speeds (%02x)\n",
569       dev->scan_capabilities & SCAN_CAP_PWRSAV ? "PowerSave " : "",
570       dev->scan_capabilities & SCAN_CAP_EXT_CAL ? "ExtCal " : "",
571       dev->scan_capabilities & SCAN_CAP_FAST_PREVIEW ? "FastPreview" :
572       "",
573       dev->scan_capabilities & SCAN_CAP_DISABLE_CAL ? "DisCal " : "",
574       dev->scan_capabilities & SCAN_CAP_SPEEDS,
575       dev->scan_capabilities);
576
577  DBG (DBG_inquiry, "Optional Devices..............: %s%s%s%s (%02x)\n",
578       dev->optional_devices & SCAN_OPT_DEV_MPCL ? "MultiPageLoad " :
579       "",
580       dev->optional_devices & SCAN_OPT_DEV_TP1 ? "TransModule1 " : "",
581       dev->optional_devices & SCAN_OPT_DEV_TP ? "TransModule " : "",
582       dev->optional_devices & SCAN_OPT_DEV_ADF ? "ADF " : "",
583       dev->optional_devices);
584
585  DBG (DBG_inquiry, "Enhancement...................: %02x\n",
586       dev->enhancements);
587  DBG (DBG_inquiry, "Gamma bits....................: %d\n",
588       dev->gamma_bits);
589
590  DBG (DBG_inquiry, "Fast Preview Resolution.......: %d\n",
591       dev->fast_preview_resolution);
592  DBG (DBG_inquiry, "Min Highlight.................: %d\n",
593       dev->minimum_highlight);
594  DBG (DBG_inquiry, "Max Shadow....................: %d\n",
595       dev->maximum_shadow);
596  DBG (DBG_inquiry, "Cal Eqn.......................: %d\n",
597       dev->calibration_equation);
598  DBG (DBG_inquiry, "Min Exposure..................: %d\n",
599       dev->minimum_exposure);
600  DBG (DBG_inquiry, "Max Exposure..................: %d\n",
601       dev->maximum_exposure);
602
603  DBG (DBG_inquiry, "x0,y0 x1,y1...................: %d,%d %d,%d\n",
604       dev->x0, dev->y0, dev->x1, dev->y1);
605  DBG (DBG_inquiry, "production....................: '%s'\n",
606       dev->production);
607  DBG (DBG_inquiry, "timestamp.....................: '%s'\n",
608       dev->timestamp);
609  DBG (DBG_inquiry, "signature.....................: '%s'\n",
610       dev->signature);
611
612}
613
614/**
615 * Initiaize scanner options from the device definition and from exposure,
616 * gain and offset defaults. The function is called by sane_open(), when no
617 * optimized settings are available yet. The scanner object is fully
618 * initialized in sane_start().
619 *
620 * @param scanner Scanner to initialize
621 * @return SANE_STATUS_GOOD
622 */
623SANE_Status
624sanei_pieusb_init_options (Pieusb_Scanner* scanner)
625{
626    int i;
627
628    DBG (DBG_info_proc, "sanei_pieusb_init_options\n");
629
630    memset (scanner->opt, 0, sizeof (scanner->opt));
631    memset (scanner->val, 0, sizeof (scanner->val));
632
633    for (i = 0; i < NUM_OPTIONS; ++i) {
634        scanner->opt[i].size = sizeof (SANE_Word);
635        scanner->opt[i].cap = SANE_CAP_SOFT_SELECT | SANE_CAP_SOFT_DETECT;
636    }
637
638    /* Number of options (a pseudo-option) */
639    scanner->opt[OPT_NUM_OPTS].name = SANE_NAME_NUM_OPTIONS;
640    scanner->opt[OPT_NUM_OPTS].title = SANE_TITLE_NUM_OPTIONS;
641    scanner->opt[OPT_NUM_OPTS].desc = SANE_DESC_NUM_OPTIONS;
642    scanner->opt[OPT_NUM_OPTS].type = SANE_TYPE_INT;
643    scanner->opt[OPT_NUM_OPTS].cap = SANE_CAP_SOFT_DETECT;
644    scanner->val[OPT_NUM_OPTS].w = NUM_OPTIONS;
645
646    /* "Mode" group: */
647    scanner->opt[OPT_MODE_GROUP].title = "Scan Mode";
648    scanner->opt[OPT_MODE_GROUP].desc = "";
649    scanner->opt[OPT_MODE_GROUP].type = SANE_TYPE_GROUP;
650    scanner->opt[OPT_MODE_GROUP].cap = 0;
651    scanner->opt[OPT_MODE_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
652
653    /* scan mode */
654    scanner->opt[OPT_MODE].name = SANE_NAME_SCAN_MODE;
655    scanner->opt[OPT_MODE].title = SANE_TITLE_SCAN_MODE;
656    scanner->opt[OPT_MODE].desc = SANE_DESC_SCAN_MODE;
657    scanner->opt[OPT_MODE].type = SANE_TYPE_STRING;
658    scanner->opt[OPT_MODE].size = max_string_size ((SANE_String_Const const *) scanner->device->scan_mode_list);
659    scanner->opt[OPT_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
660    scanner->opt[OPT_MODE].constraint.string_list = (SANE_String_Const const *) scanner->device->scan_mode_list;
661    scanner->val[OPT_MODE].s = (SANE_Char *) strdup (scanner->device->scan_mode_list[3]); /* default RGB */
662
663    /* bit depth */
664    scanner->opt[OPT_BIT_DEPTH].name = SANE_NAME_BIT_DEPTH;
665    scanner->opt[OPT_BIT_DEPTH].title = SANE_TITLE_BIT_DEPTH;
666    scanner->opt[OPT_BIT_DEPTH].desc = SANE_DESC_BIT_DEPTH;
667    scanner->opt[OPT_BIT_DEPTH].type = SANE_TYPE_INT;
668    scanner->opt[OPT_BIT_DEPTH].constraint_type = SANE_CONSTRAINT_WORD_LIST;
669    scanner->opt[OPT_BIT_DEPTH].size = sizeof (SANE_Word);
670    scanner->opt[OPT_BIT_DEPTH].constraint.word_list = scanner->device->bpp_list;
671    scanner->val[OPT_BIT_DEPTH].w = scanner->device->bpp_list[2];
672
673    /* resolution */
674    scanner->opt[OPT_RESOLUTION].name = SANE_NAME_SCAN_RESOLUTION;
675    scanner->opt[OPT_RESOLUTION].title = SANE_TITLE_SCAN_RESOLUTION;
676    scanner->opt[OPT_RESOLUTION].desc = SANE_DESC_SCAN_RESOLUTION;
677    scanner->opt[OPT_RESOLUTION].type = SANE_TYPE_FIXED;
678    scanner->opt[OPT_RESOLUTION].unit = SANE_UNIT_DPI;
679    scanner->opt[OPT_RESOLUTION].constraint_type = SANE_CONSTRAINT_RANGE;
680    scanner->opt[OPT_RESOLUTION].constraint.range = &scanner->device->dpi_range;
681    scanner->val[OPT_RESOLUTION].w = scanner->device->fast_preview_resolution << SANE_FIXED_SCALE_SHIFT;
682
683    /* halftone pattern */
684    scanner->opt[OPT_HALFTONE_PATTERN].name = SANE_NAME_HALFTONE_PATTERN;
685    scanner->opt[OPT_HALFTONE_PATTERN].title = SANE_TITLE_HALFTONE_PATTERN;
686    scanner->opt[OPT_HALFTONE_PATTERN].desc = SANE_DESC_HALFTONE_PATTERN;
687    scanner->opt[OPT_HALFTONE_PATTERN].type = SANE_TYPE_STRING;
688    scanner->opt[OPT_HALFTONE_PATTERN].size = max_string_size ((SANE_String_Const const *) scanner->device->halftone_list);
689    scanner->opt[OPT_HALFTONE_PATTERN].constraint_type = SANE_CONSTRAINT_STRING_LIST;
690    scanner->opt[OPT_HALFTONE_PATTERN].constraint.string_list = (SANE_String_Const const *) scanner->device->halftone_list;
691    scanner->val[OPT_HALFTONE_PATTERN].s = (SANE_Char *) strdup (scanner->device->halftone_list[6]);
692    scanner->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; /* Not implemented, and only meaningful at depth 1 */
693
694    /* lineart threshold */
695    scanner->opt[OPT_THRESHOLD].name = SANE_NAME_THRESHOLD;
696    scanner->opt[OPT_THRESHOLD].title = SANE_TITLE_THRESHOLD;
697    scanner->opt[OPT_THRESHOLD].desc = SANE_DESC_THRESHOLD;
698    scanner->opt[OPT_THRESHOLD].type = SANE_TYPE_FIXED;
699    scanner->opt[OPT_THRESHOLD].unit = SANE_UNIT_PERCENT;
700    scanner->opt[OPT_THRESHOLD].constraint_type = SANE_CONSTRAINT_RANGE;
701    scanner->opt[OPT_THRESHOLD].constraint.range = &percentage_range_100;
702    scanner->val[OPT_THRESHOLD].w = SANE_FIX (50);
703    /* scanner->opt[OPT_THRESHOLD].cap |= SANE_CAP_INACTIVE; Not implemented, and only meaningful at depth 1 */
704
705    /* create a sharper scan at the cost of scan time */
706    scanner->opt[OPT_SHARPEN].name = "sharpen";
707    scanner->opt[OPT_SHARPEN].title = "Sharpen scan";
708    scanner->opt[OPT_SHARPEN].desc = "Sharpen scan by taking more time to discharge the CCD.";
709    scanner->opt[OPT_SHARPEN].type = SANE_TYPE_BOOL;
710    scanner->opt[OPT_SHARPEN].unit = SANE_UNIT_NONE;
711    scanner->opt[OPT_SHARPEN].constraint_type = SANE_CONSTRAINT_NONE;
712    scanner->val[OPT_SHARPEN].b = SANE_FALSE;
713    scanner->opt[OPT_SHARPEN].cap |= SANE_CAP_SOFT_SELECT;
714
715    /* skip the auto-calibration phase before the scan */
716    scanner->opt[OPT_SHADING_ANALYSIS].name = "shading-analysis";
717    scanner->opt[OPT_SHADING_ANALYSIS].title = "Perform shading analysis";
718    scanner->opt[OPT_SHADING_ANALYSIS].desc = "Collect shading reference data before scanning the image. If set to 'no', this option may be overridden by the scanner.";
719    scanner->opt[OPT_SHADING_ANALYSIS].type = SANE_TYPE_BOOL;
720    scanner->opt[OPT_SHADING_ANALYSIS].unit = SANE_UNIT_NONE;
721    scanner->opt[OPT_SHADING_ANALYSIS].constraint_type = SANE_CONSTRAINT_NONE;
722    scanner->val[OPT_SHADING_ANALYSIS].b = SANE_FALSE;
723    scanner->opt[OPT_SHADING_ANALYSIS].cap |= SANE_CAP_SOFT_SELECT;
724
725    /* use auto-calibration settings for scan */
726    scanner->opt[OPT_CALIBRATION_MODE].name = "calibration";
727    scanner->opt[OPT_CALIBRATION_MODE].title = "Calibration mode";
728    scanner->opt[OPT_CALIBRATION_MODE].desc = "How to calibrate the scanner.";
729    scanner->opt[OPT_CALIBRATION_MODE].type = SANE_TYPE_STRING;
730    scanner->opt[OPT_CALIBRATION_MODE].size = max_string_size ((SANE_String_Const const *) scanner->device->calibration_mode_list);
731    scanner->opt[OPT_CALIBRATION_MODE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
732    scanner->opt[OPT_CALIBRATION_MODE].constraint.string_list = (SANE_String_Const const *) scanner->device->calibration_mode_list;
733    scanner->val[OPT_CALIBRATION_MODE].s = (SANE_Char *) strdup (scanner->device->calibration_mode_list[1]); /* default auto */
734
735    /* OPT_GAIN_ADJUST */
736    scanner->opt[OPT_GAIN_ADJUST].name = "gain-adjust";
737    scanner->opt[OPT_GAIN_ADJUST].title = "Adjust gain";
738    scanner->opt[OPT_GAIN_ADJUST].desc = "Adjust gain determined by calibration procedure.";
739    scanner->opt[OPT_GAIN_ADJUST].type = SANE_TYPE_STRING;
740    scanner->opt[OPT_GAIN_ADJUST].size = max_string_size ((SANE_String_Const const *) scanner->device->gain_adjust_list);
741    scanner->opt[OPT_GAIN_ADJUST].constraint_type = SANE_CONSTRAINT_STRING_LIST;
742    scanner->opt[OPT_GAIN_ADJUST].constraint.string_list = (SANE_String_Const const *) scanner->device->gain_adjust_list;
743    scanner->val[OPT_GAIN_ADJUST].s = (SANE_Char *) strdup (scanner->device->gain_adjust_list[2]); /* x 1.0 (no change) */
744
745    /* scan infrared channel faster but less accurate */
746    scanner->opt[OPT_FAST_INFRARED].name = "fast-infrared";
747    scanner->opt[OPT_FAST_INFRARED].title = "Fast infrared scan";
748    scanner->opt[OPT_FAST_INFRARED].desc = "Do not reposition scan head before scanning infrared line. Results in an infrared offset which may deteriorate IR dust and scratch removal.";
749    scanner->opt[OPT_FAST_INFRARED].type = SANE_TYPE_BOOL;
750    scanner->opt[OPT_FAST_INFRARED].unit = SANE_UNIT_NONE;
751    scanner->opt[OPT_FAST_INFRARED].constraint_type = SANE_CONSTRAINT_NONE;
752    scanner->val[OPT_FAST_INFRARED].b = SANE_FALSE;
753    scanner->opt[OPT_FAST_INFRARED].cap |= SANE_CAP_SOFT_SELECT;
754
755    /* automatically advance to next slide after scan */
756    scanner->opt[OPT_ADVANCE_SLIDE].name = "advance";
757    scanner->opt[OPT_ADVANCE_SLIDE].title = "Advance slide";
758    scanner->opt[OPT_ADVANCE_SLIDE].desc = "Automatically advance to next slide after scan";
759    scanner->opt[OPT_ADVANCE_SLIDE].type = SANE_TYPE_BOOL;
760    scanner->opt[OPT_ADVANCE_SLIDE].unit = SANE_UNIT_NONE;
761    scanner->opt[OPT_ADVANCE_SLIDE].constraint_type = SANE_CONSTRAINT_NONE;
762    scanner->val[OPT_ADVANCE_SLIDE].w = SANE_TRUE;
763    scanner->opt[OPT_ADVANCE_SLIDE].cap |= SANE_CAP_SOFT_SELECT;
764
765    /* "Geometry" group: */
766    scanner->opt[OPT_GEOMETRY_GROUP].title = "Geometry";
767    scanner->opt[OPT_GEOMETRY_GROUP].desc = "";
768    scanner->opt[OPT_GEOMETRY_GROUP].type = SANE_TYPE_GROUP;
769    scanner->opt[OPT_GEOMETRY_GROUP].cap = SANE_CAP_ADVANCED;
770    scanner->opt[OPT_GEOMETRY_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
771
772    /* top-left x */
773    scanner->opt[OPT_TL_X].name = SANE_NAME_SCAN_TL_X;
774    scanner->opt[OPT_TL_X].title = SANE_TITLE_SCAN_TL_X;
775    scanner->opt[OPT_TL_X].desc = SANE_DESC_SCAN_TL_X;
776    scanner->opt[OPT_TL_X].type = SANE_TYPE_FIXED;
777    scanner->opt[OPT_TL_X].unit = SANE_UNIT_MM;
778    scanner->opt[OPT_TL_X].constraint_type = SANE_CONSTRAINT_RANGE;
779    scanner->opt[OPT_TL_X].constraint.range = &(scanner->device->x_range);
780    scanner->val[OPT_TL_X].w = 0;
781
782    /* top-left y */
783    scanner->opt[OPT_TL_Y].name = SANE_NAME_SCAN_TL_Y;
784    scanner->opt[OPT_TL_Y].title = SANE_TITLE_SCAN_TL_Y;
785    scanner->opt[OPT_TL_Y].desc = SANE_DESC_SCAN_TL_Y;
786    scanner->opt[OPT_TL_Y].type = SANE_TYPE_FIXED;
787    scanner->opt[OPT_TL_Y].unit = SANE_UNIT_MM;
788    scanner->opt[OPT_TL_Y].constraint_type = SANE_CONSTRAINT_RANGE;
789    scanner->opt[OPT_TL_Y].constraint.range = &(scanner->device->y_range);
790    scanner->val[OPT_TL_Y].w = 0;
791
792    /* bottom-right x */
793    scanner->opt[OPT_BR_X].name = SANE_NAME_SCAN_BR_X;
794    scanner->opt[OPT_BR_X].title = SANE_TITLE_SCAN_BR_X;
795    scanner->opt[OPT_BR_X].desc = SANE_DESC_SCAN_BR_X;
796    scanner->opt[OPT_BR_X].type = SANE_TYPE_FIXED;
797    scanner->opt[OPT_BR_X].unit = SANE_UNIT_MM;
798    scanner->opt[OPT_BR_X].constraint_type = SANE_CONSTRAINT_RANGE;
799    scanner->opt[OPT_BR_X].constraint.range = &(scanner->device->x_range);
800    scanner->val[OPT_BR_X].w = scanner->device->x_range.max;
801
802    /* bottom-right y */
803    scanner->opt[OPT_BR_Y].name = SANE_NAME_SCAN_BR_Y;
804    scanner->opt[OPT_BR_Y].title = SANE_TITLE_SCAN_BR_Y;
805    scanner->opt[OPT_BR_Y].desc = SANE_DESC_SCAN_BR_Y;
806    scanner->opt[OPT_BR_Y].type = SANE_TYPE_FIXED;
807    scanner->opt[OPT_BR_Y].unit = SANE_UNIT_MM;
808    scanner->opt[OPT_BR_Y].constraint_type = SANE_CONSTRAINT_RANGE;
809    scanner->opt[OPT_BR_Y].constraint.range = &(scanner->device->y_range);
810    scanner->val[OPT_BR_Y].w = scanner->device->y_range.max;
811
812    /* "Enhancement" group: */
813    scanner->opt[OPT_ENHANCEMENT_GROUP].title = "Enhancement";
814    scanner->opt[OPT_ENHANCEMENT_GROUP].desc = "";
815    scanner->opt[OPT_ENHANCEMENT_GROUP].type = SANE_TYPE_GROUP;
816    scanner->opt[OPT_ENHANCEMENT_GROUP].cap = 0;
817    scanner->opt[OPT_ENHANCEMENT_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
818
819    /* correct data for lamp variations (shading) */
820    scanner->opt[OPT_CORRECT_SHADING].name = "correct-shading";
821    scanner->opt[OPT_CORRECT_SHADING].title = "Correct shading";
822    scanner->opt[OPT_CORRECT_SHADING].desc = "Correct data for lamp variations (shading)";
823    scanner->opt[OPT_CORRECT_SHADING].type = SANE_TYPE_BOOL;
824    scanner->opt[OPT_CORRECT_SHADING].unit = SANE_UNIT_NONE;
825    scanner->val[OPT_CORRECT_SHADING].w = SANE_TRUE;
826
827    /* correct infrared for red crosstalk */
828    scanner->opt[OPT_CORRECT_INFRARED].name = "correct-infrared";
829    scanner->opt[OPT_CORRECT_INFRARED].title = "Correct infrared";
830    scanner->opt[OPT_CORRECT_INFRARED].desc = "Correct infrared for red crosstalk";
831    scanner->opt[OPT_CORRECT_INFRARED].type = SANE_TYPE_BOOL;
832    scanner->opt[OPT_CORRECT_INFRARED].unit = SANE_UNIT_NONE;
833    scanner->val[OPT_CORRECT_INFRARED].w = SANE_FALSE;
834
835    /* detect and remove dust and scratch artifacts */
836    scanner->opt[OPT_CLEAN_IMAGE].name = "clean-image";
837    scanner->opt[OPT_CLEAN_IMAGE].title = "Clean image";
838    scanner->opt[OPT_CLEAN_IMAGE].desc = "Detect and remove dust and scratch artifacts";
839    scanner->opt[OPT_CLEAN_IMAGE].type = SANE_TYPE_BOOL;
840    scanner->opt[OPT_CLEAN_IMAGE].unit = SANE_UNIT_NONE;
841    scanner->val[OPT_CLEAN_IMAGE].w = SANE_FALSE;
842
843    /* strength of grain filtering */
844    scanner->opt[OPT_SMOOTH_IMAGE].name = "smooth";
845    scanner->opt[OPT_SMOOTH_IMAGE].title = "Attenuate film grain";
846    scanner->opt[OPT_SMOOTH_IMAGE].desc = "Amount of smoothening";
847    scanner->opt[OPT_SMOOTH_IMAGE].type = SANE_TYPE_INT;
848    scanner->opt[OPT_SMOOTH_IMAGE].constraint_type = SANE_CONSTRAINT_WORD_LIST;
849    scanner->opt[OPT_SMOOTH_IMAGE].size = sizeof (SANE_Word);
850    scanner->opt[OPT_SMOOTH_IMAGE].constraint.word_list = scanner->device->grain_sw_list;
851    scanner->val[OPT_SMOOTH_IMAGE].w = scanner->device->grain_sw_list[1];
852    if (scanner->opt[OPT_SMOOTH_IMAGE].constraint.word_list[0] < 2) {
853        scanner->opt[OPT_SMOOTH_IMAGE].cap |= SANE_CAP_INACTIVE;
854    }
855
856    /* gamma correction, to make image sRGB like */
857    scanner->opt[OPT_TRANSFORM_TO_SRGB].name = "srgb";
858    scanner->opt[OPT_TRANSFORM_TO_SRGB].title = "sRGB colors";
859    scanner->opt[OPT_TRANSFORM_TO_SRGB].desc = "Transform image to approximate sRGB color space";
860    scanner->opt[OPT_TRANSFORM_TO_SRGB].type = SANE_TYPE_BOOL;
861    scanner->opt[OPT_TRANSFORM_TO_SRGB].unit = SANE_UNIT_NONE;
862    scanner->val[OPT_TRANSFORM_TO_SRGB].w = SANE_FALSE;
863    scanner->opt[OPT_TRANSFORM_TO_SRGB].cap |= SANE_CAP_INACTIVE;
864
865    /* color correction for generic negative film */
866    scanner->opt[OPT_INVERT_IMAGE].name = "invert";
867    scanner->opt[OPT_INVERT_IMAGE].title = "Invert colors";
868    scanner->opt[OPT_INVERT_IMAGE].desc = "Correct for generic negative film";
869    scanner->opt[OPT_INVERT_IMAGE].type = SANE_TYPE_BOOL;
870    scanner->opt[OPT_INVERT_IMAGE].unit = SANE_UNIT_NONE;
871    scanner->val[OPT_INVERT_IMAGE].w = SANE_FALSE;
872    scanner->opt[OPT_INVERT_IMAGE].cap |= SANE_CAP_INACTIVE;
873
874    /* crop image */
875    scanner->opt[OPT_CROP_IMAGE].name = "crop";
876    scanner->opt[OPT_CROP_IMAGE].title = "Cropping";
877    scanner->opt[OPT_CROP_IMAGE].desc = "How to crop the image";
878    scanner->opt[OPT_CROP_IMAGE].type = SANE_TYPE_STRING;
879    scanner->opt[OPT_CROP_IMAGE].size = max_string_size ((SANE_String_Const const *)(void*) scanner->device->crop_sw_list);
880    scanner->opt[OPT_CROP_IMAGE].constraint_type = SANE_CONSTRAINT_STRING_LIST;
881    scanner->opt[OPT_CROP_IMAGE].constraint.string_list = (SANE_String_Const const *)(void*) scanner->device->crop_sw_list;
882    scanner->val[OPT_CROP_IMAGE].s = (SANE_Char *) strdup (scanner->device->crop_sw_list[2]);
883
884    /* "Advanced" group: */
885    scanner->opt[OPT_ADVANCED_GROUP].title = "Advanced";
886    scanner->opt[OPT_ADVANCED_GROUP].desc = "";
887    scanner->opt[OPT_ADVANCED_GROUP].type = SANE_TYPE_GROUP;
888    scanner->opt[OPT_ADVANCED_GROUP].cap = SANE_CAP_ADVANCED;
889    scanner->opt[OPT_ADVANCED_GROUP].constraint_type = SANE_CONSTRAINT_NONE;
890
891    /* preview */
892    scanner->opt[OPT_PREVIEW].name = SANE_NAME_PREVIEW;
893    scanner->opt[OPT_PREVIEW].title = SANE_TITLE_PREVIEW;
894    scanner->opt[OPT_PREVIEW].desc = SANE_DESC_PREVIEW;
895    scanner->opt[OPT_PREVIEW].type = SANE_TYPE_BOOL;
896    scanner->val[OPT_PREVIEW].w = SANE_FALSE;
897
898    /* save shading data */
899    scanner->opt[OPT_SAVE_SHADINGDATA].name = "save-shading-data";
900    scanner->opt[OPT_SAVE_SHADINGDATA].title = "Save shading data";
901    scanner->opt[OPT_SAVE_SHADINGDATA].desc = "Save shading data in 'pieusb.shading'";
902    scanner->opt[OPT_SAVE_SHADINGDATA].type = SANE_TYPE_BOOL;
903    scanner->val[OPT_SAVE_SHADINGDATA].w = SANE_FALSE;
904
905    /* save CCD mask */
906    scanner->opt[OPT_SAVE_CCDMASK].name = "save-ccdmask";
907    scanner->opt[OPT_SAVE_CCDMASK].title = "Save CCD mask";
908    scanner->opt[OPT_SAVE_CCDMASK].desc = "Save CCD mask 'pieusb.ccd'";
909    scanner->opt[OPT_SAVE_CCDMASK].type = SANE_TYPE_BOOL;
910    scanner->val[OPT_SAVE_CCDMASK].w = SANE_FALSE;
911
912    scanner->opt[OPT_LIGHT].name = "light";
913    scanner->opt[OPT_LIGHT].title = "Light";
914    scanner->opt[OPT_LIGHT].desc = "Light";
915    scanner->opt[OPT_LIGHT].type = SANE_TYPE_INT;
916    scanner->opt[OPT_LIGHT].unit = SANE_UNIT_MICROSECOND;
917    scanner->opt[OPT_LIGHT].cap |= SANE_CAP_SOFT_SELECT;
918    scanner->opt[OPT_LIGHT].size = sizeof(SANE_Word);
919    scanner->val[OPT_LIGHT].w = DEFAULT_LIGHT;
920
921    scanner->opt[OPT_DOUBLE_TIMES].name = "double-times";
922    scanner->opt[OPT_DOUBLE_TIMES].title = "Double times";
923    scanner->opt[OPT_DOUBLE_TIMES].desc = "Double times";
924    scanner->opt[OPT_DOUBLE_TIMES].type = SANE_TYPE_INT;
925    scanner->opt[OPT_DOUBLE_TIMES].unit = SANE_UNIT_MICROSECOND;
926    scanner->opt[OPT_DOUBLE_TIMES].cap |= SANE_CAP_SOFT_SELECT;
927    scanner->opt[OPT_DOUBLE_TIMES].size = sizeof(SANE_Word);
928    scanner->val[OPT_DOUBLE_TIMES].w = DEFAULT_DOUBLE_TIMES;
929
930    /* exposure times for R, G, B and I */
931    scanner->opt[OPT_SET_EXPOSURE_R].name = SANE_NAME_EXPOSURE_R;
932    scanner->opt[OPT_SET_EXPOSURE_R].title = SANE_TITLE_EXPOSURE_R;
933    scanner->opt[OPT_SET_EXPOSURE_R].desc = SANE_DESC_EXPOSURE_R;
934    scanner->opt[OPT_SET_EXPOSURE_G].name = SANE_NAME_EXPOSURE_G;
935    scanner->opt[OPT_SET_EXPOSURE_G].title = SANE_TITLE_EXPOSURE_G;
936    scanner->opt[OPT_SET_EXPOSURE_G].desc = SANE_DESC_EXPOSURE_G;
937    scanner->opt[OPT_SET_EXPOSURE_B].name = SANE_NAME_EXPOSURE_B;
938    scanner->opt[OPT_SET_EXPOSURE_B].title = SANE_TITLE_EXPOSURE_B;
939    scanner->opt[OPT_SET_EXPOSURE_B].desc = SANE_DESC_EXPOSURE_B;
940    scanner->opt[OPT_SET_EXPOSURE_I].name = SANE_NAME_EXPOSURE_I;
941    scanner->opt[OPT_SET_EXPOSURE_I].title = SANE_TITLE_EXPOSURE_I;
942    scanner->opt[OPT_SET_EXPOSURE_I].desc = SANE_DESC_EXPOSURE_I;
943    for (i = OPT_SET_EXPOSURE_R; i <= OPT_SET_EXPOSURE_I; ++i) {
944    scanner->opt[i].type = SANE_TYPE_INT;
945    scanner->opt[i].unit = SANE_UNIT_MICROSECOND;
946    scanner->opt[i].cap |= SANE_CAP_SOFT_SELECT;
947    scanner->opt[i].constraint_type = SANE_CONSTRAINT_RANGE;
948    scanner->opt[i].constraint.range = &(scanner->device->exposure_range);
949    scanner->opt[i].size = sizeof(SANE_Word);
950    scanner->val[i].w = SANE_EXPOSURE_DEFAULT;
951    }
952
953    /* gain for R, G, B and I */
954    scanner->opt[OPT_SET_GAIN_R].name = SANE_NAME_GAIN_R;
955    scanner->opt[OPT_SET_GAIN_R].title = SANE_TITLE_GAIN_R;
956    scanner->opt[OPT_SET_GAIN_R].desc = SANE_DESC_GAIN_R;
957    scanner->opt[OPT_SET_GAIN_G].name = SANE_NAME_GAIN_G;
958    scanner->opt[OPT_SET_GAIN_G].title = SANE_TITLE_GAIN_G;
959    scanner->opt[OPT_SET_GAIN_G].desc = SANE_DESC_GAIN_G;
960    scanner->opt[OPT_SET_GAIN_B].name = SANE_NAME_GAIN_B;
961    scanner->opt[OPT_SET_GAIN_B].title = SANE_TITLE_GAIN_B;
962    scanner->opt[OPT_SET_GAIN_B].desc = SANE_DESC_GAIN_B;
963    scanner->opt[OPT_SET_GAIN_I].name = SANE_NAME_GAIN_I;
964    scanner->opt[OPT_SET_GAIN_I].title = SANE_TITLE_GAIN_I;
965    scanner->opt[OPT_SET_GAIN_I].desc = SANE_DESC_GAIN_I;
966    for (i = OPT_SET_GAIN_R; i <= OPT_SET_GAIN_I; ++i) {
967      scanner->opt[i].type = SANE_TYPE_INT;
968      scanner->opt[i].unit = SANE_UNIT_NONE;
969      scanner->opt[i].constraint_type = SANE_CONSTRAINT_RANGE;
970      scanner->opt[i].constraint.range = &gain_range;
971      scanner->opt[i].size = sizeof(SANE_Word);
972      scanner->val[i].w = SANE_GAIN_DEFAULT;
973    }
974    /* offsets for R, G, B and I */
975    scanner->opt[OPT_SET_OFFSET_R].name = SANE_NAME_OFFSET_R;
976    scanner->opt[OPT_SET_OFFSET_R].title = SANE_TITLE_OFFSET_R;
977    scanner->opt[OPT_SET_OFFSET_R].desc = SANE_DESC_OFFSET_R;
978    scanner->opt[OPT_SET_OFFSET_G].name = SANE_NAME_OFFSET_G;
979    scanner->opt[OPT_SET_OFFSET_G].title = SANE_TITLE_OFFSET_G;
980    scanner->opt[OPT_SET_OFFSET_G].desc = SANE_DESC_OFFSET_G;
981    scanner->opt[OPT_SET_OFFSET_B].name = SANE_NAME_OFFSET_B;
982    scanner->opt[OPT_SET_OFFSET_B].title = SANE_TITLE_OFFSET_B;
983    scanner->opt[OPT_SET_OFFSET_B].desc = SANE_DESC_OFFSET_B;
984    scanner->opt[OPT_SET_OFFSET_I].name = SANE_NAME_OFFSET_I;
985    scanner->opt[OPT_SET_OFFSET_I].title = SANE_TITLE_OFFSET_I;
986    scanner->opt[OPT_SET_OFFSET_I].desc = SANE_DESC_OFFSET_I;
987    for (i = OPT_SET_OFFSET_R; i <= OPT_SET_OFFSET_I; ++i) {
988      scanner->opt[i].type = SANE_TYPE_INT;
989      scanner->opt[i].unit = SANE_UNIT_NONE;
990      scanner->opt[i].constraint_type = SANE_CONSTRAINT_RANGE;
991      scanner->opt[i].constraint.range = &offset_range;
992      scanner->opt[i].size = sizeof(SANE_Word);
993      scanner->val[i].w = SANE_OFFSET_DEFAULT;
994    }
995    return SANE_STATUS_GOOD;
996}
997
998/**
999 * Parse line from config file into a vendor id, product id, model number, and flags
1000 *
1001 * @param config_line Text to parse
1002 * @param vendor_id
1003 * @param product_id
1004 * @param model_number
1005 * @param flags
1006 * @return SANE_STATUS_GOOD, or SANE_STATUS_INVAL in case of a parse error
1007 */
1008SANE_Status
1009sanei_pieusb_parse_config_line(const char* config_line,
1010                               SANE_Word* vendor_id,
1011                               SANE_Word* product_id,
1012                               SANE_Int* model_number,
1013                               SANE_Int* flags)
1014{
1015    char *vendor_id_string, *product_id_string, *model_number_string, *flags_string;
1016
1017    if (strncmp (config_line, "usb ", 4) != 0) {
1018        return SANE_STATUS_INVAL;
1019    }
1020    /* Detect vendor-id */
1021    config_line += 4;
1022    config_line = sanei_config_skip_whitespace (config_line);
1023    if (*config_line) {
1024        config_line = sanei_config_get_string (config_line, &vendor_id_string);
1025        if (vendor_id_string) {
1026            *vendor_id = strtol (vendor_id_string, 0, 0);
1027            free (vendor_id_string);
1028        } else {
1029            return SANE_STATUS_INVAL;
1030        }
1031        config_line = sanei_config_skip_whitespace (config_line);
1032    } else {
1033        return SANE_STATUS_INVAL;
1034    }
1035    /* Detect product-id */
1036    config_line = sanei_config_skip_whitespace (config_line);
1037    if (*config_line) {
1038        config_line = sanei_config_get_string (config_line, &product_id_string);
1039        if (product_id_string) {
1040            *product_id = strtol (product_id_string, 0, 0);
1041            free (product_id_string);
1042        } else {
1043            return SANE_STATUS_INVAL;
1044        }
1045        config_line = sanei_config_skip_whitespace (config_line);
1046    } else {
1047        return SANE_STATUS_INVAL;
1048    }
1049    /* Detect model number */
1050    config_line = sanei_config_skip_whitespace (config_line);
1051    if (*config_line) {
1052        config_line = sanei_config_get_string (config_line, &model_number_string);
1053        if (model_number_string) {
1054            *model_number = (SANE_Int) strtol (model_number_string, 0, 0);
1055            free (model_number_string);
1056        } else {
1057            return SANE_STATUS_INVAL;
1058        }
1059        config_line = sanei_config_skip_whitespace (config_line);
1060    } else {
1061        return SANE_STATUS_INVAL;
1062    }
1063    /* Detect (optional) flags */
1064    *flags = 0;
1065    config_line = sanei_config_skip_whitespace (config_line);
1066    if (*config_line) {
1067        config_line = sanei_config_get_string (config_line, &flags_string);
1068        if (flags_string) {
1069            *flags = (SANE_Int) strtol (flags_string, 0, 0);
1070            free (flags_string);
1071        }
1072    }
1073    return SANE_STATUS_GOOD;
1074}
1075
1076/**
1077 * Check if current list of supported devices contains the given specifications.
1078 *
1079 * @param vendor_id
1080 * @param product_id
1081 * @param model_number
1082 * @param flags
1083 * @return
1084 */
1085SANE_Bool
1086sanei_pieusb_supported_device_list_contains(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags)
1087{
1088    int i = 0;
1089    while (pieusb_supported_usb_device_list[i].vendor != 0) {
1090        if (pieusb_supported_usb_device_list[i].vendor == vendor_id
1091              && pieusb_supported_usb_device_list[i].product == product_id
1092              && pieusb_supported_usb_device_list[i].model == model_number
1093              && pieusb_supported_usb_device_list[i].flags == flags) {
1094            return SANE_TRUE;
1095        }
1096        i++;
1097    }
1098    return SANE_FALSE;
1099}
1100
1101/**
1102 * Add the given specifications to the current list of supported devices
1103 * @param vendor_id
1104 * @param product_id
1105 * @param model_number
1106 * @param flags
1107 * @return
1108 */
1109SANE_Status
1110sanei_pieusb_supported_device_list_add(SANE_Word vendor_id, SANE_Word product_id, SANE_Int model_number, SANE_Int flags)
1111{
1112    int i = 0, k;
1113    struct Pieusb_USB_Device_Entry* dl;
1114
1115    while (pieusb_supported_usb_device_list[i].vendor != 0) {
1116        i++;
1117    }
1118    /* i is index of last entry */
1119    for (k=0; k<=i; k++) {
1120        DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add(): current %03d: %04x %04x %02x %02x\n", i,
1121            pieusb_supported_usb_device_list[k].vendor,
1122            pieusb_supported_usb_device_list[k].product,
1123            pieusb_supported_usb_device_list[k].model,
1124            pieusb_supported_usb_device_list[k].flags);
1125    }
1126
1127    dl = realloc(pieusb_supported_usb_device_list,(i+2)*sizeof(struct Pieusb_USB_Device_Entry)); /* Add one entry to list */
1128    if (dl == NULL) {
1129        return SANE_STATUS_INVAL;
1130    }
1131    /* Copy values */
1132    pieusb_supported_usb_device_list = dl;
1133    pieusb_supported_usb_device_list[i].vendor = vendor_id;
1134    pieusb_supported_usb_device_list[i].product = product_id;
1135    pieusb_supported_usb_device_list[i].model = model_number;
1136    pieusb_supported_usb_device_list[i].flags = flags;
1137    pieusb_supported_usb_device_list[i+1].vendor = 0;
1138    pieusb_supported_usb_device_list[i+1].product = 0;
1139    pieusb_supported_usb_device_list[i+1].model = 0;
1140    pieusb_supported_usb_device_list[i+1].flags = 0;
1141    for (k=0; k<=i+1; k++) {
1142        DBG(DBG_info_proc,"sanei_pieusb_supported_device_list_add() add: %03d: %04x %04x %02x %02x\n", i,
1143            pieusb_supported_usb_device_list[k].vendor,
1144            pieusb_supported_usb_device_list[k].product,
1145            pieusb_supported_usb_device_list[k].model,
1146            pieusb_supported_usb_device_list[k].flags);
1147    }
1148    return SANE_STATUS_GOOD;
1149}
1150
1151/**
1152 * Actions to perform when a cancel request has been received.
1153 *
1154 * @param scanner scanner to stop scanning
1155 * @return SANE_STATUS_CANCELLED
1156 */
1157SANE_Status
1158sanei_pieusb_on_cancel (Pieusb_Scanner * scanner)
1159{
1160    struct Pieusb_Command_Status status;
1161
1162    DBG (DBG_info_proc, "sanei_pieusb_on_cancel()\n");
1163
1164    sanei_pieusb_cmd_stop_scan (scanner->device_number, &status);
1165    sanei_pieusb_cmd_set_scan_head (scanner->device_number, 1, 0, &status);
1166    sanei_pieusb_buffer_delete (&scanner->buffer);
1167    scanner->scanning = SANE_FALSE;
1168    return SANE_STATUS_CANCELLED;
1169}
1170
1171/**
1172 * Determine maximum length of a set of strings.
1173 *
1174 * @param strings Set of strings
1175 * @return maximum length
1176 */
1177static size_t
1178max_string_size (SANE_String_Const const strings[])
1179{
1180    size_t size, max_size = 0;
1181    int i;
1182
1183    for (i = 0; strings[i]; ++i) {
1184        size = strlen (strings[i]) + 1;
1185        if (size > max_size) {
1186            max_size = size;
1187        }
1188    }
1189
1190    return max_size;
1191}
1192
1193/* From MR's pie.c */
1194
1195/* ------------------------- PIEUSB_CORRECT_SHADING -------------------------- */
1196
1197/**
1198 * Correct the given buffer for shading using shading data in scanner.
1199 * If the loop order is width->color->height, a 7200 dpi scan correction takes
1200 * 45 minutes. If the loop order is color->height->width, this is less than 3
1201 * minutes. So it is worthwhile to find the used pixels first (array width_to_loc).
1202 *
1203 * @param scanner Scanner
1204 * @param buffer Buffer to correct
1205 */
1206void
1207sanei_pieusb_correct_shading(struct Pieusb_Scanner *scanner, struct Pieusb_Read_Buffer *buffer)
1208{
1209
1210    int i, j, c, k;
1211    SANE_Uint val, val_org, *p;
1212    int *width_to_loc;
1213
1214    DBG (DBG_info_proc, "sanei_pieusb_correct_shading()\n");
1215
1216    /* Loop through CCD-mask to find used pixels */
1217    width_to_loc = calloc(buffer->width,sizeof(int));
1218    j = 0;
1219    for (i = 0; i < scanner->ccd_mask_size; i++) {
1220        if (scanner->ccd_mask[i] == 0) {
1221            width_to_loc[j++] = i;
1222        }
1223    }
1224    /* Correct complete image */
1225    for (c = 0; c < buffer->colors; c++) {
1226        DBG(DBG_info,"sanei_pieusb_correct_shading() correct color %d\n",c);
1227        for (k = 0; k < buffer->height; k++) {
1228            /* DBG(DBG_info,"Correct line %d\n",k); */
1229            p = buffer->data + c * buffer->width * buffer->height + k * buffer->width;
1230            for (j = 0; j < buffer->width; j++) {
1231                val_org = *p;
1232                val = lround((double)scanner->shading_mean[c] / scanner->shading_ref[c][width_to_loc[j]] * val_org);
1233                /* DBG(DBG_info,"Correct [%d,%d,%d] %d -> %d\n",k,j,c,val_org,val); */
1234                *p++ = val;
1235            }
1236        }
1237    }
1238    /* Free memory */
1239    free(width_to_loc);
1240}
1241
1242/* === functions copied from MR's code === */
1243
1244/**
1245 *
1246 * @param scanner
1247 * @param in_img
1248 * @param planes
1249 * @param out_planes
1250 * @return
1251 */
1252SANE_Status
1253sanei_pieusb_post (Pieusb_Scanner *scanner, uint16_t **in_img, int planes)
1254{
1255  uint16_t *cplane[PLANES];    /* R, G, B, I gray scale planes */
1256  SANE_Parameters parameters;   /* describes the image */
1257  int winsize_smooth;           /* for adapting replaced pixels */
1258  char filename[64];
1259  SANE_Status status;
1260  int smooth, i;
1261
1262  memcpy (&parameters, &scanner->scan_parameters, sizeof (SANE_Parameters));
1263  parameters.format = SANE_FRAME_GRAY;
1264  parameters.bytes_per_line = parameters.pixels_per_line;
1265  if (parameters.depth > 8)
1266    parameters.bytes_per_line *= 2;
1267  parameters.last_frame = 0;
1268
1269  DBG (DBG_info, "pie_usb_post: %d ppl, %d lines, %d bits, %d planes, %d dpi\n",
1270       parameters.pixels_per_line, parameters.lines,
1271       parameters.depth, planes, scanner->mode.resolution);
1272
1273  if (planes > PLANES) {
1274    DBG (DBG_error, "pie_usb_post: too many planes: %d (max %d)\n", planes, PLANES);
1275    return SANE_STATUS_INVAL;
1276  }
1277
1278  for (i = 0; i < planes; i++)
1279    cplane[i] = in_img[i];
1280
1281  /* dirt is rather resolution invariant, so
1282   * setup resolution dependent parameters
1283   */
1284  /* film grain reduction */
1285  smooth = scanner->val[OPT_SMOOTH_IMAGE].w;
1286  winsize_smooth = (scanner->mode.resolution / 540) | 1;
1287  /* smoothen whole image or only replaced pixels */
1288  if (smooth)
1289    {
1290      winsize_smooth += 2 * (smooth - 3);       /* even */
1291      if (winsize_smooth < 3)
1292        smooth = 0;
1293    }
1294  if (winsize_smooth < 3)
1295    winsize_smooth = 3;
1296  DBG (DBG_info, "pie_usb_sw_post: winsize_smooth %d\n", winsize_smooth);
1297
1298  /* RGBI post-processing if selected:
1299   * 1) remove spectral overlay from ired plane,
1300   * 2) remove dirt, smoothen if, crop if */
1301  if (scanner->val[OPT_CORRECT_INFRARED].b) /* (scanner->processing & POST_SW_IRED_MASK) */
1302    {
1303      /* remove spectral overlay from ired plane */
1304      status = sanei_ir_spectral_clean (&parameters, scanner->ln_lut, cplane[0], cplane[3]);
1305      if (status != SANE_STATUS_GOOD)
1306        return status;
1307      if (DBG_LEVEL >= 15)
1308        {
1309          snprintf (filename, 63, "/tmp/ir-spectral.pnm");
1310          pieusb_write_pnm_file (filename, cplane[3],
1311                                  parameters.depth, 1,
1312                                  parameters.pixels_per_line, parameters.lines);
1313        }
1314      if (scanner->cancel_request)          /* asynchronous cancel ? */
1315        return SANE_STATUS_CANCELLED;
1316  } /* scanner-> processing & POST_SW_IRED_MASK */
1317
1318  /* remove dirt, smoothen if, crop if */
1319  if (scanner->val[OPT_CLEAN_IMAGE].b) /* (scanner->processing & POST_SW_DIRT) */
1320    {
1321      double *norm_histo;
1322      uint16_t *thresh_data;
1323      int static_thresh, too_thresh;    /* static thresholds */
1324      int winsize_filter;               /* primary size of filtering window */
1325      int size_dilate;                  /* the dirt mask */
1326
1327      /* size of filter detecting dirt */
1328      winsize_filter = (int) (5.0 * (double) scanner->mode.resolution / 300.0) | 1;
1329      if (winsize_filter < 3)
1330        winsize_filter = 3;
1331      /* dirt usually has smooth edges which also need correction */
1332      size_dilate = scanner->mode.resolution / 1000 + 1;
1333
1334      /* first detect large dirt by a static threshold */
1335      status = sanei_ir_create_norm_histogram (&parameters, cplane[3], &norm_histo);
1336      if (status != SANE_STATUS_GOOD)
1337        {
1338          DBG (DBG_error, "pie_usb_sw_post: no buffer\n");
1339          return SANE_STATUS_NO_MEM;
1340        }
1341      /* generate a "bimodal" static threshold */
1342      status = sanei_ir_threshold_yen (&parameters, norm_histo, &static_thresh);
1343      if (status != SANE_STATUS_GOOD)
1344        return status;
1345      /* generate traditional static threshold */
1346      status = sanei_ir_threshold_otsu (&parameters, norm_histo, &too_thresh);
1347      if (status != SANE_STATUS_GOOD)
1348        return status;
1349      /* choose lower one */
1350      if (too_thresh < static_thresh)
1351        static_thresh = too_thresh;
1352      free (norm_histo);
1353
1354      /* then generate dirt mask with adaptive thresholding filter
1355       * and add the dirt from the static threshold */
1356      /* last two parameters: 10, 50 detects more, 20, 75 less */
1357      status = sanei_ir_filter_madmean (&parameters, cplane[3], &thresh_data, winsize_filter, 20, 100);
1358      if (status != SANE_STATUS_GOOD) {
1359        free (thresh_data);
1360        return status;
1361      }
1362      sanei_ir_add_threshold (&parameters, cplane[3], thresh_data, static_thresh);
1363      if (DBG_LEVEL >= 15)
1364        {
1365          snprintf (filename, 63, "/tmp/ir-threshold.pnm");
1366          pieusb_write_pnm_file (filename, thresh_data,
1367                                  8, 1, parameters.pixels_per_line,
1368                                  parameters.lines);
1369        }
1370      if (scanner->cancel_request) {         /* asynchronous cancel ? */
1371        free (thresh_data);
1372        return SANE_STATUS_CANCELLED;
1373      }
1374      /* replace the dirt and smoothen film grain and crop if possible */
1375      status = sanei_ir_dilate_mean (&parameters, cplane, thresh_data,
1376              500, size_dilate, winsize_smooth, smooth,
1377              0, NULL);
1378      if (status != SANE_STATUS_GOOD) {
1379        free (thresh_data);
1380        return status;
1381      }
1382      smooth = 0;
1383      free (thresh_data);
1384    }
1385
1386  if (DBG_LEVEL >= 15)
1387    {
1388      pieusb_write_pnm_file ("/tmp/RGBi-img.pnm", scanner->buffer.data,
1389        scanner->scan_parameters.depth, 3, scanner->scan_parameters.pixels_per_line,
1390        scanner->scan_parameters.lines);
1391    }
1392
1393  return status;
1394}
1395
1396/* ------------------------------ PIE_USB_WRITE_PNM_FILE ------------------------------- */
1397static SANE_Status
1398pieusb_write_pnm_file (char *filename, SANE_Uint *data, int depth,
1399                        int channels, int pixels_per_line, int lines)
1400{
1401  FILE *out;
1402  int r, c, ch;
1403  SANE_Uint val;
1404  uint8_t b = 0;
1405
1406  DBG (DBG_info_proc,
1407       "pie_usb_write_pnm_file: depth=%d, channels=%d, ppl=%d, lines=%d\n",
1408       depth, channels, pixels_per_line, lines);
1409
1410  out = fopen (filename, "w");
1411  if (!out)
1412    {
1413      DBG (DBG_error,
1414           "pie_usb_write_pnm_file: could not open %s for writing: %s\n",
1415           filename, strerror (errno));
1416      return SANE_STATUS_INVAL;
1417    }
1418
1419  switch (depth) {
1420      case 1:
1421          fprintf (out, "P4\n%d\n%d\n", pixels_per_line, lines);
1422          for (r = 0; r < lines; r++) {
1423              int i;
1424              i = 0;
1425              b = 0;
1426              for (c = 0; c < pixels_per_line; c++) {
1427                  val = *(data + r * pixels_per_line + c);
1428                  if (val > 0) b |= (0x80 >> i);
1429                  i++;
1430                  if (i == 7) {
1431                      fputc(b, out);
1432                      i = 0;
1433                      b = 0;
1434                  }
1435              }
1436              if (i != 0) {
1437                  fputc(b, out);
1438              }
1439          }
1440          break;
1441      case 8:
1442          fprintf (out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6', pixels_per_line, lines, 255);
1443          for (r = 0; r < lines; r++) {
1444              for (c = 0; c < pixels_per_line; c++) {
1445                  for (ch = 0; ch < channels; ch++) {
1446                      val = *(data + ch * lines * pixels_per_line + r * pixels_per_line + c);
1447                      b = val & 0xFF;
1448                      fputc(b, out);
1449                  }
1450              }
1451          }
1452          break;
1453      case 16:
1454          fprintf (out, "P%c\n%d\n%d\n%d\n", channels == 1 ? '5' : '6', pixels_per_line, lines, 65535);
1455          for (r = 0; r < lines; r++) {
1456              for (c = 0; c < pixels_per_line; c++) {
1457                  for (ch = 0; ch < channels; ch++) {
1458                      val = *(data + ch * lines * pixels_per_line + r * pixels_per_line + c);
1459                      b = (val >> 8) & 0xFF;
1460                      fputc(b, out);
1461                      b = val & 0xFF;
1462                      fputc(b, out);
1463                  }
1464              }
1465          }
1466          break;
1467      default:
1468          DBG (DBG_error, "pie_usb_write_pnm_file: depth %d not implemented\n", depth);
1469  }
1470  fclose (out);
1471
1472  DBG (DBG_info, "pie_usb_write_pnm_file: finished\n");
1473  return SANE_STATUS_GOOD;
1474}
1475
1476/**
1477 * Check option inconsistencies.
1478 * In most cases an inconsistency can be solved by ignoring an option setting.
1479 * Message these situations and return 1 to indicate we can work with the
1480 * current set op options. If the settings are really inconsistent, return 0.
1481 */
1482int
1483sanei_pieusb_analyse_options(struct Pieusb_Scanner *scanner)
1484{
1485    /* Checks*/
1486    if (scanner->val[OPT_TL_X].w > scanner->val[OPT_BR_X].w) {
1487        DBG (DBG_error, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) -- aborting\n",
1488	   scanner->opt[OPT_TL_X].title,
1489	   SANE_UNFIX (scanner->val[OPT_TL_X].w),
1490	   scanner->opt[OPT_BR_X].title,
1491	   SANE_UNFIX (scanner->val[OPT_BR_X].w));
1492        return 0;
1493    }
1494    if (scanner->val[OPT_TL_Y].w > scanner->val[OPT_BR_Y].w) {
1495        DBG (DBG_error, "sane_start: %s (%.1f mm) is bigger than %s (%.1f mm) -- aborting\n",
1496	   scanner->opt[OPT_TL_Y].title,
1497	   SANE_UNFIX (scanner->val[OPT_TL_Y].w),
1498	   scanner->opt[OPT_BR_Y].title,
1499	   SANE_UNFIX (scanner->val[OPT_BR_Y].w));
1500        return 0;
1501    }
1502    /* Modes sometimes limit other choices */
1503    if (scanner->val[OPT_PREVIEW].b) {
1504        /* Preview uses its own specific settings */
1505        if (scanner->val[OPT_RESOLUTION].w != (scanner->device->fast_preview_resolution << SANE_FIXED_SCALE_SHIFT)) {
1506            DBG (DBG_info_sane, "Option %s = %f ignored during preview\n", scanner->opt[OPT_RESOLUTION].name, SANE_UNFIX(scanner->val[OPT_RESOLUTION].w));
1507        }
1508        if (scanner->val[OPT_SHARPEN].b) {
1509            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_SHARPEN].name, scanner->val[OPT_SHARPEN].b);
1510        }
1511        if (!scanner->val[OPT_FAST_INFRARED].b) {
1512            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b);
1513        }
1514        if (scanner->val[OPT_CORRECT_INFRARED].b) {
1515            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b);
1516        }
1517        if (scanner->val[OPT_CLEAN_IMAGE].b) {
1518            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b);
1519        }
1520        if (scanner->val[OPT_SMOOTH_IMAGE].w != 0) {
1521            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_SMOOTH_IMAGE].name, scanner->val[OPT_SMOOTH_IMAGE].w);
1522        }
1523        if (strcmp(scanner->val[OPT_CROP_IMAGE].s, scanner->device->crop_sw_list[0]) != 0) {
1524            DBG (DBG_info_sane, "Option %s = %s ignored during preview\n", scanner->opt[OPT_CROP_IMAGE].name, scanner->val[OPT_CROP_IMAGE].s);
1525        }
1526        if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) {
1527            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w);
1528        }
1529        if (scanner->val[OPT_INVERT_IMAGE].w) {
1530            DBG (DBG_info_sane, "Option %s = %d ignored during preview\n", scanner->opt[OPT_INVERT_IMAGE].name, scanner->val[OPT_INVERT_IMAGE].w);
1531        }
1532    } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_LINEART)==0) {
1533        /* Can we do any post processing in lineart? Needs testing to see what's possible */
1534        if (scanner->val[OPT_BIT_DEPTH].w != 1) {
1535            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (will use 1)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w);
1536        }
1537        if (!scanner->val[OPT_FAST_INFRARED].b) {
1538            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b);
1539        }
1540        if (!scanner->val[OPT_CORRECT_SHADING].b) {
1541            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CORRECT_SHADING].name, scanner->val[OPT_CORRECT_SHADING].b);
1542        }
1543        if (!scanner->val[OPT_CORRECT_INFRARED].b) {
1544            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b);
1545        }
1546        if (scanner->val[OPT_CLEAN_IMAGE].b) {
1547            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b);
1548        }
1549        if (scanner->val[OPT_SMOOTH_IMAGE].w != 0) {
1550            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_SMOOTH_IMAGE].name, scanner->val[OPT_SMOOTH_IMAGE].w);
1551        }
1552        if (strcmp(scanner->val[OPT_CROP_IMAGE].s, scanner->device->crop_sw_list[0]) != 0) {
1553            DBG (DBG_info_sane, "Option %s = %s ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_CROP_IMAGE].name, scanner->val[OPT_CROP_IMAGE].s);
1554        }
1555        if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) {
1556            DBG (DBG_info_sane, "Option %s = %d ignored in lineart mode (irrelevant)\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w);
1557        }
1558    } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_HALFTONE)==0) {
1559        /* Can we do any post processing in halftone? Needs testing to see what's possible */
1560        if (scanner->val[OPT_BIT_DEPTH].w != 1) {
1561            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (will use 1)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w);
1562        }
1563        if (!scanner->val[OPT_FAST_INFRARED].b) {
1564            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b);
1565        }
1566        if (!scanner->val[OPT_CORRECT_SHADING].b) {
1567            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CORRECT_SHADING].name, scanner->val[OPT_CORRECT_SHADING].b);
1568        }
1569        if (!scanner->val[OPT_CORRECT_INFRARED].b) {
1570            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b);
1571        }
1572        if (scanner->val[OPT_CLEAN_IMAGE].b) {
1573            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b);
1574        }
1575        if (scanner->val[OPT_SMOOTH_IMAGE].w != 0) {
1576            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_SMOOTH_IMAGE].name, scanner->val[OPT_SMOOTH_IMAGE].w);
1577        }
1578        if (strcmp(scanner->val[OPT_CROP_IMAGE].s, scanner->device->crop_sw_list[0]) != 0) {
1579            DBG (DBG_info_sane, "Option %s = %s ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_CROP_IMAGE].name, scanner->val[OPT_CROP_IMAGE].s);
1580        }
1581        if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) {
1582            DBG (DBG_info_sane, "Option %s = %d ignored in halftone mode (irrelevant)\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w);
1583        }
1584    } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_GRAY)==0) {
1585        /* Can we do any post processing in gray mode? */
1586        /* Can we obtain a single color channel in this mode? How? */
1587        /* Is this just RGB with luminance trasformation? */
1588        /* Needs testing to see what's possible */
1589        /* Only do 8 or 16 bit scans */
1590        if (scanner->val[OPT_BIT_DEPTH].w == 1) {
1591            DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (will use 8)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w);
1592        }
1593        if (!scanner->val[OPT_FAST_INFRARED].b) {
1594            DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_FAST_INFRARED].name, scanner->val[OPT_FAST_INFRARED].b);
1595        }
1596        if (!scanner->val[OPT_CORRECT_INFRARED].b) {
1597            DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_CORRECT_INFRARED].name, scanner->val[OPT_CORRECT_INFRARED].b);
1598        }
1599        if (scanner->val[OPT_CLEAN_IMAGE].b) {
1600            DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_CLEAN_IMAGE].name, scanner->val[OPT_CLEAN_IMAGE].b);
1601        }
1602        if (scanner->val[OPT_TRANSFORM_TO_SRGB].b) {
1603            DBG (DBG_info_sane, "Option %s = %d ignored in gray mode (irrelevant)\n", scanner->opt[OPT_TRANSFORM_TO_SRGB].name, scanner->val[OPT_TRANSFORM_TO_SRGB].w);
1604        }
1605    } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_COLOR)==0) {
1606        /* Some options require infrared data to be obtained, so all infrared options are relevant */
1607        /* Only do 8 or 16 bit scans */
1608        if (scanner->val[OPT_BIT_DEPTH].w == 1) {
1609            DBG (DBG_info_sane, "Option %s = %d ignored in color mode (will use 8)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w);
1610        }
1611    } else if (strcmp(scanner->val[OPT_MODE].s,SANE_VALUE_SCAN_MODE_RGBI)==0) {
1612        /* Only do 8 or 16 bit scans */
1613        if (scanner->val[OPT_BIT_DEPTH].w == 1) {
1614            DBG (DBG_info_sane, "Option %s = %d ignored in color mode (will use 8)\n", scanner->opt[OPT_BIT_DEPTH].name, scanner->val[OPT_BIT_DEPTH].w);
1615        }
1616    }
1617
1618    return 1;
1619}
1620
1621/**
1622 * Print options
1623 *
1624 * @param scanner
1625 */
1626void
1627sanei_pieusb_print_options(struct Pieusb_Scanner *scanner)
1628{
1629    int k;
1630    /* List current options and values */
1631    DBG (DBG_info, "Num options = %d\n", scanner->val[OPT_NUM_OPTS].w);
1632    for (k = 1; k < scanner->val[OPT_NUM_OPTS].w; k++) {
1633        switch (scanner->opt[k].type) {
1634            case SANE_TYPE_BOOL:
1635                DBG(DBG_info,"  Option %d: %s = %d\n", k, scanner->opt[k].name, scanner->val[k].b);
1636                break;
1637            case SANE_TYPE_INT:
1638	        DBG(DBG_info,"  Option %d: %s = %d\n", k, scanner->opt[k].name, scanner->val[k].w);
1639                break;
1640            case SANE_TYPE_FIXED:
1641                DBG(DBG_info,"  Option %d: %s = %f\n", k, scanner->opt[k].name, SANE_UNFIX (scanner->val[k].w));
1642                break;
1643            case SANE_TYPE_STRING:
1644                DBG(DBG_info,"  Option %d: %s = %s\n", k, scanner->opt[k].name, scanner->val[k].s);
1645                break;
1646            case SANE_TYPE_GROUP:
1647                DBG(DBG_info,"  Option %d: %s = %s\n", k, scanner->opt[k].title, scanner->val[k].s);
1648	        break;
1649            default:
1650                DBG(DBG_info,"  Option %d: %s unknown type %d\n", k, scanner->opt[k].name, scanner->opt[k].type);
1651                break;
1652        }
1653    }
1654}
1655
1656/**
1657 * Calculate reference values for each pixel, line means and line maxima.
1658 * We have got 45 lines for all four colors and for each CCD pixel.
1659 * The reference value for each pixel is the 45-line average for that
1660 * pixel, for each color separately.
1661 *
1662 * @param scanner
1663 * @param buffer
1664 */
1665static void pieusb_calculate_shading(struct Pieusb_Scanner *scanner, SANE_Byte* buffer)
1666{
1667    int k, m;
1668    SANE_Byte* p;
1669    SANE_Int ci, val;
1670    SANE_Int shading_width = scanner->device->shading_parameters[0].pixelsPerLine;
1671    SANE_Int shading_height = scanner->device->shading_parameters[0].nLines;
1672
1673    /* Initialize all to 0 */
1674    for (k = 0; k < SHADING_PARAMETERS_INFO_COUNT; k++) {
1675        scanner->shading_max[k] = 0;
1676        scanner->shading_mean[k] = 0;
1677        memset(scanner->shading_ref[k], 0, shading_width * sizeof (SANE_Int));
1678    }
1679    /* Process data from buffer */
1680    p = buffer;
1681    switch (scanner->mode.colorFormat) {
1682        case 0x01: /* Pixel */
1683            /* Process pixel by pixel */
1684            for (k = 0; k < shading_height; k++) {
1685                for (m = 0; m < shading_width; m++) {
1686                    for (ci = 0; ci < SHADING_PARAMETERS_INFO_COUNT; ci++) {
1687                        val = *(p) + *(p+1) * 256;
1688                        scanner->shading_ref[ci][m] += val;
1689                        scanner->shading_max[ci] = scanner->shading_max[ci] < val ? val : scanner->shading_max[ci];
1690                        p += 2;
1691                    }
1692                }
1693            }
1694            break;
1695        case 0x04: /* Indexed */
1696            /* Process each line in the sequence found in the buffer */
1697            for (k = 0; k < shading_height*4; k++) {
1698                /* Save at right color */
1699                switch (*p) {
1700                    case 'R': ci = 0; break;
1701                    case 'G': ci = 1; break;
1702                    case 'B': ci = 2; break;
1703                    case 'I': ci = 3; break;
1704                    default: ci = -1; break; /* ignore line */
1705                }
1706                /* Add scanned data to reference line and keep track of maximum */
1707                if (ci != -1) {
1708                    for (m = 0; m < shading_width; m++) {
1709                        val = *(p+2+2*m) + *(p+2+2*m+1) * 256;
1710                        scanner->shading_ref[ci][m] += val;
1711                        scanner->shading_max[ci] = scanner->shading_max[ci] < val ? val : scanner->shading_max[ci];
1712                        /* DBG(DBG_error,"%02d Shading_ref[%d][%d] = %d\n",k,ci,m,scanner->shading_ref[ci][m]); */
1713                    }
1714                }
1715                /* Next line */
1716                p += 2*shading_width+2;
1717            }
1718            break;
1719        default:
1720            DBG (DBG_error,"sane_start(): color format %d not implemented\n",scanner->mode.colorFormat);
1721            return;
1722    }
1723    /* Mean reference value needs division */
1724    for (k = 0; k < SHADING_PARAMETERS_INFO_COUNT; k++) {
1725        for (m = 0; m < shading_width; m++) {
1726            scanner->shading_ref[k][m] = lround((double)scanner->shading_ref[k][m]/shading_height);
1727            /* DBG(DBG_error,"Shading_ref[%d][%d] = %d\n",k,m,scanner->shading_ref[k][m]); */
1728        }
1729    }
1730    /* Overall means */
1731    for (k = 0; k < SHADING_PARAMETERS_INFO_COUNT; k++) {
1732        for (m=0; m<shading_width; m++) {
1733            scanner->shading_mean[k] += scanner->shading_ref[k][m];
1734        }
1735        scanner->shading_mean[k] = lround((double)scanner->shading_mean[k]/shading_width);
1736        DBG (DBG_error,"Shading_mean[%d] = %d\n",k,scanner->shading_mean[k]);
1737    }
1738
1739    /* Set shading data present */
1740    scanner->shading_data_present = SANE_TRUE;
1741
1742    /* Export shading data as TIFF */
1743#ifdef CAN_DO_4_CHANNEL_TIFF
1744    if (scanner->val[OPT_SAVE_SHADINGDATA].b) {
1745        struct Pieusb_Read_Buffer shading;
1746        SANE_Byte* lboff = buffer;
1747        SANE_Int bpl = shading_width*2;
1748        SANE_Int n;
1749        buffer_create(&shading, shading_width, shading_height, 0x0F, 16);
1750        for (n=0; n<4*shading_height; n++) {
1751            if (buffer_put_single_color_line(&shading, *lboff, lboff+2, bpl) == 0) {
1752                break;
1753            }
1754            lboff += (bpl + 2);
1755        }
1756        FILE* fs = fopen("pieusb.shading", "w");
1757        /* write_tiff_rgbi_header (fs, shading_width, shading_height, 16, 3600, NULL); */
1758        fwrite(shading.data, 1, shading.image_size_bytes, fs);
1759        fclose(fs);
1760        buffer_delete(&shading);
1761    }
1762#endif
1763
1764}
1765
1766/*
1767 * Set frame (from scanner options)
1768 */
1769
1770SANE_Status
1771sanei_pieusb_set_frame_from_options(Pieusb_Scanner * scanner)
1772{
1773    double dpmm;
1774    struct Pieusb_Command_Status status;
1775
1776    dpmm = (double) scanner->device->maximum_resolution / MM_PER_INCH;
1777    scanner->frame.x0 = SANE_UNFIX(scanner->val[OPT_TL_X].w) * dpmm;
1778    scanner->frame.y0 = SANE_UNFIX(scanner->val[OPT_TL_Y].w) * dpmm;
1779    scanner->frame.x1 = SANE_UNFIX(scanner->val[OPT_BR_X].w) * dpmm;
1780    scanner->frame.y1 = SANE_UNFIX(scanner->val[OPT_BR_Y].w) * dpmm;
1781    scanner->frame.index = 0x80; /* 0x80: value from cyberview */
1782    sanei_pieusb_cmd_set_scan_frame (scanner->device_number, scanner->frame.index, &(scanner->frame), &status);
1783    DBG (DBG_info_sane, "sanei_pieusb_set_frame_from_options(): sanei_pieusb_cmd_set_scan_frame status %s\n", sane_strstatus (sanei_pieusb_convert_status (status.pieusb_status)));
1784    return sanei_pieusb_convert_status (status.pieusb_status);
1785}
1786
1787/*
1788 * Set mode (from scanner options)
1789 */
1790
1791SANE_Status
1792sanei_pieusb_set_mode_from_options(Pieusb_Scanner * scanner)
1793{
1794    struct Pieusb_Command_Status status;
1795    const char *mode;
1796    SANE_Status res;
1797
1798    mode = scanner->val[OPT_MODE].s;
1799    if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) {
1800        scanner->mode.passes = SCAN_FILTER_GREEN; /* G */
1801        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_PIXEL;
1802    } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) {
1803        scanner->mode.passes = SCAN_FILTER_GREEN; /* G */
1804        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_PIXEL;
1805    } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) {
1806        scanner->mode.passes = SCAN_FILTER_GREEN; /* G=gray; unable to get R & B & I to work */
1807        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_PIXEL;
1808    } else if(scanner->val[OPT_PREVIEW].b) {
1809        /* Catch preview here, otherwise next ifs get complicated */
1810        scanner->mode.passes = SCAN_ONE_PASS_COLOR;
1811        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX; /* pixel format might be an alternative */
1812    } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) {
1813        scanner->mode.passes = SCAN_ONE_PASS_RGBI;
1814        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX;
1815    } else if(strcmp (mode, SANE_VALUE_SCAN_MODE_COLOR) == 0 && scanner->val[OPT_CLEAN_IMAGE].b) {
1816        scanner->mode.passes = SCAN_ONE_PASS_RGBI; /* Need infrared for cleaning */
1817        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX;
1818    } else { /* SANE_VALUE_SCAN_MODE_COLOR */
1819        scanner->mode.passes = SCAN_ONE_PASS_COLOR;
1820        scanner->mode.colorFormat = SCAN_COLOR_FORMAT_INDEX; /* pixel format might be an alternative */
1821    }
1822    /* Resolution */
1823    if (scanner->val[OPT_PREVIEW].b) {
1824        scanner->mode.resolution = scanner->device->fast_preview_resolution;
1825        DBG (DBG_info_sane, "sanei_pieusb_set_mode_from_options(): resolution fast preview (%d)\n", scanner->mode.resolution);
1826    } else {
1827        scanner->mode.resolution = SANE_UNFIX (scanner->val[OPT_RESOLUTION].w);
1828        DBG (DBG_info_sane, "sanei_pieusb_set_mode_from_options(): resolution from option setting (%d)\n", scanner->mode.resolution);
1829    }
1830    /* Bit depth: exit on untested values */
1831    switch (scanner->val[OPT_BIT_DEPTH].w) {
1832        case 1: scanner->mode.colorDepth = SCAN_COLOR_DEPTH_1; break;
1833        case 8: scanner->mode.colorDepth = SCAN_COLOR_DEPTH_8; break;
1834        case 16: scanner->mode.colorDepth = SCAN_COLOR_DEPTH_16; break;
1835        default: /* 4, 10 & 12 */
1836            DBG (DBG_error, "sanei_pieusb_set_mode_from_options(): sanei_pieusb_cmd_set_scan_frame untested bit depth %d\n", scanner->val[OPT_BIT_DEPTH].w);
1837            return SANE_STATUS_INVAL;
1838    }
1839    scanner->mode.byteOrder = 0x01; /* 0x01 = Intel; only bit 0 used */
1840    scanner->mode.sharpen = scanner->val[OPT_SHARPEN].b && !scanner->val[OPT_PREVIEW].b;
1841    scanner->mode.skipShadingAnalysis = !scanner->val[OPT_SHADING_ANALYSIS].b;
1842    scanner->mode.fastInfrared = scanner->val[OPT_FAST_INFRARED].b && !scanner->val[OPT_PREVIEW].b;
1843    if (strcmp (scanner->val[OPT_HALFTONE_PATTERN].s, "53lpi 45d ROUND") == 0) {
1844        scanner->mode.halftonePattern = 0;
1845    } else { /*TODO: the others */
1846        scanner->mode.halftonePattern = 0;
1847    }
1848    scanner->mode.lineThreshold = SANE_UNFIX (scanner->val[OPT_THRESHOLD].w) / 100 * 0xFF; /* 0xFF = 100% */
1849    sanei_pieusb_cmd_set_mode (scanner->device_number, &(scanner->mode), &status);
1850    res = sanei_pieusb_convert_status(status.pieusb_status);
1851    if (res == SANE_STATUS_GOOD) {
1852      res = sanei_pieusb_wait_ready (scanner, 0);
1853    }
1854    DBG (DBG_info_sane, "sanei_pieusb_set_mode_from_options(): sanei_pieusb_cmd_set_mode status %s\n", sane_strstatus(res));
1855    return res;
1856}
1857
1858/**
1859 * Set gains, exposure and offset, to:
1860 * - values default (pieusb_set_default_gain_offset)
1861 * - values set by options
1862 * - values set by auto-calibration procedure
1863 * - values determined from preceding preview
1864 *
1865 * @param scanner
1866 * @return
1867 */
1868SANE_Status
1869sanei_pieusb_set_gain_offset(Pieusb_Scanner * scanner, const char *calibration_mode)
1870{
1871    struct Pieusb_Command_Status status;
1872    SANE_Status ret;
1873    double gain;
1874
1875    DBG (DBG_info,"sanei_pieusb_set_gain_offset(): mode = %s\n", calibration_mode);
1876
1877    if (strcmp (calibration_mode, SCAN_CALIBRATION_DEFAULT) == 0) {
1878        /* Default values */
1879        DBG(DBG_info_sane,"sanei_pieusb_set_gain_offset(): get calibration data from defaults\n");
1880        scanner->settings.exposureTime[0] = DEFAULT_EXPOSURE;
1881        scanner->settings.exposureTime[1] = DEFAULT_EXPOSURE;
1882        scanner->settings.exposureTime[2] = DEFAULT_EXPOSURE;
1883        scanner->settings.exposureTime[3] = DEFAULT_EXPOSURE;
1884        scanner->settings.offset[0] = DEFAULT_OFFSET;
1885        scanner->settings.offset[1] = DEFAULT_OFFSET;
1886        scanner->settings.offset[2] = DEFAULT_OFFSET;
1887        scanner->settings.offset[3] = DEFAULT_OFFSET;
1888        scanner->settings.gain[0] = DEFAULT_GAIN;
1889        scanner->settings.gain[1] = DEFAULT_GAIN;
1890        scanner->settings.gain[2] = DEFAULT_GAIN;
1891        scanner->settings.gain[3] = DEFAULT_GAIN;
1892        scanner->settings.light = DEFAULT_LIGHT;
1893        scanner->settings.extraEntries = DEFAULT_ADDITIONAL_ENTRIES;
1894        scanner->settings.doubleTimes = DEFAULT_DOUBLE_TIMES;
1895        status.pieusb_status = PIEUSB_STATUS_GOOD;
1896    } else if ((strcmp(calibration_mode, SCAN_CALIBRATION_PREVIEW) == 0)
1897	       && scanner->preview_done) {
1898        /* If no preview data available, do the auto-calibration. */
1899        double dg, dgi;
1900        DBG (DBG_info, "sanei_pieusb_set_gain_offset(): get calibration data from preview. scanner->mode.passes %d\n", scanner->mode.passes);
1901        switch (scanner->mode.passes) {
1902            case SCAN_ONE_PASS_RGBI:
1903                dg = 3.00;
1904                dgi = ((double)scanner->settings.saturationLevel[0] / 65536) / ((double)scanner->preview_upper_bound[0] / HISTOGRAM_SIZE);
1905                if (dgi < dg) dg = dgi;
1906                dgi = ((double)scanner->settings.saturationLevel[1] / 65536) / ((double)scanner->preview_upper_bound[1] / HISTOGRAM_SIZE);
1907                if (dgi < dg) dg = dgi;
1908                dgi = ((double)scanner->settings.saturationLevel[2] / 65536) / ((double)scanner->preview_upper_bound[2] / HISTOGRAM_SIZE);
1909                if (dgi < dg) dg = dgi;
1910                updateGain2(scanner, 0, dg);
1911                updateGain2(scanner, 1, dg);
1912                updateGain2(scanner, 2, dg);
1913	    break;
1914            case SCAN_ONE_PASS_COLOR:
1915                dg = 3.00;
1916                dgi = ((double)scanner->settings.saturationLevel[0] / 65536) / ((double)scanner->preview_upper_bound[0] / HISTOGRAM_SIZE);
1917                if (dgi < dg) dg = dgi;
1918                dgi = ((double)scanner->settings.saturationLevel[1] / 65536) / ((double)scanner->preview_upper_bound[1] / HISTOGRAM_SIZE);
1919                if (dgi < dg) dg = dgi;
1920                dgi = ((double)scanner->settings.saturationLevel[2] / 65536) / ((double)scanner->preview_upper_bound[2] / HISTOGRAM_SIZE);
1921                if (dgi < dg) dg = dgi;
1922                updateGain2(scanner, 0, dg);
1923                updateGain2(scanner, 1, dg);
1924                updateGain2(scanner, 2, dg);
1925                break;
1926            case SCAN_FILTER_BLUE:
1927                dg = 3.00;
1928                dgi = ((double)scanner->settings.saturationLevel[2] / 65536) / ((double)scanner->preview_upper_bound[2] / HISTOGRAM_SIZE);
1929                if (dgi < dg) dg = dgi;
1930                updateGain2(scanner, 2, dg);
1931                break;
1932            case SCAN_FILTER_GREEN:
1933                dg = 3.00;
1934                dgi = ((double)scanner->settings.saturationLevel[1] / 65536) / ((double)scanner->preview_upper_bound[1] / HISTOGRAM_SIZE);
1935                if (dgi < dg) dg = dgi;
1936                updateGain2(scanner, 1, dg);
1937                break;
1938            case SCAN_FILTER_RED:
1939                dg = 3.00;
1940                dgi = ((double)scanner->settings.saturationLevel[0] / 65536) / ((double)scanner->preview_upper_bound[0] / HISTOGRAM_SIZE);
1941                if (dgi < dg) dg = dgi;
1942                updateGain2(scanner, 0, dg);
1943                break;
1944            case SCAN_FILTER_NEUTRAL:
1945                break;
1946        }
1947        status.pieusb_status = PIEUSB_STATUS_GOOD;
1948    } else if (strcmp (calibration_mode, SCAN_CALIBRATION_OPTIONS) == 0) {
1949        DBG (DBG_info_sane, "sanei_pieusb_set_gain_offset(): get calibration data from options\n");
1950        /* Exposure times */
1951        scanner->settings.exposureTime[0] = scanner->val[OPT_SET_EXPOSURE_R].w;
1952        scanner->settings.exposureTime[1] = scanner->val[OPT_SET_EXPOSURE_G].w;
1953        scanner->settings.exposureTime[2] = scanner->val[OPT_SET_EXPOSURE_B].w;
1954        scanner->settings.exposureTime[3] = scanner->val[OPT_SET_EXPOSURE_I].w; /* Infrared */
1955        /* Offsets */
1956        scanner->settings.offset[0] = scanner->val[OPT_SET_OFFSET_R].w;
1957        scanner->settings.offset[1] = scanner->val[OPT_SET_OFFSET_G].w;
1958        scanner->settings.offset[2] = scanner->val[OPT_SET_OFFSET_B].w;
1959        scanner->settings.offset[3] = scanner->val[OPT_SET_OFFSET_I].w; /* Infrared */
1960        /* Gains */
1961        scanner->settings.gain[0] = scanner->val[OPT_SET_GAIN_R].w;
1962        scanner->settings.gain[1] = scanner->val[OPT_SET_GAIN_G].w;
1963        scanner->settings.gain[2] = scanner->val[OPT_SET_GAIN_B].w;
1964        scanner->settings.gain[3] = scanner->val[OPT_SET_GAIN_I].w; /* Infrared */
1965        /* Light, extra entries and doubling */
1966        scanner->settings.light = scanner->val[OPT_LIGHT].w;
1967        scanner->settings.extraEntries = DEFAULT_ADDITIONAL_ENTRIES;
1968        scanner->settings.doubleTimes = scanner->val[OPT_DOUBLE_TIMES].w;
1969        status.pieusb_status = PIEUSB_STATUS_GOOD;
1970    } else { /* SCAN_CALIBRATION_AUTO */
1971        DBG (DBG_info_sane, "sanei_pieusb_set_gain_offset(): get calibration data from scanner\n");
1972        sanei_pieusb_cmd_get_gain_offset (scanner->device_number, &scanner->settings, &status);
1973    }
1974    /* Check status */
1975    if (status.pieusb_status == PIEUSB_STATUS_DEVICE_BUSY) {
1976      ret = sanei_pieusb_wait_ready (scanner, 0);
1977      if (ret != SANE_STATUS_GOOD) {
1978	DBG (DBG_error,"sanei_pieusb_set_gain_offset(): not ready after sanei_pieusb_cmd_get_gain_offset(): %d\n", ret);
1979	return ret;
1980      }
1981    }
1982    else if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
1983        return SANE_STATUS_INVAL;
1984    }
1985    /* Adjust gain */
1986    gain = 1.0;
1987    if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_03) == 0) {
1988        gain = 0.3;
1989    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_05) == 0) {
1990        gain = 0.5;
1991    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_08) == 0) {
1992        gain = 0.8;
1993    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_10) == 0) {
1994        gain = 1.0;
1995    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_12) == 0) {
1996        gain = 1.2;
1997    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_16) == 0) {
1998        gain = 1.6;
1999    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_19) == 0) {
2000        gain = 1.9;
2001    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_24) == 0) {
2002        gain = 2.4;
2003    } else if (strcmp (scanner->val[OPT_GAIN_ADJUST].s, SCAN_GAIN_ADJUST_30) == 0) {
2004        gain = 3.0;
2005    }
2006    switch (scanner->mode.passes) {
2007        case SCAN_ONE_PASS_RGBI:
2008        case SCAN_ONE_PASS_COLOR:
2009            updateGain2 (scanner, 0, gain);
2010            updateGain2 (scanner, 1, gain);
2011            updateGain2 (scanner, 2, gain);
2012            /* Don't correct IR, hampers cleaning process... */
2013            break;
2014        case SCAN_FILTER_INFRARED:
2015            updateGain2 (scanner, 3, gain);
2016            break;
2017        case SCAN_FILTER_BLUE:
2018            updateGain2 (scanner, 2, gain);
2019            break;
2020        case SCAN_FILTER_GREEN:
2021            updateGain2 (scanner, 1, gain);
2022            break;
2023        case SCAN_FILTER_RED:
2024            updateGain2 (scanner, 0, gain);
2025            break;
2026        case SCAN_FILTER_NEUTRAL:
2027            break;
2028    }
2029    /* Now set values for gain, offset and exposure */
2030    sanei_pieusb_cmd_set_gain_offset (scanner->device_number, &(scanner->settings), &status);
2031    ret = sanei_pieusb_convert_status (status.pieusb_status);
2032    DBG (DBG_info_sane, "sanei_pieusb_set_gain_offset(): status %s\n", sane_strstatus (ret));
2033    return ret;
2034}
2035
2036/*
2037 * get shading data
2038 * must be called immediately after sanei_pieusb_set_gain_offset
2039 */
2040
2041SANE_Status
2042sanei_pieusb_get_shading_data(Pieusb_Scanner * scanner)
2043{
2044    struct Pieusb_Command_Status status;
2045    SANE_Int shading_width;
2046    SANE_Int shading_height;
2047    SANE_Byte* buffer;
2048    SANE_Int lines;
2049    SANE_Int cols;
2050    SANE_Int size;
2051    SANE_Status res = SANE_STATUS_GOOD;
2052
2053    DBG (DBG_info_sane, "sanei_pieusb_get_shading_data()\n");
2054    shading_width = scanner->device->shading_parameters[0].pixelsPerLine;
2055    shading_height = scanner->device->shading_parameters[0].nLines;
2056    if (shading_height < 1) {
2057        DBG (DBG_error, "shading_height < 1\n");
2058	return SANE_STATUS_INVAL;
2059    }
2060    switch (scanner->mode.colorFormat) {
2061        case SCAN_COLOR_FORMAT_PIXEL: /* Pixel */
2062            lines = shading_height * 4;
2063            cols = 2 * shading_width;
2064            break;
2065        case SCAN_COLOR_FORMAT_INDEX: /* Indexed */
2066            lines = shading_height * 4;
2067            cols = (2 * shading_width + 2);
2068            break;
2069        default:
2070            DBG (DBG_error, "sanei_pieusb_get_shading_data(): color format %d not implemented\n", scanner->mode.colorFormat);
2071            return SANE_STATUS_INVAL;
2072    }
2073
2074    size = cols * lines;
2075    buffer = malloc (size);
2076    if (buffer == NULL) {
2077        return SANE_STATUS_NO_MEM;
2078    }
2079    sanei_pieusb_cmd_get_scanned_lines (scanner->device_number, buffer, 4, cols * 4, &status);
2080    if (status.pieusb_status == PIEUSB_STATUS_GOOD) {
2081        res = sanei_pieusb_wait_ready (scanner, 0);
2082        if (res == SANE_STATUS_GOOD) {
2083            sanei_pieusb_cmd_get_scanned_lines (scanner->device_number, buffer + cols*4, lines - 4, (lines - 4) * cols, &status);
2084	    if (status.pieusb_status == PIEUSB_STATUS_GOOD) {
2085	        pieusb_calculate_shading (scanner, buffer);
2086	    }
2087	    res = sanei_pieusb_convert_status (status.pieusb_status);
2088	}
2089    }
2090    else {
2091        res = sanei_pieusb_convert_status (status.pieusb_status);
2092    }
2093    free (buffer);
2094    return res;
2095}
2096
2097/*
2098 *
2099 */
2100
2101SANE_Status
2102sanei_pieusb_get_ccd_mask(Pieusb_Scanner * scanner)
2103{
2104    struct Pieusb_Command_Status status;
2105
2106    DBG(DBG_info_proc, "sanei_pieusb_get_ccd_mask()\n");
2107
2108    sanei_pieusb_cmd_get_ccd_mask(scanner->device_number, scanner->ccd_mask, scanner->ccd_mask_size, &status);
2109    if (status.pieusb_status == PIEUSB_STATUS_GOOD) {
2110      /* Save CCD mask */
2111      if (scanner->val[OPT_SAVE_CCDMASK].b) {
2112        FILE* fs = fopen ("pieusb.ccd", "w");
2113        fwrite (scanner->ccd_mask, 1, scanner->ccd_mask_size, fs);
2114        fclose (fs);
2115      }
2116    }
2117  return sanei_pieusb_convert_status(status.pieusb_status);
2118
2119}
2120
2121/**
2122 * Read parameters from scanner
2123 * and initialize SANE parameters
2124 *
2125 * @param scanner
2126 * @return parameter_bytes for use in get_scan_data()
2127 */
2128SANE_Status
2129sanei_pieusb_get_parameters(Pieusb_Scanner * scanner, SANE_Int *parameter_bytes)
2130{
2131    struct Pieusb_Command_Status status;
2132    struct Pieusb_Scan_Parameters parameters;
2133    const char *mode;
2134
2135    DBG (DBG_info_proc, "sanei_pieusb_get_parameters()\n");
2136
2137    sanei_pieusb_cmd_get_parameters (scanner->device_number, &parameters, &status);
2138    if (status.pieusb_status != PIEUSB_STATUS_GOOD) {
2139        return sanei_pieusb_convert_status (status.pieusb_status);
2140    }
2141    *parameter_bytes = parameters.bytes;
2142    /* Use response from sanei_pieusb_cmd_get_parameters() for initialization of SANE parameters.
2143     * Note the weird values of the bytes-field: this is because of the colorFormat
2144     * setting in sanei_pieusb_cmd_set_mode(). The single-color modes all use the pixel format,
2145     * which makes sanei_pieusb_cmd_get_parameters() return a full color line although just
2146     * one color actually contains data. For the index format, the bytes field
2147     * gives the size of a single color line. */
2148    mode = scanner->val[OPT_MODE].s;
2149    if (strcmp (mode, SANE_VALUE_SCAN_MODE_LINEART) == 0) {
2150        scanner->scan_parameters.format = SANE_FRAME_GRAY;
2151        scanner->scan_parameters.depth = 1;
2152        scanner->scan_parameters.bytes_per_line = parameters.bytes/3;
2153    } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_HALFTONE) == 0) {
2154        scanner->scan_parameters.format = SANE_FRAME_GRAY;
2155        scanner->scan_parameters.depth = 1;
2156        scanner->scan_parameters.bytes_per_line = parameters.bytes/3;
2157    } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_GRAY) == 0) {
2158        scanner->scan_parameters.format = SANE_FRAME_GRAY;
2159        scanner->scan_parameters.depth = scanner->val[OPT_BIT_DEPTH].w;
2160        scanner->scan_parameters.bytes_per_line = parameters.bytes/3;
2161    } else if (strcmp (mode, SANE_VALUE_SCAN_MODE_RGBI) == 0) {
2162        scanner->scan_parameters.format = SANE_FRAME_RGB; /* was: SANE_FRAME_RGBI */
2163        scanner->scan_parameters.depth = scanner->val[OPT_BIT_DEPTH].w;
2164        scanner->scan_parameters.bytes_per_line = 4*parameters.bytes;
2165    } else { /* SANE_VALUE_SCAN_MODE_COLOR, with and without option clean image set */
2166        scanner->scan_parameters.format = SANE_FRAME_RGB;
2167        scanner->scan_parameters.depth = scanner->val[OPT_BIT_DEPTH].w;
2168        scanner->scan_parameters.bytes_per_line = 3*parameters.bytes;
2169    }
2170    scanner->scan_parameters.lines = parameters.lines;
2171    scanner->scan_parameters.pixels_per_line = parameters.width;
2172    scanner->scan_parameters.last_frame = SANE_TRUE;
2173
2174    DBG (DBG_info_sane,"sanei_pieusb_get_parameters(): mode '%s'\n", mode);
2175    DBG (DBG_info_sane," format = %d\n", scanner->scan_parameters.format);
2176    DBG (DBG_info_sane," depth = %d\n", scanner->scan_parameters.depth);
2177    DBG (DBG_info_sane," bytes_per_line = %d\n", scanner->scan_parameters.bytes_per_line);
2178    DBG (DBG_info_sane," lines = %d\n", scanner->scan_parameters.lines);
2179    DBG (DBG_info_sane," pixels_per_line = %d\n", scanner->scan_parameters.pixels_per_line);
2180    DBG (DBG_info_sane," last_frame = %d\n", scanner->scan_parameters.last_frame);
2181
2182    return SANE_STATUS_GOOD;
2183}
2184
2185SANE_Status
2186sanei_pieusb_get_scan_data(Pieusb_Scanner * scanner, SANE_Int parameter_bytes)
2187{
2188    struct Pieusb_Command_Status status;
2189    SANE_Parameters *parameters = &scanner->scan_parameters;
2190    SANE_Int lines_to_read, lines_remaining;
2191    SANE_Int ppl, bpl;
2192    SANE_Byte *linebuf, *lboff;
2193    SANE_Bool compress;
2194    int n, k, i;
2195
2196    switch (scanner->mode.colorFormat) {
2197        case SCAN_COLOR_FORMAT_PIXEL: /* Pixel */
2198            lines_to_read = scanner->buffer.height;
2199            break;
2200        case SCAN_COLOR_FORMAT_INDEX: /* Indexed */
2201            lines_to_read = scanner->buffer.colors * scanner->buffer.height;
2202            break;
2203        default:
2204            DBG(DBG_error, "sanei_pieusb_get_scan_data(): color format %d not implemented\n",scanner->mode.colorFormat);
2205            return SANE_STATUS_INVAL;
2206    }
2207    lines_remaining = lines_to_read;
2208    DBG (DBG_info_proc, "sanei_pieusb_get_scan_data(colorFormat %d), lines_to_read %d, bytes %d\n", scanner->mode.colorFormat, lines_to_read, parameter_bytes);
2209
2210  /*
2211    fdraw = open("/tmp/pieusb.raw", O_WRONLY | O_CREAT | O_TRUNC, (mode_t)0600);
2212    if (fdraw == -1) {
2213         perror("error opening raw image buffer file");
2214    }
2215*/
2216    while (lines_remaining > 0) {
2217        SANE_Int lines;
2218        /* Read lines */
2219        /* The amount of bytes_per_line varies with color format setting; only 'pixel' and 'index' implemented */
2220        ppl = parameters->pixels_per_line;
2221        switch (scanner->mode.colorFormat) {
2222	    case SCAN_COLOR_FORMAT_PIXEL: /* Pixel */
2223	        bpl = parameter_bytes;
2224	        break;
2225            case SCAN_COLOR_FORMAT_INDEX: /* Indexed */
2226	        bpl = parameter_bytes + 2; /* Index bytes! */
2227	        break;
2228            default:
2229	        DBG(DBG_error, "sanei_pieusb_get_scan_data(): color format %d not implemented\n", scanner->mode.colorFormat);
2230	        return SANE_STATUS_INVAL;
2231        }
2232        lines = (lines_remaining < 256) ? lines_remaining : 255;
2233        DBG(DBG_info_sane, "sanei_pieusb_get_scan_data(): reading lines: now %d, bytes per line = %d\n", lines, bpl);
2234        linebuf = malloc(lines * bpl);
2235        sanei_pieusb_cmd_get_scanned_lines(scanner->device_number, linebuf, lines, lines * bpl, &status);
2236        if (status.pieusb_status != PIEUSB_STATUS_GOOD ) {
2237	    /* Error, return */
2238	    free(linebuf);
2239	    return SANE_STATUS_INVAL;
2240	}
2241        /* Save raw data */
2242/*
2243        if (fdraw != -1) {
2244            wcnt = write(fdraw,linebuf,parameters.lines*bpl);
2245            DBG(DBG_info_sane,"Raw written %d\n",wcnt);
2246        }
2247*/
2248        /* Copy into official buffer
2249	 * Sometimes the scanner returns too many lines. Take care not to
2250	 * overflow the buffer. */
2251        lboff = linebuf;
2252        switch (scanner->mode.colorFormat) {
2253	    case SCAN_COLOR_FORMAT_PIXEL:
2254	        /* The scanner may return lines with 3 colors even though only
2255		 * one color is actually scanned. Detect this situation and
2256		 * eliminate the excess samples from the line buffer before
2257		 * handing it to buffer_put_full_color_line(). */
2258	        compress = SANE_FALSE;
2259	        if (scanner->buffer.colors == 1
2260		    && (bpl * scanner->buffer.packing_density / ppl) == (3 * scanner->buffer.packet_size_bytes)) {
2261		    compress = SANE_TRUE;
2262	        }
2263	        for (n = 0; n < lines; n++) {
2264		     if (compress) {
2265		         /* Move samples to fill up all unused locations */
2266		         int ps = scanner->buffer.packet_size_bytes;
2267		         for (k = 0; k < scanner->buffer.line_size_packets; k++) {
2268			     for (i = 0; i < ps; i++) {
2269			         lboff[ps*k+i] = lboff[3*ps*k+i];
2270			     }
2271			 }
2272		     }
2273		     if (sanei_pieusb_buffer_put_full_color_line(&scanner->buffer, lboff, bpl/3) == 0) {
2274		         /* Error, return */
2275		         return SANE_STATUS_INVAL;
2276		     }
2277		     lboff += bpl;
2278	        }
2279	        break;
2280	    case SCAN_COLOR_FORMAT_INDEX:
2281	        /* Indexed data */
2282	        for (n = 0; n < lines; n++) {
2283		    if (sanei_pieusb_buffer_put_single_color_line(&scanner->buffer, *lboff, lboff+2, bpl-2) == 0) {
2284		        /* Error, return */
2285		        return SANE_STATUS_INVAL;
2286		    }
2287		    lboff += bpl;
2288	        }
2289	        break;
2290	    default:
2291	        DBG(DBG_error, "sanei_pieusb_get_scan_data(): store color format %d not implemented\n", scanner->mode.colorFormat);
2292	        free(linebuf);
2293	        return SANE_STATUS_INVAL;
2294        }
2295        free(linebuf);
2296        lines_remaining -= lines; /* Note: excess discarded */
2297        DBG(DBG_info_sane, "sanei_pieusb_get_scan_data(): reading lines: remaining %d\n", lines_remaining);
2298    }
2299/*
2300    if (fdraw != -1) close(fdraw);
2301*/
2302    return SANE_STATUS_GOOD;
2303}
2304
2305/**
2306 * Wait for scanner to get ready
2307 *
2308 * loop of test_ready/read_state
2309 *
2310 * @param scanner
2311 * @param device_number, used if scanner == NULL
2312 * @return SANE_Status
2313 */
2314
2315SANE_Status
2316sanei_pieusb_wait_ready(Pieusb_Scanner * scanner, SANE_Int device_number)
2317{
2318  struct Pieusb_Command_Status status;
2319  struct Pieusb_Scanner_State state;
2320  time_t start, elapsed;
2321
2322  DBG (DBG_info_proc, "sanei_pieusb_wait_ready()\n");
2323  start = time(NULL);
2324  if (scanner)
2325    device_number = scanner->device_number;
2326
2327  for(;;) {
2328    sanei_pieusb_cmd_test_unit_ready(device_number, &status);
2329    DBG (DBG_info_proc, "-> sanei_pieusb_cmd_test_unit_ready: %d\n", status.pieusb_status);
2330    if (status.pieusb_status == PIEUSB_STATUS_GOOD)
2331      break;
2332    if (status.pieusb_status == PIEUSB_STATUS_IO_ERROR)
2333      break;
2334    sanei_pieusb_cmd_read_state(device_number, &state, &status);
2335    DBG (DBG_info_proc, "-> sanei_pieusb_cmd_read_state: %d\n", status.pieusb_status);
2336    if (status.pieusb_status != PIEUSB_STATUS_DEVICE_BUSY)
2337      break;
2338    sleep(2);
2339    elapsed = time(NULL) - start;
2340    if (elapsed > 120) { /* 2 minute overall timeout */
2341      DBG (DBG_error, "scanner not ready after 2 minutes\n");
2342      break;
2343    }
2344    if (elapsed % 2) {
2345      DBG (DBG_info, "still waiting for scanner to get ready\n");
2346    }
2347  }
2348  return sanei_pieusb_convert_status(status.pieusb_status);
2349}
2350
2351
2352SANE_Status sanei_pieusb_analyze_preview(Pieusb_Scanner * scanner)
2353{
2354    int k, n;
2355    SANE_Parameters params;
2356    SANE_Int N;
2357    double *norm_histo;
2358    double level;
2359
2360    DBG(DBG_info, "sanei_pieusb_analyze_preview(): saving preview data\n");
2361
2362    /* Settings */
2363    scanner->preview_done = SANE_TRUE;
2364    for (k = 0; k < 4; k++) {
2365        scanner->preview_exposure[k] = scanner->settings.exposureTime[k];
2366        scanner->preview_gain[k] = scanner->settings.gain[k];
2367        scanner->preview_offset[k] = scanner->settings.offset[k];
2368    }
2369    /* Analyze color planes */
2370    N = scanner->buffer.width * scanner->buffer.height;
2371    params.format = SANE_FRAME_GRAY;
2372    params.depth = scanner->buffer.depth;
2373    params.pixels_per_line = scanner->buffer.width;
2374    params.lines = scanner->buffer.height;
2375    for (k = 0; k < scanner->buffer.colors; k++) {
2376        /* Create histogram for color k */
2377        sanei_ir_create_norm_histogram (&params, scanner->buffer.data + k * N, &norm_histo);
2378        /* Find 1% and 99% limits */
2379        level = 0;
2380        for (n =0; n < HISTOGRAM_SIZE; n++) {
2381
2382            level += norm_histo[n];
2383            if (level < 0.01) {
2384                scanner->preview_lower_bound[k] = n;
2385            }
2386            if (level < 0.99) {
2387                scanner->preview_upper_bound[k] = n;
2388            }
2389        }
2390        DBG(DBG_info,"sanei_pieusb_analyze_preview(): 1%%-99%% levels for color %d: %d - %d\n", k, scanner->preview_lower_bound[k], scanner->preview_upper_bound[k]);
2391    }
2392    /* Disable remaining color planes */
2393    for (k = scanner->buffer.colors; k < 4; k++) {
2394        scanner->preview_lower_bound[k] = 0;
2395        scanner->preview_upper_bound[k] = 0;
2396    }
2397    return SANE_STATUS_GOOD;
2398}
2399
2400
2401/**
2402 * Return actual gain at given gain setting
2403 *
2404 * @param gain Gain setting (0 - 63)
2405 * @return
2406 */
2407static double getGain(int gain)
2408{
2409    int k;
2410
2411    /* Actually an error, but don't be picky */
2412    if (gain <= 0) {
2413        return gains[0];
2414    }
2415    /* A gain > 63 is also an error, but don't be picky */
2416    if (gain >= 60) {
2417        return (gain-55)*(gains[12]-gains[11])/5 + gains[11];
2418    }
2419    /* Interpolate other values */
2420    k = gain/5; /* index of array value just below given gain */
2421    return (gain-5*k)*(gains[k+1]-gains[k])/5 + gains[k];
2422}
2423
2424static int getGainSetting(double gain)
2425{
2426    int k, m;
2427
2428    /* Out of bounds */
2429    if (gain < 1.0) {
2430        return 0;
2431    }
2432    if (gain >= gains[12]) {
2433        m = 60 + lround((gain-gains[11])/(gains[12]-gains[11])*5);
2434        if (m > 63) m = 63;
2435        return m;
2436    }
2437    /* Interpolate the rest */
2438    m = 0;
2439    for (k = 0; k <= 11; k++) {
2440        if (gains[k] <= gain && gain < gains[k+1]) {
2441            m = 5*k + lround((gain-gains[k])/(gains[k+1]-gains[k])*5);
2442        }
2443    }
2444    return m;
2445}
2446
2447/**
2448 * Modify gain and exposure times in order to make maximal use of the scan depth.
2449 * Each color treated separately, infrared excluded.
2450 *
2451 * This may be too aggressive => leads to a noisy whitish border instead of the orange.
2452 * In a couuple of tries, gain was set to values of 60 and above, which introduces
2453 * the noise?
2454 * The whitish border is logical since the brightest parts of the negative, the
2455 * unexposed borders, are amplified to values near CCD saturation, which is white.
2456 * Maybe a uniform gain increase for each color is more appropriate? Somewhere
2457 * between 2.5 and 3 seems worthwhile trying, see updateGain2().
2458 *
2459        switch (scanner->mode.passes) {
2460            case SCAN_ONE_PASS_RGBI:
2461                updateGain(scanner,0);
2462                updateGain(scanner,1);
2463                updateGain(scanner,2);
2464                updateGain(scanner,3);
2465                break;
2466            case SCAN_ONE_PASS_COLOR:
2467                updateGain(scanner,0);
2468                updateGain(scanner,1);
2469                updateGain(scanner,2);
2470                break;
2471            case SCAN_FILTER_INFRARED:
2472                updateGain(scanner,3);
2473                break;
2474            case SCAN_FILTER_BLUE:
2475                updateGain(scanner,2);
2476                break;
2477            case SCAN_FILTER_GREEN:
2478                updateGain(scanner,1);
2479                break;
2480            case SCAN_FILTER_RED:
2481                updateGain(scanner,0);
2482                break;
2483            case SCAN_FILTER_NEUTRAL:
2484                break;
2485        }
2486 * @param scanner
2487 */
2488/*
2489static void updateGain(Pieusb_Scanner *scanner, int color_index)
2490{
2491    double g, dg;
2492
2493    DBG(DBG_info_sane,"updateGain(): color %d preview used G=%d Exp=%d\n", color_index, scanner->preview_gain[color_index], scanner->preview_exposure[color_index]);
2494    // Additional gain to obtain
2495    dg = ((double)scanner->settings.saturationLevel[color_index] / 65536) / ((double)scanner->preview_upper_bound[color_index] / HISTOGRAM_SIZE);
2496    DBG(DBG_info_sane,"updateGain(): additional gain %f\n", dg);
2497    // Achieve this by modifying gain and exposure
2498    // Gain used for preview
2499    g = getGain(scanner->preview_gain[color_index]);
2500    DBG(DBG_info_sane,"updateGain(): preview had gain %d => %f\n",scanner->preview_gain[color_index],g);
2501    // Look up new gain setting g*sqrt(dg)
2502    DBG(DBG_info_sane,"updateGain(): optimized gain * %f = %f\n",sqrt(dg),sqrt(dg)*g);
2503    scanner->settings.gain[color_index] = getGainSetting(g*sqrt(dg));
2504    DBG(DBG_info_sane,"updateGain(): optimized gain setting %d => %f\n",scanner->settings.gain[color_index],getGain(scanner->settings.gain[color_index]));
2505    // Exposure change is straightforward
2506    DBG(DBG_info_sane,"updateGain(): remains for exposure %f\n",dg/(getGain(scanner->settings.gain[color_index])/g));
2507    scanner->settings.exposureTime[color_index] = lround( g / getGain(scanner->settings.gain[color_index]) * dg * scanner->preview_exposure[color_index] );
2508    DBG(DBG_info_sane,"updateGain(): new setting G=%d Exp=%d\n", scanner->settings.gain[color_index], scanner->settings.exposureTime[color_index]);
2509}
2510*/
2511
2512static void updateGain2(Pieusb_Scanner *scanner, int color_index, double gain_increase)
2513{
2514    double g;
2515
2516    DBG(DBG_info,"updateGain2(): color %d preview used G=%d Exp=%d\n", color_index, scanner->settings.gain[color_index], scanner->settings.exposureTime[color_index]);
2517    /* Additional gain to obtain */
2518    DBG(DBG_info,"updateGain2(): additional gain %f\n", gain_increase);
2519    /* Achieve this by modifying gain and exposure */
2520    /* Gain used for preview */
2521    g = getGain(scanner->settings.gain[color_index]);
2522    DBG(DBG_info,"updateGain2(): preview had gain %d => %f\n", scanner->settings.gain[color_index], g);
2523    /* Look up new gain setting g*sqrt(dg) */
2524    DBG(DBG_info,"updateGain2(): optimized gain * %f = %f\n", sqrt(gain_increase), sqrt(gain_increase) * g);
2525    scanner->settings.gain[color_index] = getGainSetting(g * sqrt(gain_increase));
2526    DBG(DBG_info,"updateGain2(): optimized gain setting %d => %f\n", scanner->settings.gain[color_index], getGain(scanner->settings.gain[color_index]));
2527    /* Exposure change is straightforward */
2528    DBG(DBG_info,"updateGain2(): remains for exposure %f\n", gain_increase / (getGain(scanner->settings.gain[color_index]) / g));
2529    scanner->settings.exposureTime[color_index] = lround( g / getGain(scanner->settings.gain[color_index]) * gain_increase * scanner->settings.exposureTime[color_index] );
2530    DBG(DBG_info,"updateGain2(): new setting G=%d Exp=%d\n", scanner->settings.gain[color_index], scanner->settings.exposureTime[color_index]);
2531}
2532