Exemple #1
0
extern int setDefaultScannerOption(SANE_Handle *devHandle, const SANE_Option_Descriptor *sod, int option ) {
  if ( sod->cap & SANE_CAP_AUTOMATIC ) {
    int paramSetRet;
    int status = control_option (devHandle, sod, option, SANE_ACTION_SET_AUTO, NULL, &paramSetRet);
    if(status == SANE_STATUS_GOOD) {
      handleSaneErrors("Cannot set automatically", status, paramSetRet);
      //updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
      return 1;
    }
  }
  return 0;
}
Exemple #2
0
char *internalDoScanningOperation(char *uuid, char *lang) {

  int request_resolution = 0;
  int docid;
  int current_page = 0;
  int total_requested_pages;
  double totbytes = 0;
  SANE_Status status;
  SANE_Handle *openDeviceHandle;
  SANE_Byte *raw_image;
  SANE_Parameters pars;
  char *docid_s;
  char *total_requested_pages_s;
  char *devName;
  char *outFilename;
  char *raw_image_format;
  char *header;

  o_log(DEBUGM, "doScanningOperation: sane initialized uuid(%s)",(char *)uuid);
  updateScanProgress(uuid, SCAN_WAITING_ON_SCANNER, 0);

  // Open the device
  devName = getScanParam(uuid, SCAN_PARAM_DEVNAME);
  o_log(DEBUGM, "sane_open of \"%s\"",devName);
  status = sane_open ((SANE_String_Const) devName, (SANE_Handle)&openDeviceHandle);
  if(status != SANE_STATUS_GOOD) {
    handleSaneErrors("Cannot open device ", devName, status, 0);
    updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
    free(devName);
    return 0;
  }
  free(devName);

  /* ========================================================== */
  if ( ! setOptions( (char *)uuid, openDeviceHandle, &request_resolution ) )
    return 0;
  o_log(DEBUGM, "sane_start: setOptions returned request_resolution %d\n",request_resolution);

  int timeout = 5;
  while( 0 < timeout ) {
    status = sane_start (openDeviceHandle);
    if(status == SANE_STATUS_GOOD) {  
      break;
    }
    else {
      if(status == SANE_STATUS_DEVICE_BUSY ) {  
        // BUSY signal could be the scanner just having a 
        // bit of lag - specially network connected devices
        timeout--;
        if ( timeout == 0 ) {
          handleSaneErrors("Cannot start scanning", "even after trying several time", status, 0);
          updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
          return 0;
        }
        else {
          o_log(WARNING, "Device reports not ready to 'start', waiting 500ms. Will try another %d times", timeout);
          usleep(500 * 1000); // 500ms or 0.5sec
        }
      }
      else {
        handleSaneErrors("Cannot start scanning", "", status, 0);
        updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
        return 0;
      }
    }
  }

  // Get scanning params (from the scanner)
  if( request_resolution == 0 ) {
    o_log(DEBUGM, "Resolution did not get set in scanner setup.");
    updateScanProgress(uuid, SCAN_INTERNAL_ERROR, 10004);
    return 0;
  }

  o_log(DEBUGM, "Get scanning params");
  status = sane_get_parameters (openDeviceHandle, &pars);
  o_log(INFORMATION, "Scanner Parm : stat=%s form=%d,lf=%d,bpl=%d,pixpl=%d,lin=%d,dep=%d",
    sane_strstatus (status),
    pars.format, pars.last_frame,
    pars.bytes_per_line, pars.pixels_per_line,
    pars.lines, pars.depth);

  switch (pars.format) {
    case SANE_FRAME_GRAY:
      o_log(DEBUGM, "Expecting Gray data (1 channel only).");
      raw_image_format = o_strdup( "P5" );
      break;
    case SANE_FRAME_RGB:
      o_log(DEBUGM, "Expecting RGB data (3 channels).");
      raw_image_format = o_strdup( "P6" );
      break;
    default:
      o_log(DEBUGM, "backend returns three frames speratly. We do not currently support this.");
      updateScanProgress(uuid, SCAN_INTERNAL_ERROR, 10003);
      return 0;
      break;
  }
  
  header = o_printf ("%s\n# SANE data follows\n%d %d\n%d\n", 
    raw_image_format, pars.pixels_per_line, pars.lines,
    (pars.depth <= 8) ? 255 : 65535);
  free( raw_image_format );


  // Save Record
  //
  docid_s = getScanParam(uuid, SCAN_PARAM_DOCID);
  total_requested_pages_s = getScanParam(uuid, SCAN_PARAM_REQUESTED_PAGES);
  total_requested_pages = atoi(total_requested_pages_s);
  free(total_requested_pages_s);
  if( docid_s == NULL ) {
    o_log(DEBUGM, "Saving record");
    updateScanProgress(uuid, SCAN_DB_WORKING, 0);

    docid_s = addNewScannedDoc(pars.lines, pars.pixels_per_line, request_resolution, total_requested_pages); 
    setScanParam(uuid, SCAN_PARAM_DOCID, docid_s);
    setScanParam(uuid, SCAN_PARAM_ON_PAGE, "1");
    current_page = 1;
  }
  else {
    char *current_page_s = getScanParam(uuid, SCAN_PARAM_ON_PAGE);
    current_page = atoi(current_page_s);
    free(current_page_s);

    current_page++;

    current_page_s = itoa(current_page, 10);
    setScanParam(uuid, SCAN_PARAM_ON_PAGE, current_page_s);
    free(current_page_s);
  }
  docid = atoi(docid_s);
  free(docid_s);

  totbytes = (double)((pars.bytes_per_line * pars.lines));

  /* ========================================================== */
  raw_image = collectData( (char *)uuid, openDeviceHandle, totbytes, pars.bytes_per_line, header );
  o_log(INFORMATION, "Scanning done.");

  o_log(DEBUGM, "sane_cancel");
  sane_cancel(openDeviceHandle);

  o_log(DEBUGM, "sane_close");
  sane_close(openDeviceHandle);


  // Convert Raw into JPEG
  //
  updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 0);
  PIX *pix;
  if ( ( pix = pixReadMem( raw_image, (pars.bytes_per_line*pars.lines)+strlen(header) ) ) == NULL) {
    o_log(ERROR, "Could not load the image data into a PIX");
  }
  updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 55);
  o_log(INFORMATION, "Convertion process: Loaded (depth: %d)", pixGetDepth(pix));
  free(raw_image);
  free(header);

  outFilename = o_printf("%s/scans/%d_%d.jpg", BASE_DIR, docid, current_page);
  pixWrite(outFilename, pix, IFF_JFIF_JPEG);
  free(outFilename);
  updateScanProgress(uuid, SCAN_CONVERTING_FORMAT, 100);
  o_log(INFORMATION, "Conversion process: Complete");




  // Do OCR - on this page
  // - OCR libs just wants the raw data and not the image header
  ocrImage( uuid, docid, current_page, request_resolution, pix, lang );


#ifdef CAN_PHASH
  // Calulate the pHash, so we can compare images later
  if( current_page == 1 ) {
    updateScanProgress(uuid, SCAN_CALULATING_PHASH, 0);
    unsigned long long hash = getImagePhash_px( pix );
    savePhash( docid, hash );
  }
#endif /* CAN_PHASH */
  pixDestroy( &pix );


  // cleaup && What should we do next
  //
  o_log(DEBUGM, "mostly done.");
  if(current_page >= total_requested_pages)
    updateScanProgress(uuid, SCAN_FINISHED, docid);
  else
    updateScanProgress(uuid, SCAN_WAITING_ON_NEW_PAGE, ++current_page);

  o_log(DEBUGM, "Page scan done.");

  return o_strdup("OK"); 
}
Exemple #3
0
int setOptions( char *uuid, SANE_Handle *openDeviceHandle, int *request_resolution ) {

  int option = 0;
  SANE_Status status;
  SANE_Fixed v_f;
  SANE_Int v_i;
  SANE_Bool v_b;
  char *v_c;
  //const char *modes[] = { SANE_VALUE_SCAN_MODE_COLOR, SANE_VALUE_SCAN_MODE_GRAY, "Grayscale", NULL };
  const char *modes_colour[] = { SANE_VALUE_SCAN_MODE_COLOR, "Color", SANE_VALUE_SCAN_MODE_GRAY, "Grayscale", NULL };
  const char *modes_gray[] = { SANE_VALUE_SCAN_MODE_GRAY, "Grayscale", NULL };
  const char *speeds[] = { "Auto", "Normal", "Fast", NULL };
  const char *compression[] = { "None", NULL };
  const char *sources[] = { "Auto", SANE_I18N ("Auto"), "Flatbed", SANE_I18N ("Flatbed"), 
                            "FlatBed", "Normal", SANE_I18N ("Normal"), NULL };

  int testScanner = 0;
  char *devName = getScanParam(uuid, SCAN_PARAM_DEVNAME);
  if ( strstr(devName, "test") != 0 ) {
    testScanner = 1;
  }
  free(devName);


  for (option = 0; option < 9999; option++) {

    const SANE_Option_Descriptor *sod = sane_get_option_descriptor (openDeviceHandle, option);

    // No more options    
    if (sod == NULL)
      break;

    // Just a placeholder
    if (sod->type == SANE_TYPE_GROUP
    || sod->name == NULL
    || option == 0)
      continue;

    log_option( option, sod );

    // Validation
    if ( (sod->cap & SANE_CAP_SOFT_SELECT) && (sod->cap & SANE_CAP_HARD_SELECT) ) {
      o_log(DEBUGM, "The backend said that '%s' is both hardward and software settable! Err", sod->name);
      updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, 0);
      return 0;
    }

    // we MUST set this value
    if ( (sod->cap & SANE_CAP_SOFT_DETECT) && ((sod->cap & SANE_CAP_INACTIVE) == 0) ) {

      // A hardware setting
      if ( sod->cap & SANE_CAP_HARD_SELECT ) {
        o_log(DEBUGM, "We've got no way of telling the user to set the hardward %s! Err", sod->name);
      }

      // a software setting
      else {

        int paramSetRet = 0;

        // Set scanning Source
        if ( strcmp(sod->name, SANE_NAME_SCAN_SOURCE) == 0 ) {
          if ( !setDefaultScannerOption(openDeviceHandle, sod, option, &paramSetRet) ) {
            int i, j; 
            int foundMatch = 0;
            for (i = 0; sources[i] != NULL; i++) {
              for (j = 0; sod->constraint.string_list[j]; j++) {
                if (strcmp (sources[i], sod->constraint.string_list[j]) == 0)
                  break;
              }
              if (sod->constraint.string_list[j] != NULL) {
                v_c = o_strdup(sources[i]);
                status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, &paramSetRet);
                free(v_c);
                foundMatch = 1;
                break;
              }
            }
            if( foundMatch == 0 ) {
              o_log(DEBUGM, "Non of the available options are appropriate.");
            }
          }
        }

        // Set scanning mode
        else if ( strcmp(sod->name, SANE_NAME_SCAN_MODE ) == 0 ) {
          const char **modes;
          char *requested_mode = getScanParam(uuid, SCAN_PARAM_FORMAT );
          if( 0 == strcmp( "colour", requested_mode ) ) {
            modes = modes_colour;
          }
          else {
            modes = modes_gray;
          }
          free( requested_mode );
          int i, j; 
          int foundMatch = 0;
          for (i = 0; modes[i] != NULL; i++) {
            for (j = 0; sod->constraint.string_list[j]; j++) {
              if (strcmp (modes[i], sod->constraint.string_list[j]) == 0)
                break;
            }
            if (sod->constraint.string_list[j] != NULL) {
              v_c = o_strdup(modes[i]);
              status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, &paramSetRet);
              free(v_c);
              foundMatch = 1;
              break;
            }
          }
          if( foundMatch == 0 ) {
            o_log(DEBUGM, "Non of the available options are appropriate.");
          }
        }

        else if ( strcmp(sod->name, "batch-scan" ) == 0 ) {
          v_b = SANE_FALSE;
          status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
        }

        else if ( strcmp(sod->name, "compression") == 0 ) {
            int i, j; 
            int foundMatch = 0;
            for (i = 0; compression[i] != NULL; i++) {
              for (j = 0; sod->constraint.string_list[j]; j++) {
              o_log(DEBUGM, "n list: %s", sod->constraint.string_list[j]);
                if (strcmp (compression[i], sod->constraint.string_list[j]) == 0)
                  break;
              }
              if (sod->constraint.string_list[j] != NULL) {
              o_log(DEBUGM, "Attempting to set compresstion to: %s", compression[i]);
                v_c = o_strdup(compression[i]);
                status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, &paramSetRet);
                free(v_c);
                foundMatch = 1;
                break;
              }
            }
            if( foundMatch == 0 ) {
              o_log(DEBUGM, "Non of the available options are appropriate.");
            }
        }

        // Set scanning depth
        else if ( strcmp(sod->name, SANE_NAME_BIT_DEPTH) == 0 ) {
          if ( !setDefaultScannerOption(openDeviceHandle, sod, option, &paramSetRet) ) {
            if( sod->type == SANE_TYPE_STRING ) {
              v_c = o_strdup("8");
              status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, &paramSetRet);
              free(v_c);
            }
            if (sod->type == SANE_TYPE_FIXED) {
              v_f = SANE_FIX( 8 );
              status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
            }
            else {
              v_i = 8;
              status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, &paramSetRet);
            }
          }
        }

        // Set Preview mode
        else if ( strcmp(sod->name, SANE_NAME_PREVIEW) == 0 ) {
          if ( !setDefaultScannerOption(openDeviceHandle, sod, option, &paramSetRet) ) {
            v_b = SANE_FALSE;
            status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
        }

        // Set scanning resolution
        else if ( strcmp(sod->name, SANE_NAME_SCAN_RESOLUTION) == 0 ) {

          char *request_resolution_s;

          request_resolution_s = getScanParam(uuid, SCAN_PARAM_REQUESTED_RESOLUTION);
          *request_resolution = atoi(request_resolution_s);
          free(request_resolution_s);

          if (sod->type == SANE_TYPE_FIXED) {
            v_f = SANE_FIX( *request_resolution );
            status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
          }
          else if (sod->type == SANE_TYPE_INT) {
            int sane_resolution = *request_resolution;
            status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &sane_resolution, &paramSetRet);
          }
         else {
            int sane_resolution = *request_resolution;
            if( sod->constraint.range->quant != 0 ) 
              sane_resolution = sane_resolution * sod->constraint.range->quant;
            status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &sane_resolution, &paramSetRet);
          }
        }

        else if ( strcmp(sod->name, SANE_NAME_SCAN_TL_Y) == 0 ) {
          v_f = sod->constraint.range->min;
          status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
        }

        else if ( strcmp(sod->name, SANE_NAME_SCAN_TL_X) == 0 ) {
          v_f = sod->constraint.range->min;
          status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
        }

        else if ( strcmp(sod->name, SANE_NAME_SCAN_BR_Y) == 0 ) {
          int pagelength;
          char *length_s;

          v_f = sod->constraint.range->max;
          length_s = getScanParam(uuid, SCAN_PARAM_LENGTH);
          pagelength = atoi(length_s);
          if(pagelength && pagelength >= 20 && pagelength < 100)
            v_f = SANE_FIX( ( SANE_UNFIX(v_f) * (double)pagelength) / 100);
          free(length_s);

          status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
        }

        else if ( strcmp(sod->name, SANE_NAME_SCAN_BR_X) == 0 ) {
          v_f = sod->constraint.range->max;
          status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
        }

        else if ( strcmp(sod->name, SANE_NAME_BRIGHTNESS) == 0 ) {
          v_f = 0;
          status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
        }

        else if ( strcmp(sod->name, SANE_NAME_CONTRAST) == 0 ) {
          v_f = 0;
          status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_f, &paramSetRet);
        }

        else if ( strcmp(sod->name, SANE_NAME_SCAN_SPEED) == 0) {
          if ( !setDefaultScannerOption(openDeviceHandle, sod, option, &paramSetRet) ) {
            int i, j; 
            int foundMatch = 0;
            for (i = 0; speeds[i] != NULL; i++) {
              for (j = 0; sod->constraint.string_list[j]; j++) {
                if (strcmp (speeds[i], sod->constraint.string_list[j]) == 0)
                  break;
              }
              if (sod->constraint.string_list[j] != NULL) {
                v_c = o_strdup(speeds[i]);
                status = control_option (openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, (void *)v_c, &paramSetRet);
                free(v_c);
                foundMatch = 1;
                break;
              }
            }
            if( foundMatch == 0 ) {
              o_log(DEBUGM, "Non of the available options are appropriate.");
            }
          }
        }

        else if ( strcmp(sod->name, "custom-gamma") == 0 ) {
          v_b = SANE_FALSE;
          status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
        }

        // For the test 'virtual scanner'
        else if (testScanner == 1) {

          if ( strcmp(sod->name, "hand-scanner" ) == 0 ) {
            v_b = SANE_FALSE;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
          else if ( strcmp(sod->name, "three-pass") == 0 ){
            v_b = SANE_FALSE;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
          else if ( strcmp(sod->name, "three-pass-order") == 0 ) {
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, "RGB", &paramSetRet);
          }
          else if ( strcmp(sod->name, "test-raw_imageture") == 0 ) {
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, "Color pattern", &paramSetRet);
          }
          else if ( strcmp(sod->name, "read-delay") == 0 ) {
            v_b = SANE_TRUE;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
          else if ( strcmp(sod->name, "fuzzy-parameters") == 0 ) {
            v_b = SANE_TRUE;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
          else if ( strcmp(sod->name, "read-delay-duration") == 0 ) {
            v_i = 1000;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, &paramSetRet);
          }
          else if ( strcmp(sod->name, "read-limit") == 0 ) {
            v_b = SANE_TRUE;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
          else if ( strcmp(sod->name, "read-limit-size") == 0 ) {
            v_i = sod->constraint.range->max;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, &paramSetRet);
          }
          else if ( strcmp(sod->name, "read-return-value") == 0 ) {
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, "Default", &paramSetRet);
          }
          else if ( strcmp(sod->name, "ppl-loss") == 0 ) {
            v_i = 0;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_i, &paramSetRet);
          }
          else if ( strcmp(sod->name, "invert-endianess") == 0 ) {
            v_b = SANE_FALSE;
            status = control_option(openDeviceHandle, sod, option, SANE_ACTION_SET_VALUE, &v_b, &paramSetRet);
          }
        }

        // not a 'well known' option
        else {
          // try setting automatically
          if ( !setDefaultScannerOption(openDeviceHandle, sod, option, &paramSetRet) )
            o_log(DEBUGM, "Could not set authmatically", sod->name);
        }

        if( status != SANE_STATUS_GOOD ) {
          handleSaneErrors("Cannot set no to", sod->name, status, paramSetRet);
          updateScanProgress(uuid, SCAN_ERRO_FROM_SCANNER, status);
          return 0;
        }

        if ( paramSetRet & SANE_INFO_RELOAD_OPTIONS ) {
          //start from the beginning again.
          option = 0;
        } 


      } // setable option
    }
    else {
      o_log(DEBUGM, "The option does not need to be set.");
    }

  } // options loop

  return 1;
}