home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 4 Drivers / 04-Drivers.zip / mtek004.zip / mtekscan.c < prev    next >
C/C++ Source or Header  |  1997-09-16  |  36KB  |  1,123 lines

  1. /*
  2.    mtekscan.c
  3.  
  4.    Linux driver for MicroTek SCSI scanners (and compatibles).
  5.  
  6.    Copyright (c) 1996,1997 Jan Schoenepauck / Fast Forward Productions
  7.    <schoenep@uni-wuppertal.de>
  8.  
  9.    For latest information, check:
  10.    http://fb4-1112.uni-muenster.de/ffwd/
  11.  
  12.    $Id: mtekscan.c 1.5 1997/09/16 04:43:59 parent Exp parent $
  13. */
  14.  
  15.  
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18. #include <signal.h>
  19. #include <unistd.h>
  20. #include <string.h>
  21. #ifdef __EMX__
  22. #include <ctype.h>
  23. #endif
  24. #include "config.h"
  25. #include "global.h"
  26. #include "options.h"
  27. #include "scsi.h"
  28. #include "gammatab.h"
  29. #include "mt_defs.h"
  30. #include "mt_error.h"
  31.  
  32. char *myname;
  33.  
  34. int use_expanded_resolution;
  35. int fast_color_prescan;
  36. int resolution_setting_unit;
  37. int multi_bit_scan;
  38. int one_pass_color_scan;
  39.  
  40. unsigned char contrast;
  41. unsigned char exposure;
  42. FILE *output_file;
  43. unsigned char *imagebuffer;
  44. unsigned char *xferbuffer;
  45. unsigned int ibufsize;
  46. int image_width, image_height;
  47.  
  48. int scanning = 0;
  49.  
  50.  
  51. /* Macros */
  52.  
  53. #define ERROR_RETURN(string...) { fprintf(stderr, "%s: ", myname); \
  54. fprintf(stderr, ##string);  scsi_close_device(); return(RET_FAIL); }
  55.  
  56. #define EXIT_CLOSE(code) { scsi_close_device(); exit(code); }
  57. #define SWAP(a,b) { int t; (t) = (a);  (a) = (b);  (b) = (t); }
  58.  
  59. #define DEBUG_MSG(string) { fprintf(stderr, "%s: %s\n", myname, string); }
  60.  
  61. /*------------------------------------------------------------------------*/
  62. /* int convert_unit (float value)                                         */
  63. /* Converts between measurement units. The input value unit is defined    */
  64. /* by src_unit and is converted into the unit defined by set_unit.        */
  65. /* Args: value  - the size to be converted                                */
  66. /* Return: The converted value in int format.                             */
  67. /*------------------------------------------------------------------------*/
  68. int convert_unit (float value) {
  69.   switch (set_unit) {
  70.   case EIGHTHINCH :
  71.     switch (src_unit) {
  72.     case CM :
  73.       return((int)((value / 2.54) * 8));
  74.     case MM :
  75.       return((int)((value / 25.4) * 8));
  76.     case EIGHTHINCH :
  77.       return((int)value);
  78.     default :
  79.       return((int)(value * 8));
  80.     }
  81.     break;
  82.   case PIXEL :
  83.     switch (src_unit) {
  84.     case CM :
  85.     case MM :
  86.     case EIGHTHINCH :
  87.     default :
  88.     }
  89.   }
  90.   return(0);
  91. }
  92.  
  93.  
  94. /*------------------------------------------------------------------------*/
  95. /* unsigned char get_resolution_byte (int desired_level)                  */
  96. /* Computes the resolution code needed by the scanner from the specified  */
  97. /* resolution value <desired_level>                                       */
  98. /* Args: <desired_level>  Resolution value.                               */
  99. /* Return: Resolution value or 0 if desired resolution is too high.       */
  100. /*------------------------------------------------------------------------*/
  101. unsigned char get_resolution_byte (int desired_level) {
  102.   float max_in_range;
  103.   float temp;
  104.   int min_val;
  105.   
  106. /* some special cases */
  107.   if ((MAX_BASE_RESOLUTION == 600) && (mt_res_5percent)) {
  108.     if (desired_level == 400) return(0x17);
  109.     if (desired_level == 200) return(0x1d);
  110.   }
  111.   if ((MAX_BASE_RESOLUTION == 300) && (mt_res_5percent)) {
  112.     if (desired_level == 200) return(0x17);
  113.     if (desired_level == 100) return(0x1d);
  114.   }
  115.   if (desired_level > MAX_BASE_RESOLUTION) {
  116. #if (IGNORE_XRES_FLAG)
  117.     if (desired_level > MAX_EXPANDED_RESOLUTION) {
  118. #else
  119.     if ((!mt_ExpandedResolution) || 
  120.        (desired_level > MAX_EXPANDED_RESOLUTION)) {
  121. #endif
  122.       fprintf(stderr, "%s: Selected resolution exceeds maximum.\n", myname);
  123.       return(0);
  124.     }
  125.     max_in_range = MAX_EXPANDED_RESOLUTION;
  126.     use_expanded_resolution = 1;
  127.   }
  128.   else {
  129.     max_in_range = MAX_BASE_RESOLUTION;
  130.     use_expanded_resolution = 0;
  131.   }
  132.   if ((mt_res_1percent) && (!FORCE_5_PERCENT_STEPS)) {
  133.     resolution_setting_unit = 1;
  134.     return((unsigned char)(((float)desired_level * 100) / max_in_range));
  135.   }
  136.   else {
  137.     resolution_setting_unit = 5;
  138.     min_val = ((MAX_BASE_RESOLUTION == 400)||(MAX_BASE_RESOLUTION == 800)) ?
  139.               0x20 : 0x10;
  140.     temp = (max_in_range - (float)desired_level) / (max_in_range * 0.05);
  141.     if ((unsigned char)temp > 0x0f) {
  142.       fprintf(stderr, "%s: Resolution must be at least %d dpi.\n",
  143.               myname, (int)(max_in_range*0.25));
  144.       return(0);
  145.     }
  146.     return(min_val + (unsigned char)temp);
  147.   }
  148. }
  149.  
  150.  
  151. /*------------------------------------------------------------------------*/
  152. int wait_unit_ready (void) {
  153.   scsi_6byte_cmd TEST_UNIT_READY = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  154.   int retry = 0;
  155.  
  156. #if (DEBUG)
  157.   DEBUG_MSG("wait_unit_ready() called.");
  158. #endif
  159.  
  160.   while (scsi_handle_cmd(TEST_UNIT_READY, 6, NULL, 0, NULL, 0)
  161.          != RET_SUCCESS) {
  162.     retry++;
  163.     if (retry == 5) {
  164.       fprintf(stderr, "%s: Timeout waiting for scanner.\n", myname);
  165.       return(RET_FAIL);
  166.     }
  167.     if (verbose)
  168.       fprintf(stderr, "%s: Waiting for scanner to get ready (retry %d).\n",
  169.               myname, retry);
  170.     sleep(3);
  171.   }
  172.  
  173. #if (DEBUG)
  174.   DEBUG_MSG("wait_unit_ready() done.");
  175. #endif
  176.   return(RET_SUCCESS);
  177. }
  178.  
  179.  
  180. /*------------------------------------------------------------------------*/
  181. int selftest (void) {
  182.   scsi_6byte_cmd SEND_DIAGNOSTIC = { 0x1d, 0x04, 0x00, 0x00, 0x00, 0x00 };
  183.   scsi_6byte_cmd RECEIVE_RESULTS = { 0x1c, 0x00, 0x00, 0x00, 0x01, 0x00 };
  184.   unsigned char diag_result;
  185.  
  186.   fprintf(stderr, "%s: Performing scanner selftest...\n", myname);
  187.  
  188.   if (scsi_handle_cmd(SEND_DIAGNOSTIC, 6, NULL, 0, NULL, 0) != RET_SUCCESS) {
  189.     check_sense(scsi_sensebuffer);
  190.     ERROR_RETURN("Error executing SEND DIAGNOSTIC command.\n");
  191.   }
  192.  
  193.   sleep(5);
  194.   wait_unit_ready();
  195.  
  196.   if (scsi_handle_cmd(RECEIVE_RESULTS, 6, NULL, 0, &diag_result, 1)
  197.       != RET_SUCCESS) {
  198.     check_sense(scsi_sensebuffer);
  199.     ERROR_RETURN("Error executing RECEIVE DIAGNOSTIC RESULTS command.\n");
  200.   }
  201.  
  202.   if (diag_result == 0x00)
  203.     fprintf(stderr, "%s: Selftest result code 0x%02x (no failures).\n",
  204.             myname, diag_result);
  205.   else {
  206.     fprintf(stderr, "%s: Selftest result code 0x%02x.\n", myname, diag_result);
  207.     if (diag_result & 0x01)
  208.       fprintf(stderr, "    CPU RAM failure\n");
  209.     if (diag_result & 0x02)
  210.       fprintf(stderr, "    Scanner system RAM failure\n");
  211.     if (diag_result & 0x04)
  212.       fprintf(stderr, "    Image RAM failure (image buffer or "
  213.                       "ping-pong buffer)\n");
  214.     if (diag_result & 0x10)
  215.       fprintf(stderr, "    DC offset error (black level "
  216.                       "calibration failure)\n");
  217.     if (diag_result & 0x20)
  218.       fprintf(stderr, "    Scanning lamp or image sensor circuit failure\n");
  219.     if (diag_result & 0x40)
  220.       fprintf(stderr, "    Scanning head motor or home position "
  221.                       "sensor failure\n");
  222.     if (diag_result & 0x80)
  223.       fprintf(stderr, "    Automatic document feeder paper "
  224.                       "ejection failure\n");
  225.   }
  226.   return(RET_SUCCESS);
  227. }
  228.  
  229.  
  230. /*------------------------------------------------------------------------*/
  231. int scanning_frame (float xf1, float yf1, float xf2, float yf2) {
  232.   scsi_6byte_cmd SCANNING_FRAME = { 0x04, 0x00, 0x00, 0x00, 0x09, 0x00 };
  233.   unsigned char frame_data[9];
  234.   int x1, y1, x2, y2;
  235.   float ymax = doc_max_y;
  236.  
  237. #if (DEBUG)
  238.   DEBUG_MSG("scanning_frame() called.");
  239. #endif
  240.  
  241.   if ((paper_length >= 0) && (paper_length < doc_max_y)) ymax = paper_length;
  242.   if ((xf1 >= doc_max_x)||(xf2 >= doc_max_x)||(yf1 >= ymax)||(yf2 >= ymax))
  243.     ERROR_RETURN("Scanning frame coordinate exceeds max. document size.\n");
  244. #if (FIX_FRAMESIZE)
  245.   xf1 /= 2;
  246.   yf1 /= 2;
  247.   xf2 /= 2;
  248.   yf2 /= 2;
  249. #endif
  250.   x1 = convert_unit(xf1);
  251.   y1 = convert_unit(yf1);
  252.   x2 = convert_unit(xf2);
  253.   y2 = convert_unit(yf2);
  254.   if (x1 == x2)
  255.     ERROR_RETURN("Scanning frame has zero width.\n");
  256.   if (y1 == y2)
  257.     ERROR_RETURN("Scanning frame has zero height.\n");
  258.   if (x2 < x1) SWAP(x1, x2);
  259.   if (y2 < y1) SWAP(y1, y2);
  260.   frame_data[0] = 0;
  261.   if (scan_type == HALFTONE) frame_data[0] |= 0x01;
  262.   if (set_unit == PIXEL)    frame_data[0] |= 0x08;
  263.   frame_data[1] = (unsigned char)(x1 & 0xff);
  264.   frame_data[2] = (unsigned char)((x1 & 0xff00) >> 8);
  265.   frame_data[3] = (unsigned char)(y1 & 0xff);
  266.   frame_data[4] = (unsigned char)((y1 & 0xff00) >> 8);
  267.   frame_data[5] = (unsigned char)(x2 & 0xff);
  268.   frame_data[6] = (unsigned char)((x2 & 0xff00) >> 8);
  269.   frame_data[7] = (unsigned char)(y2 & 0xff);
  270.   frame_data[8] = (unsigned char)((y2 & 0xff00) >> 8);
  271.   if (scsi_handle_cmd(SCANNING_FRAME, 6, frame_data, 9, NULL, 0)
  272.       != RET_SUCCESS) {
  273.     check_sense(scsi_sensebuffer);
  274.     ERROR_RETURN("Error executing SCANNING FRAME command.\n");
  275.   }
  276.  
  277. #if (DEBUG)
  278.   DEBUG_MSG("scanning_frame() done.");
  279. #endif
  280.   return(RET_SUCCESS);
  281. }
  282.  
  283.  
  284. /*------------------------------------------------------------------------*/
  285. int mode_select (void) {
  286.   scsi_6byte_cmd MODE_SELECT = { 0x15, 0x00, 0x00, 0x00, 0x00, 0x00 };
  287.   unsigned char mode_data[11];
  288.   int paperlen;
  289.   int tlength = 0x0a;
  290.  
  291. #if (DEBUG)
  292.   DEBUG_MSG("mode_select() called.");
  293. #endif
  294.  
  295.   if (mt_MidtoneAdjustment) tlength = 0x0b;
  296.   MODE_SELECT[4] = (unsigned char)(tlength & 0xff);
  297.   if (paper_length < 0) paper_length = doc_max_y;
  298.   paperlen = convert_unit(paper_length);
  299.   mode_data[0] = 0x81;
  300.   mode_data[1] = get_resolution_byte(scan_resolution);
  301.   if (mode_data[1] == 0x00) return(RET_FAIL);
  302.   if (resolution_setting_unit == 1) mode_data[0] |= 0x02;
  303.   if (set_unit == PIXEL)            mode_data[0] |= 0x08;
  304.   mode_data[2]  = exposure;
  305.   mode_data[3]  = contrast;
  306.   mode_data[4]  = halftone_pattern;
  307.   mode_data[5]  = scan_velocity;
  308.   mode_data[6]  = shadow_adjust;
  309.   mode_data[7]  = highlight_adjust;
  310.   mode_data[8]  = (unsigned char)(paperlen & 0xff);
  311.   mode_data[9]  = (unsigned char)((paperlen & 0xff00) >> 8);
  312.   mode_data[10] = midtone_adjust;
  313.   if (scsi_handle_cmd(MODE_SELECT, 6, mode_data, tlength, NULL, 0)
  314.       != RET_SUCCESS) {
  315.     check_sense(scsi_sensebuffer);
  316.     ERROR_RETURN("Error executing MODE SELECT command.\n");
  317.   }
  318.  
  319. #if (DEBUG)
  320.   DEBUG_MSG("mode_select() done.");
  321. #endif
  322.   return(RET_SUCCESS);
  323. }
  324.  
  325.  
  326. /*------------------------------------------------------------------------*/
  327. int mode_select_1 (void) {
  328.   scsi_6byte_cmd MODE_SELECT_1 = { 0x16, 0x00, 0x00, 0x00, 0x0a, 0x00 };
  329.   unsigned char mode_data[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  330.  
  331. #if (DEBUG)
  332.   DEBUG_MSG("mode_select_1() called.");
  333. #endif
  334.  
  335.   mode_data[1] = (unsigned char)brightness_adjust_r;
  336.   if (!allow_calibration) mode_data[3] |= 0x02;
  337.   if (scsi_handle_cmd(MODE_SELECT_1, 6, mode_data, 10, NULL, 0)
  338.       != RET_SUCCESS) {
  339.     check_sense(scsi_sensebuffer);
  340.     ERROR_RETURN("Error executing MODE SELECT 1 command.\n");
  341.   }
  342.  
  343. #if (DEBUG)
  344.   DEBUG_MSG("mode_select_1() done.");
  345. #endif
  346.   return(RET_SUCCESS);
  347. }
  348.  
  349.  
  350. /*------------------------------------------------------------------------*/
  351. int mode_sense (void) {
  352.   scsi_6byte_cmd MODE_SENSE = { 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00 };
  353.   unsigned char mode_data[20];
  354.   int tlength = 0x13;
  355.  
  356. #if (DEBUG)
  357.   DEBUG_MSG("mode_sense() called.")
  358. #endif
  359.  
  360.   if (!mt_OnePass) {
  361.     if (mt_MidtoneAdjustment) tlength = 0x0b;
  362.     else tlength = 0x0a;
  363.   }
  364.   MODE_SENSE[4] = (unsigned char)(tlength & 0xff);
  365.   if (scsi_handle_cmd(MODE_SENSE, 6, NULL, 0, mode_data, tlength) 
  366.       != RET_SUCCESS) {
  367.     check_sense(scsi_sensebuffer);
  368.     ERROR_RETURN("Error executing MODE SENSE command.\n");
  369.   }
  370. #if (SHOW_MODE_SENSE)
  371.   {
  372.     int i;
  373.     fprintf(stderr, "%s: MODE SENSE data:\n", myname);
  374.     for (i=0; i<tlength; i++) fprintf(stderr, "%02x ", mode_data[i]);
  375.     fprintf(stderr, "\n");
  376.   }
  377. #endif
  378. #if (DEBUG)
  379.   DEBUG_MSG("mode_sense() done.");
  380. #endif
  381.   return(RET_SUCCESS);
  382. }
  383.  
  384.  
  385. /*------------------------------------------------------------------------*/
  386. int mode_sense_1 (void) {
  387.   scsi_6byte_cmd MODE_SENSE_1 = { 0x19, 0x00, 0x00, 0x00, 0x1e, 0x00 };
  388.   unsigned char mode_data[30] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  389.                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  390.                                   0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  391.  
  392. #if (DEBUG)
  393.   DEBUG_MSG("mode_sense_1() called.");
  394. #endif
  395.  
  396.   mode_data[1] = (unsigned char)brightness_adjust_r;
  397.   mode_data[2] = (unsigned char)brightness_adjust_g;
  398.   mode_data[3] = (unsigned char)brightness_adjust_b;
  399.   if (scsi_handle_cmd(MODE_SENSE_1, 6, mode_data, 30, NULL, 0)
  400.       != RET_SUCCESS) {
  401.     check_sense(scsi_sensebuffer);
  402.     ERROR_RETURN("Error executing MODE SENSE 1 command.\n");
  403.   }
  404.  
  405. #if (DEBUG)
  406.   DEBUG_MSG("mode_sense_1() done.");
  407. #endif
  408.   return(RET_SUCCESS);
  409. }
  410.  
  411.  
  412. /*------------------------------------------------------------------------*/
  413. int accessory_and_backtracking (void) {
  414.   scsi_6byte_cmd ACCESSORY = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00 };
  415.  
  416. #if (DEBUG)
  417.   DEBUG_MSG("accessory_and_backtracking() called.");
  418. #endif
  419.  
  420.   if (use_adf)            ACCESSORY[4] |= 0x41;
  421.   if (prescan)            ACCESSORY[4] |= 0x18;
  422.   if (transparency)       ACCESSORY[4] |= 0x24;
  423.   if (allow_backtracking) ACCESSORY[4] |= 0x81;
  424.   if (scsi_handle_cmd(ACCESSORY, 6, NULL, 0, NULL, 0) != RET_SUCCESS) {
  425.     check_sense(scsi_sensebuffer);
  426.     ERROR_RETURN("Error executing ACCESSORY & BACKTRACKING command.\n");
  427.   }
  428.  
  429. #if (DEBUG)
  430.   DEBUG_MSG("accessory_and_backtracking() done.");
  431. #endif
  432.   return(RET_SUCCESS);
  433. }
  434.  
  435.  
  436. /*------------------------------------------------------------------------*/
  437. int start_scan (char filter) {
  438.   scsi_6byte_cmd START_SCAN = { 0x1b, 0x00, 0x00, 0x00, 0x01, 0x00 };
  439.  
  440. #if (DEBUG)
  441.   DEBUG_MSG("start_scan() called.");
  442. #endif
  443.  
  444.   if (use_expanded_resolution) START_SCAN[4] |= 0x80;
  445.   if (multi_bit_scan)          START_SCAN[4] |= 0x40;
  446.   if (one_pass_color_scan)     START_SCAN[4] |= 0x20;
  447.   if (reverse_colors)          START_SCAN[4] |= 0x04;
  448.   if (fast_color_prescan)      START_SCAN[4] |= 0x02;
  449.   switch(filter) {
  450.   case RED :
  451.     START_SCAN[4] |= 0x08;  break;
  452.   case GREEN :
  453.     START_SCAN[4] |= 0x10;  break;
  454.   case BLUE :
  455.     START_SCAN[4] |= 0x18;  break;
  456.   case CLEAR :
  457.   default :
  458.   }
  459.   if (scsi_handle_cmd(START_SCAN, 6, NULL, 0, NULL, 0) != RET_SUCCESS) {
  460.     check_sense(scsi_sensebuffer);
  461.     ERROR_RETURN("Error executing START SCAN command.\n");
  462.   }
  463.  
  464. #if (DEBUG)
  465.   DEBUG_MSG("start_scan() done.");
  466. #endif
  467.   return(RET_SUCCESS);
  468. }
  469.  
  470.  
  471. /*------------------------------------------------------------------------*/
  472. int stop_scan (void) {
  473.   scsi_6byte_cmd STOP_SCAN = { 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00 };
  474.   int retry = 0;
  475.   int result, error;
  476.  
  477. #if (DEBUG)
  478.   DEBUG_MSG("stop_scan() called.");
  479. #endif
  480.  
  481.   do {
  482.     result = scsi_handle_cmd(STOP_SCAN, 6, NULL, 0, NULL, 0);
  483.     if (result != RET_SUCCESS) {
  484.       error = check_sense(scsi_sensebuffer);
  485.       if ((error == HW_ERROR) || (error == OP_ERROR)) return(-1);
  486.       retry++;
  487.       if (verbose)
  488.         fprintf(stderr, "%s: Waiting for scan head to return (retry %d).\n",
  489.                 myname, retry);
  490.       sleep(WAIT_RETURN_SLEEP_TIME);
  491.     }
  492.   } while ((result != RET_SUCCESS) && (retry < MAX_WAIT_RETURN_RETRY));
  493.   if (result < 0) 
  494.     ERROR_RETURN("Error executing STOP SCAN command (timeout).\n");
  495.  
  496. #if (DEBUG)
  497.   DEBUG_MSG("stop_scan() done.");
  498. #endif
  499.   return(RET_SUCCESS);
  500. }
  501.  
  502.  
  503. /*------------------------------------------------------------------------*/
  504. int get_scan_status (int *busy, int *lw, int *rmg) {
  505.   scsi_6byte_cmd GET_SCAN_STATUS = { 0x0f, 0x00, 0x00, 0x00, 0x06, 0x00 };
  506.   unsigned char status_reply[6];
  507.   int retry = 0;
  508.  
  509. #if (DEBUG)
  510.   DEBUG_MSG("get_scan_status() called.");
  511. #endif
  512.  
  513.   do {
  514.     if (scsi_handle_cmd(GET_SCAN_STATUS, 6, NULL, 0, status_reply, 6)
  515.         != RET_SUCCESS) {
  516.       check_sense(scsi_sensebuffer);
  517.       ERROR_RETURN("Error executing GET SCAN STATUS command.\n");
  518.     }
  519.     *busy = (int)(status_reply[0] != 0);
  520.     *lw   = (int)(status_reply[1] 
  521.             +       256 * status_reply[2]);
  522.     *rmg  = (int)(status_reply[3] 
  523.             +       256 * status_reply[4] 
  524.             + 256 * 256 * status_reply[5]);
  525.     if (*busy) {
  526.       retry++;
  527.       fprintf(stderr, "%s: Scanner is busy, retrying (%d)...\n",
  528.               myname, retry);
  529.       sleep(BUSY_SLEEP_TIME);
  530.     }
  531.   } while ((*busy) && (retry < MAX_BUSY_RETRY));
  532.   if (*busy)
  533.     ERROR_RETURN("Maximum retry reached - aborting.\n");
  534.  
  535. #if (DEBUG)
  536.   DEBUG_MSG("get_scan_status() done.");
  537. #endif
  538.   return(RET_SUCCESS);
  539. }
  540.  
  541.  
  542. /*------------------------------------------------------------------------*/
  543. int read_scanned_data (int nlines, unsigned char *buffer, int bsize) {
  544.   scsi_6byte_cmd READ_SCANNED_DATA = { 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 };
  545.  
  546. #if (DEBUG)
  547.   DEBUG_MSG("read_scanned_data() called.");
  548. #endif
  549.  
  550.   READ_SCANNED_DATA[2] = (unsigned char)((nlines & 0xff0000) >> 16);
  551.   READ_SCANNED_DATA[3] = (unsigned char)((nlines & 0xff00) >> 8);
  552.   READ_SCANNED_DATA[4] = (unsigned char)(nlines & 0xff);
  553.   if (scsi_handle_cmd(READ_SCANNED_DATA, 6, NULL, 0, buffer, bsize)
  554.       != RET_SUCCESS) {
  555.     check_sense(scsi_sensebuffer);
  556.     ERROR_RETURN("Error executing READ SCANNED DATA command for %d lines.\n",
  557.                  nlines);
  558.   }
  559.  
  560. #if (DEBUG)
  561.   DEBUG_MSG("read_scanned_data() done.");
  562. #endif
  563.   return(RET_SUCCESS);
  564. }
  565.  
  566.  
  567. /*------------------------------------------------------------------------*/
  568. /* int lut_download (char filter, char *gtable, int gt_entries)           */
  569. /* Issue the LOOK-UP-TABLE DOWNLOAD command to the scanner to download    */
  570. /* the gamma table pointed to by <gtable>. <filter> determines the color  */
  571. /* to which the table applies (RED, GREEN, BLUE, or CLEAR; values other   */
  572. /* than CLEAR may only be specified for one-pass color scanners). The     */
  573. /* number of entries is determined by <entries> (256, 1024, 4096 or       */
  574. /* 65536). The entry width is automatically assumed to be one byte if the */
  575. /* number of entries is 256 and two bytes otherwise.                      */
  576. /*------------------------------------------------------------------------*/
  577. int lut_download (char filter, char *gtable, int entries) {
  578.   scsi_10byte_cmd LUT_DOWNLOAD = { 0x55, 0x00, 0x27, 0x00, 0x00,
  579.                                    0x00, 0x00, 0x00, 0x00, 0x00 };
  580.   int transfer_length;
  581.  
  582. #if (DEBUG)
  583.   DEBUG_MSG("lut_download() called.");
  584. #endif
  585.  
  586.   transfer_length = entries * ((entries > 256) ? 2 : 1);
  587.   LUT_DOWNLOAD[7] = (unsigned char)((transfer_length & 0xff00) >> 8);
  588.   LUT_DOWNLOAD[8] = (unsigned char)(transfer_length & 0xff);
  589.   if (gt_entries > 256) LUT_DOWNLOAD[9] |= 0x01;
  590.   switch (filter) {
  591.   case RED :
  592.     LUT_DOWNLOAD[9] |= 0x40;
  593.     break;
  594.   case GREEN :
  595.     LUT_DOWNLOAD[9] |= 0x80;
  596.     break;
  597.   case BLUE :
  598.     LUT_DOWNLOAD[9] |= 0xc0;
  599.     break;
  600.   case CLEAR :
  601.   default :
  602.   }
  603.   if (scsi_handle_cmd(LUT_DOWNLOAD, 10, gtable, transfer_length, NULL, 0)
  604.       != RET_SUCCESS) {
  605.     check_sense(scsi_sensebuffer);
  606.     ERROR_RETURN("Error sending LOOK-UP-TABLE DOWNLOAD command.\n");
  607.   }
  608.  
  609. #if (DEBUG)
  610.   DEBUG_MSG("lut_download() done.");
  611. #endif
  612.   return(RET_SUCCESS);
  613. }
  614.  
  615.  
  616. /*------------------------------------------------------------------------*/
  617. /* void abort_scan (int s)                                                */
  618. /* When scanning starts, this is made the signal handler for SIGINT, so   */
  619. /* scanning is correctly terminated with a STOP SCAN command. Also called */
  620. /* (with s = -1) if errors occur after the START SCAN command.            */
  621. /* Args: <s>  signal number or -1 if called directly                      */
  622. /*------------------------------------------------------------------------*/
  623. void abort_scan (int s) {
  624.   free(imagebuffer);
  625.   free(xferbuffer);
  626.   stop_scan();
  627.   if (s == -1)
  628.     fprintf(stderr, "\n%s: Abort scan called.\n", myname);
  629.   else if (verbose) 
  630.     fprintf(stderr, "\n%s: Scan aborted (caught signal %d).\n", myname, s);
  631.   EXIT_CLOSE(RET_FAIL);
  632. }
  633.  
  634.  
  635. /*------------------------------------------------------------------------*/
  636. /* int scan (void)                                                        */
  637. /* Main scanning function. The 3-pass code is based on the patch I got    */
  638. /* from Warwick Allison <warwick@cs.uq.edu.au>.                           */
  639. /* Return: RET_SUCCESS if successful, RET_FAIL if not.                    */
  640. /*------------------------------------------------------------------------*/
  641. int scan (void) {
  642.   int scanner_busy, linewidth, remaining;
  643.   int bytes_per_line, header_bytes_per_line;
  644.   int total_lines, lines_read[3];
  645.   int nlines;
  646.   int planes, plane;
  647.   int passes, pass;
  648.   int i, j;
  649.   unsigned char *bptr;
  650.  
  651.   xferbuffer = (unsigned char *)malloc(scsi_memsize);
  652.   if (xferbuffer == NULL) {
  653.     perror("malloc");
  654.     ERROR_RETURN("Cannot allocate %d bytes for transfer buffer.\n",
  655.                  scsi_memsize);
  656.   }
  657.  
  658.   if (wait_unit_ready() != RET_SUCCESS)
  659.     ERROR_RETURN("TEST UNIT READY failed.\n");
  660.  
  661.   lines_read[0] = lines_read[1] = lines_read[2] = 0;
  662.   contrast = (contrast_adjust / 7) + 7;
  663.   exposure = (exposure_time_adjust / 3) + 7;
  664. #if (USE_FCP)
  665.   if (prescan && mt_FastColorPrescan) fast_color_prescan = 1;
  666.   else fast_color_prescan = 0;
  667. #else
  668.   fast_color_prescan = 0;
  669. #endif
  670.   if ((scan_type == COLOR) || (scan_type == GRAYSCALE)) multi_bit_scan = 1;
  671.   else multi_bit_scan = 0;
  672. #if (FORCE_3PASS)
  673.   mt_OnePass = 0;
  674. #endif
  675.   if (scan_type == COLOR) {
  676.     if (mt_OnePass) {
  677.       one_pass_color_scan = 1;
  678.       passes = 1;
  679.     }
  680.     else {
  681.       one_pass_color_scan = 0;
  682.       passes = 3;
  683.     }
  684.   }
  685.   else {
  686.     one_pass_color_scan = 0;
  687.     passes = 1;
  688.   }
  689.  
  690.   if (mt_MODE_SELECT_1) {
  691.     if (mode_select_1() != RET_SUCCESS) return(RET_FAIL);
  692.     if (mode_sense_1()  != RET_SUCCESS) return(RET_FAIL);
  693.   }
  694.  
  695.   if (mt_SWslct)
  696.     if (accessory_and_backtracking() != RET_SUCCESS) return(RET_FAIL);
  697.  
  698.   if (mode_sense() != RET_SUCCESS) return(RET_FAIL);
  699.  
  700.   if (verbose) {
  701.     fprintf(stderr, "%s: Scan settings\n", myname);
  702.     fprintf(stderr, "  frame: %2.2f, %2.2f to %2.2f, %2.2f %s, %d dpi, "
  703.             "paper length %2.2f %s\n",
  704.             scan_frame_x1, scan_frame_y1,
  705.             scan_frame_x2, scan_frame_y2, unit_string[src_unit],
  706.             scan_resolution,
  707.             (paper_length<0) ? doc_max_y : paper_length, unit_string[src_unit]);
  708.     fprintf(stderr, "  exposure time %d%%, contrast %d%%\n",
  709.             (exposure - 7) * 3, (contrast - 7) * 7);
  710.     fprintf(stderr, "  brightness adjustment: red 0x%02x, green 0x%02x, "
  711.             "blue 0x%02x\n",
  712.             (unsigned char)brightness_adjust_r,
  713.             (unsigned char)brightness_adjust_g,
  714.             (unsigned char)brightness_adjust_b);
  715.     fprintf(stderr, "  black: 0x%02x  gray: 0x%02x  white: 0x%02x\n",
  716.             shadow_adjust, midtone_adjust, highlight_adjust);
  717.     if (gammatable_filename != NULL)
  718.       fprintf(stderr, "  gamma: <%s>\n", gammatable_filename);
  719.     else
  720.       fprintf(stderr, "  gamma: red %.2f, green %.2f, blue %.2f\n",
  721.               red_gamma, green_gamma, blue_gamma);
  722.     if (scan_type == HALFTONE) 
  723.       fprintf(stderr, "  halftone pattern 0x%02x\n", halftone_pattern);
  724.     fprintf(stderr, "  writing to %s\n", output_filename ? output_filename :
  725.             "stdout");
  726.   }
  727.  
  728.   for (pass = 0; pass < passes; pass++) {
  729.     if (scanning_frame(scan_frame_x1, scan_frame_y1, 
  730.                        scan_frame_x2, scan_frame_y2) != RET_SUCCESS)
  731.        return(RET_FAIL);
  732.  
  733.     if (mt_MaxLookupTableSize) {          /* download gamma table */
  734.       if (verbose)
  735.         fprintf(stderr,"%s: Downloading gamma table...\n", myname);
  736.       if (one_pass_color_scan) {
  737.         lut_download(RED, gt_r, gt_entries);
  738.         lut_download(GREEN, gt_g, gt_entries);
  739.         lut_download(BLUE, gt_b, gt_entries);
  740.       }
  741.       else {
  742.         switch (pass) {
  743.         case 1 :
  744.           lut_download(CLEAR, gt_g, gt_entries);
  745.           break;
  746.         case 2 :
  747.           lut_download(CLEAR, gt_b, gt_entries);
  748.           break;
  749.         case 0 :
  750.         default :
  751.           lut_download(CLEAR, gt_r, gt_entries);
  752.           break;
  753.         }
  754.       }
  755.     }
  756.     if (mode_select() != RET_SUCCESS) return(RET_FAIL);
  757.     if (mode_sense()  != RET_SUCCESS) return(RET_FAIL);
  758.  
  759.     if ((verbose) && (allow_calibration)) {
  760.       if (passes == 1) fprintf(stderr, "%s: Calibrating scanner...\n", myname);
  761.       else fprintf(stderr, "%s: Calibrating %s...\n", myname, 
  762.                    (pass == 0) ? "red" : ((pass == 1) ? "green" : "blue"));
  763.     }
  764.  
  765.     signal(SIGINT, abort_scan);
  766.     signal(SIGSEGV, abort_scan);
  767.    
  768.     if (passes == 3) {
  769.       if (start_scan((pass == 0) ? RED : ((pass == 1) ? GREEN : BLUE))
  770.           != RET_SUCCESS)
  771.         return(RET_FAIL);
  772.     }
  773.     else if (start_scan(CLEAR) != RET_SUCCESS) return(RET_FAIL);
  774.  
  775.     if (get_scan_status(&scanner_busy, &linewidth, &remaining) < 0)
  776.       abort_scan(-1);
  777.  
  778. /* Some strange errors can only be detected by this check */
  779.     if (linewidth <= 0) {
  780.       fprintf(stderr, "%s: Scanner returned suspicious line width value %d.\n",
  781.               myname, linewidth);
  782.       abort_scan(-1);
  783.     }
  784.  
  785.     switch (scan_type) {
  786.     case LINEART :
  787.     case HALFTONE :
  788.       bytes_per_line = linewidth;
  789.       header_bytes_per_line = 0;
  790.       image_width = bytes_per_line * 8;
  791.       planes = 1;
  792.       break;
  793.     case GRAYSCALE :
  794.       if (bits_per_color < 8) {
  795.         bytes_per_line = linewidth;
  796.         image_width = linewidth * (8 / bits_per_color);
  797.       }
  798.       else {
  799.         bytes_per_line = ((bits_per_color + 7) / 8) * linewidth;
  800.         image_width = linewidth;
  801.       }
  802.       header_bytes_per_line = 0;
  803.       planes = 1;
  804.       break;
  805.     case COLOR :
  806.       switch (mt_ColorDataSequencing) {
  807.       case 0x00 :
  808.         header_bytes_per_line = 0;
  809.         bytes_per_line = ((bits_per_color + 7) / 8) * linewidth;
  810.         image_width = linewidth;
  811.         planes = 1;
  812.         break;
  813.       case 0x03 :
  814.         header_bytes_per_line = 6;
  815.         bytes_per_line = ((bits_per_color + 7) / 8) * 3 * (linewidth - 2);
  816.         image_width = linewidth - 2;
  817.         planes = 3;
  818.         break;
  819.       default :
  820.         header_bytes_per_line = 0;
  821.         bytes_per_line = ((bits_per_color + 7) / 8) * 3 * linewidth;
  822.         image_width = linewidth;
  823.         planes = 3;
  824.       }
  825.       break;
  826.     default :
  827.       fprintf(stderr, "%s: Unknown scan type (%d).\n", myname, scan_type);
  828.       abort_scan(-1);
  829.       return(RET_FAIL);
  830.     }
  831.  
  832. #if (FORCE_3PASS)
  833.     header_bytes_per_line = 0;
  834.     bytes_per_line = ((bits_per_color + 7) / 8) * linewidth;
  835.     image_width = linewidth;
  836.     planes = 1;
  837. #endif
  838.  
  839.     image_height = remaining;
  840.     if (verbose) {
  841.       fprintf(stderr, "%s: %s %s image, %dx%d pixel\n",
  842.               myname, prescan ? "Previewing" : "Scanning",
  843.               (scan_type == COLOR) ? ((passes == 1) ? "color" : 
  844.               ((pass == 0) ? "red" : ((pass == 1) ? "green" : "blue"))) :
  845.               ((scan_type == GRAYSCALE) ? "grayscale" : 
  846.               ((scan_type == HALFTONE) ? "halftone" : "line art")),
  847.               image_width, image_height);
  848.     }
  849.  
  850.     if (pass == 0) {
  851.       ibufsize = bytes_per_line * remaining * passes;
  852.       imagebuffer = (unsigned char *)malloc(ibufsize);
  853.       if (imagebuffer == NULL) {
  854.         perror("malloc");
  855.         fprintf(stderr, "%s: Cannot allocate %d bytes for image buffer.\n",
  856.                 myname, ibufsize);
  857.         abort_scan(-1);
  858.       }
  859.     }
  860.     total_lines = remaining;
  861.     if (verbose) {
  862.       fprintf(stderr, "%s: Remaining lines: %04d", myname, remaining);
  863.       fflush(stderr);
  864.     }
  865.  
  866.     while (lines_read[0]+lines_read[1]+lines_read[2] < 
  867.            total_lines * planes * (pass + 1)) {
  868.       if (get_scan_status(&scanner_busy, &linewidth, &remaining) < 0)
  869.         abort_scan(-1);
  870.       nlines = remaining;
  871.       if (nlines * (bytes_per_line + header_bytes_per_line) > scsi_memsize) {
  872.         nlines = scsi_memsize / (bytes_per_line + header_bytes_per_line);
  873. /* Error check suggested by Itai Nahshon <nahshon@almaden.ibm.com> */
  874.         if (nlines < 1) {
  875.           fprintf(stderr, "%s: SCSI buffer can not hold single line "
  876.                           "of scanned data.\n", myname);
  877.           abort_scan(-1);
  878.         }
  879.       }
  880.       if (read_scanned_data(nlines, xferbuffer, 
  881.           (bytes_per_line + header_bytes_per_line) * nlines) < 0)
  882.         abort_scan(-1);
  883.       if (verbose) {
  884.         fprintf(stderr, "\b\b\b\b%04d", remaining-nlines);
  885.         fflush(stderr);
  886.       }
  887.  
  888.       if ((scan_type == COLOR) && (one_pass_color_scan)) {
  889.         bptr = xferbuffer;
  890.         for (i = 0; i < nlines; i++) {
  891.           for (j = 0; j < planes; j++) {
  892.             if (header_bytes_per_line) {
  893.               bptr++;
  894.               plane = (bptr[0] == 'R') ? 0 : ((bptr[0] == 'G') ? 1 : 2);
  895.               bptr++;
  896.             }
  897.             else plane = j;
  898.             memcpy(imagebuffer + (plane * image_width * image_height) + 
  899.                    (lines_read[plane] * bytes_per_line / planes), bptr, 
  900.                    bytes_per_line / 3);
  901.             bptr += bytes_per_line / 3;
  902.             lines_read[plane]++;
  903.           }
  904.         }
  905.       }
  906.       else if ((fast_color_prescan) && (pass == 1)) {
  907.         for (i = 0; i < nlines; i++) {
  908.           lines_read[0]++;
  909.           memcpy(imagebuffer + (2 * bytes_per_line * image_height) -
  910.                  (lines_read[0] * bytes_per_line), xferbuffer +
  911.                  (i * bytes_per_line), bytes_per_line);
  912.         }
  913.       }
  914.       else {
  915.         memcpy(imagebuffer + (lines_read[0] * bytes_per_line), xferbuffer, 
  916.                nlines * bytes_per_line);
  917.         lines_read[0] += nlines;
  918.       }
  919.     } /* end of read loop */
  920.     if (verbose) fprintf(stderr, "\n");
  921.     if (stop_scan() != RET_SUCCESS) return(RET_FAIL);
  922.   } /* end of pass loop */
  923.   signal(SIGINT, SIG_DFL);
  924.   signal(SIGSEGV, SIG_DFL);
  925.   free(xferbuffer);
  926.   return(RET_SUCCESS);
  927. }
  928.  
  929.  
  930. /*------------------------------------------------------------------------*/
  931. /* int open_output_file (void)                                            */
  932. /* Tries to open the output file specified by <output_filename> and sets  */
  933. /* <output_file> to the file pointer. If <output_filename> is NULL,       */
  934. /* <output_file> is set to stdout.                                        */
  935. /* Return: 0 if successful, -1 if file could not be opened.               */
  936. /*------------------------------------------------------------------------*/
  937. int open_output_file (void) {
  938.   if (output_filename == NULL) {
  939.     output_file = stdout;
  940.     return(RET_SUCCESS);
  941.   }
  942. #ifndef __EMX__
  943. #define WRTMODE "w"
  944. #else    /* OS/2 */
  945. #define WRTMODE "wb"
  946. #endif
  947.   if ((output_file = fopen(output_filename, WRTMODE)) == NULL) {
  948.     perror(myname);
  949.     return(RET_FAIL);
  950.   }
  951.   return(RET_SUCCESS);
  952. }
  953.  
  954.  
  955. /*------------------------------------------------------------------------*/
  956. /* void write_image (int raw)                                             */
  957. /* Writes the image file to <output_file> in pbm/pgm/ppm format (depen-   */
  958. /* ding on the value of <scan_type>).                                     */
  959. /* Includes some changes submitted by Wolfgang Wander <wwc@lars.desy.de>  */
  960. /* to speed up writing of data.                                           */
  961. /* Args: <raw>  If this is nonzero, the image is written in pbm/pgm/ppm   */
  962. /*              raw format (smaller, faster, better) if possible.         */
  963. /*              Otherwise the longer, but more generic standard ASCII     */
  964. /*              format is written.                                        */
  965. /* Note: Raw format cannot be used if the maximum value for a color       */
  966. /*       component is larger than 255, i.e. in 10 or 12 bpp images.       */
  967. /*------------------------------------------------------------------------*/
  968. void write_image (int raw) {
  969.   int i, j;
  970.   unsigned char mask;
  971.   char wbuf[3];
  972.   char magic_number[3] = { 'P', '0', 0 };
  973.  
  974.   switch (scan_type) {
  975.   case LINEART :
  976.   case HALFTONE :
  977.     magic_number[1] = (raw ? '4' : '1');  break;
  978.   case GRAYSCALE :
  979.     magic_number[1] = (raw ? '5' : '2');  break;
  980.   case COLOR :
  981.     magic_number[1] = (raw ? '6' : '3');  break;
  982.   }
  983.   fprintf(output_file, "%s\n# Created with mtekscan v.%s\n%d %d\n",
  984.           magic_number, VERSION,  image_width, image_height);
  985.   if ((scan_type == GRAYSCALE) || (scan_type == COLOR))
  986.     fprintf(output_file, "255\n");
  987.   if (scan_type == GRAYSCALE) {
  988.     for (i = 0; i < image_width * image_height; i++) {
  989.       if (raw)
  990.         fputc(imagebuffer[i], output_file);
  991.       else
  992.         fprintf(output_file, "%d%s", imagebuffer[i], (i%16==15) ? "\n" : " ");
  993.     }
  994.   }
  995.   else if (scan_type == COLOR) {
  996.     for (i = 0; i < image_width * image_height; i++) {
  997.       if (raw) {
  998.         for (j = 0; j < 3; j++) 
  999.           wbuf[j] = imagebuffer[i + image_width * image_height * j];
  1000.         fwrite(wbuf, 3, 1, output_file);
  1001.       }
  1002.       else {
  1003.         fprintf(output_file, "%d %d %d%s", imagebuffer[i], 
  1004.                 imagebuffer[i + image_width * image_height],
  1005.                 imagebuffer[i + image_width * image_height * 2],
  1006.                 (i % 6 == 5) ? "\n" : " ");
  1007.       }
  1008.     }
  1009.   }
  1010.   else {
  1011.     if (raw)
  1012.       for (i = 0; i < ibufsize; i++)
  1013.         fputc(imagebuffer[i], output_file);
  1014.     else {
  1015.       mask = 0x80;
  1016.       j = 0;
  1017.       for (i = 0; i < image_width * image_height; i++) {
  1018.         fprintf(output_file, "%d%s", (imagebuffer[j] & mask) ? 1 : 0,
  1019.                 (i % 30 == 29) ? "\n" : " ");
  1020.         mask = mask >> 1;
  1021.         if (mask == 0x00) {
  1022.           mask = 0x80;
  1023.           j++;
  1024.         }
  1025.       }
  1026.     }
  1027.   }
  1028.   fprintf(output_file, "\n");
  1029. }
  1030.  
  1031.  
  1032.  
  1033. /**************************************************************************/
  1034.  
  1035. /**********************           M A I N           ***********************/
  1036.  
  1037. /**************************************************************************/
  1038. int main (int argc, char **argv) {
  1039.   int result;
  1040.  
  1041.   myname = strrchr(argv[0], '/');
  1042.   if (myname == NULL) myname = argv[0];
  1043.   else myname++;
  1044.  
  1045.   scsi_debug_level = SCSI_DEBUGLEVEL;
  1046. #ifndef __EMX__
  1047.   scsi_device = (char *)malloc(strlen(DEFAULT_DEVICE)+1);
  1048.   strcpy(scsi_device, DEFAULT_DEVICE);
  1049. #else    /* OS/2 */
  1050.   if (argc > 1 && isdigit(argv[1][0])) {    // Get SCSI ID of scanner.
  1051.      scsi_device = (char *)malloc(strlen(argv[1]) + 1);
  1052.      strcpy(scsi_device, argv[1]);
  1053.   } else {
  1054.      usage();
  1055.      exit(RET_FAIL);
  1056.   }
  1057. #endif
  1058.   if (scsi_open_device() == RET_FAIL)
  1059.     ERROR_RETURN("Unable to open SCSI device.\n");
  1060.  
  1061. #ifndef __EMX__
  1062.   result = checkopt(argc, argv);
  1063. #else    /* OS/2 */
  1064.   result = checkopt(argc - 1, argv + 1);    // 1st opt. is scsi ID.
  1065. #endif
  1066.   if (result != RET_SUCCESS) {
  1067.     if (-result >= argc)
  1068.       ERROR_RETURN("Missing or invalid option(s).\n  Use %s -h for a list "
  1069.                    "of valid options.\n", myname);
  1070.     ERROR_RETURN("Illegal option '%s'.\n  Use %s -h for a list "
  1071.                  "of valid options.\n", argv[-result], myname);
  1072.   }
  1073.  
  1074.   if (open_output_file() != RET_SUCCESS)
  1075.     ERROR_RETURN("Unable to open output file '%s'.\n", output_filename);
  1076.   if (get_scanner_info() != RET_SUCCESS)
  1077.     ERROR_RETURN("Unable to get scanner info.\n");
  1078.  
  1079.   if (perform_selftest) {
  1080.     if (wait_unit_ready() != RET_SUCCESS) EXIT_CLOSE(RET_FAIL);
  1081.     if (selftest() != RET_SUCCESS) EXIT_CLOSE(RET_FAIL);
  1082.     EXIT_CLOSE(RET_SUCCESS);
  1083.   }
  1084.  
  1085.   if (gammatable_filename != NULL) {
  1086.     if (verbose)
  1087.       fprintf(stderr, "%s: Loading gamma tables from %s...\n", myname,
  1088.               gammatable_filename);
  1089.     if (read_gamma_tables(gammatable_filename) != RET_SUCCESS) {
  1090.       fprintf(stderr, "%s: Failed reading gamma tables from %s.\n",
  1091.               myname, gammatable_filename);
  1092.       EXIT_CLOSE(RET_FAIL);
  1093.     }
  1094.   }
  1095.   else {
  1096.     init_gamma_tables(mt_MaxLookupTableSize);
  1097.     create_gamma_table(gt_r, red_gamma);
  1098.     create_gamma_table(gt_g, green_gamma);
  1099.     create_gamma_table(gt_b, blue_gamma);
  1100.   }
  1101.  
  1102. #if (INVERT_USING_GAMMA)
  1103.   if (reverse_colors) {
  1104.     invert_gamma_table(gt_r);
  1105.     invert_gamma_table(gt_g);
  1106.     invert_gamma_table(gt_b);
  1107.     reverse_colors = 0;
  1108.   }
  1109. #endif
  1110.  
  1111. #if (WRITE_GAMMA)
  1112.   write_gamma_tables("mtekscan.gt");
  1113. #endif
  1114.  
  1115.   if (test_options() != RET_SUCCESS) EXIT_CLOSE(RET_FAIL);
  1116.   if (scan() != RET_SUCCESS) EXIT_CLOSE(RET_FAIL);
  1117.   free_gamma_tables();
  1118.   write_image(WRITE_RAW);
  1119.   free(imagebuffer);
  1120.   scsi_close_device();
  1121.   return(RET_SUCCESS);
  1122. }
  1123.