Beispiel #1
0
 void KSaneScanThread::readData()
 {
     SANE_Int readBytes = 0;
     m_saneStatus = sane_read(m_saneHandle, m_readData, SCAN_READ_CHUNK_SIZE, &readBytes);
     
     switch (m_saneStatus) 
     {
         case SANE_STATUS_GOOD:
             // continue to parsing the data
             break;
             
         case SANE_STATUS_EOF:
             if (m_frameRead < m_frameSize) {
                 kDebug() << "frameRead =" << m_frameRead  << ", frameSize =" << m_frameSize << "readBytes =" << readBytes;
                 if ((readBytes > 0) && ((m_frameRead + readBytes) <= m_frameSize)) {
                     kDebug() << "This is not a standard compliant backend";
                     copyToScanData(readBytes);
                 }
                 m_readStatus = READ_READY; // It is better to return a broken image than nothing
                 return;
             }
             if (m_params.last_frame == SANE_TRUE) {
                 // this is where it all ends well :)
                 m_readStatus = READ_READY;
                 return;
             }
             else {
                 // start reading next frame
                 m_saneStatus = sane_start(m_saneHandle);
                 if (m_saneStatus != SANE_STATUS_GOOD) {
                     kDebug() << "sane_start =" << sane_strstatus(m_saneStatus);
                     m_readStatus = READ_ERROR;
                     return;
                 }
                 m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
                 if (m_saneStatus != SANE_STATUS_GOOD) {
                     kDebug() << "sane_get_parameters =" << sane_strstatus(m_saneStatus);
                     m_readStatus = READ_ERROR;
                     sane_cancel(m_saneHandle);
                     return;
                 }
                 //kDebug() << "New Frame";
                 m_frameRead = 0;
                 m_frame_t_count++;
                 break;
             }
         default:
             kDebug() << "sane_read=" << m_saneStatus << "=" << sane_strstatus(m_saneStatus);
             m_readStatus = READ_ERROR;
             sane_cancel(m_saneHandle);
             return;
     }
     
     copyToScanData(readBytes);
 }
Beispiel #2
0
void
sane_close (SANE_Handle handle)
{
  AS6E_Scan *prev, *s;
  SANE_Word repeat = 0;
  DBG (2, "sane_close\n");
  /* remove handle from list of open handles: */
  prev = 0;
  for (s = first_handle; s; s = s->next)
    {
      if (s == handle)
	break;
      prev = s;
    }
  if (!s)
    {
      DBG (1, "close: invalid handle %p\n", handle);
      return;			/* oops, not a handle we know about */
    }

  if (s->scanning)
    sane_cancel (handle);
  write (s->as6e_params.ctloutpipe, &repeat, sizeof (repeat));
  close (s->as6e_params.ctloutpipe);
  free (s->scan_buffer);
  free (s->line_buffer);
  if (prev)
    prev->next = s->next;
  else
    first_handle = s;
  free (handle);
}
Beispiel #3
0
void
sane_close (SANE_Handle handle)
{
  V4L_Scanner *prev, *s;

  DBG (2, "sane_close: trying to close handle %p\n", (void *) handle);
  /* remove handle from list of open handles: */
  prev = 0;
  for (s = first_handle; s; s = s->next)
    {
      if (s == handle)
	break;
      prev = s;
    }
  if (!s)
    {
      DBG (1, "sane_close: bad handle %p\n", handle);
      return;			/* oops, not a handle we know about */
    }
  if (prev)
    prev->next = s->next;
  else
    first_handle = s->next;

  if (s->scanning)
    sane_cancel (handle);
  v4l1_close (s->fd);
  free (s);
}
Beispiel #4
0
static PyObject *readScan (_ScanDevice * self, PyObject * args)
{
    SANE_Status st;
    SANE_Int len;
    SANE_Byte buffer[MAX_READSIZE];
    int bytes_to_read;

    if (!PyArg_ParseTuple (args, "i", &bytes_to_read))
        raiseError("Invalid arguments.");

    if (bytes_to_read > MAX_READSIZE)
        return raiseError("bytes_to_read > MAX_READSIZE");

    if (self->h == NULL)
        return raiseDeviceClosedError();

    //Py_BEGIN_ALLOW_THREADS
    Py_UNBLOCK_THREADS
    st = sane_read (self->h, buffer, bytes_to_read, &len);
    //Py_END_ALLOW_THREADS
    Py_BLOCK_THREADS

    if (st != SANE_STATUS_GOOD &&
        st != SANE_STATUS_EOF &&
        st != SANE_STATUS_NO_DOCS)
    {
        sane_cancel(self->h);
        //Py_BLOCK_THREADS
        return raiseSaneError(st);
    }

    return Py_BuildValue (FORMAT_STRING, st, buffer, len);
}
Beispiel #5
0
/*
 * Ends use of the scanner.
 * 
 * From the SANE spec:
 * This function terminates the association between the device handle
 * passed in argument h and the device it represents. If the device is
 * presently active, a call to sane_cancel() is performed first. After
 * this function returns, handle h must not be used anymore.
 */
void
sane_close (SANE_Handle handle)
{
  DBG (10, "sane_close: start\n");

  sane_cancel(handle);
  disconnect_fd((struct scanner *) handle);

  DBG (10, "sane_close: finish\n");
}
Beispiel #6
0
static void
sane_idadone(void *data)
{
    struct sane_state *h = data;

    sane_cancel(h->sane);
    sane_close(h->sane);
    sane_exit();
    free(h->buf);
    free(h);
}
Beispiel #7
0
static PyObject *cancelScan (_ScanDevice * self, PyObject * args)
{
    if (!PyArg_ParseTuple (args, ""))
        raiseError("Invalid arguments.");

    if (self->h == NULL)
        return raiseDeviceClosedError();

    sane_cancel (self->h);
    Py_INCREF (Py_None);
    return Py_None;
}
Beispiel #8
0
void
sane_close( SANE_Handle handle )
{
	ST400_Device *dev = handle;

	DBG(DCODE, "sane_close(%p)\n", handle);

	if( dev->status.open ) {
		sane_cancel(dev);
		dev->status.open = 0;
	}
}
Beispiel #9
0
/*
 * Called by SANE when a page acquisition operation is to be started.
 */
SANE_Status
sane_start (SANE_Handle handle)
{
    struct scanner *s = handle;
    SANE_Status ret;
  
    DBG (10, "sane_start: start\n");
  
    /* first page of batch */
    if(s->started){
        DBG(5,"sane_start: previous transfer not finished?");
        sane_cancel((SANE_Handle)s);
        return SANE_STATUS_CANCELLED;
    }
  
    /* set clean defaults */
    s->started=1;
    s->bytes_rx=0;
    s->bytes_tx=0;
    s->paperless_lines=0;
  
    /* heat up the lamp */ 
    if(s->mode == MODE_COLOR){
        ret = heat_lamp_color(s);
    }
    else{
        ret = heat_lamp_gray(s);
    }
  
    if (ret != SANE_STATUS_GOOD) {
        DBG (5, "sane_start: ERROR: failed to heat lamp\n");
        sane_cancel((SANE_Handle)s);
        return ret;
    }
  
    DBG (10, "sane_start: finish\n");
  
    return SANE_STATUS_GOOD;
}
Beispiel #10
0
static PyObject *
SaneDev_cancel(SaneDevObject *self, PyObject *args)
{
  if (!PyArg_ParseTuple(args, ""))
    return NULL;
  if (self->h==NULL)
    {
      PyErr_SetString(ErrorObject, "SaneDev object is closed");
      return NULL;
    }
  sane_cancel(self->h);
  Py_INCREF(Py_None);
  return Py_None;
}
Beispiel #11
0
static PyObject *
SaneDev_snap(SaneDevObject *self, PyObject *args)
{
  SANE_Status st; 
   /* The buffer should be a multiple of 3 in size, so each sane_read
      operation will return an integral number of RGB triples. */
  SANE_Byte buffer[READSIZE];  /* XXX how big should the buffer be? */
  SANE_Int len, lastlen;
  Imaging im;
  SANE_Parameters p;
  int px, py, remain, cplen, bufpos, padbytes;
  long L;
  char errmsg[80];
  union 
    { char c[2];
      INT16 i16;
    } 
  endian;
  PyObject *pyNoCancel = NULL;
  int noCancel = 0;
    
  endian.i16 = 1;
  
  if (!PyArg_ParseTuple(args, "l|O", &L, &pyNoCancel))
    return NULL;
  if (self->h==NULL)
    {
      PyErr_SetString(ErrorObject, "SaneDev object is closed");
      return NULL;
    }
  im=(Imaging)L;
  
  if (pyNoCancel)
    noCancel = PyObject_IsTrue(pyNoCancel);

  st=SANE_STATUS_GOOD; px=py=0;
  /* xxx not yet implemented
     - handscanner support (i.e., unknown image length during start)
     - generally: move the functionality from method snap in sane.py
       down here -- I don't like this cross-dependency.
       we need to call sane_get_parameters here, and we can create
       the result Image object here.
  */
  
  Py_UNBLOCK_THREADS
  sane_get_parameters(self->h, &p);
  if (p.format == SANE_FRAME_GRAY)
    {
      switch (p.depth)
        {
          case 1: 
            remain = p.bytes_per_line * im->ysize;
            padbytes = p.bytes_per_line - (im->xsize+7)/8;
            bufpos = 0;
            lastlen = len = 0;
            while (st!=SANE_STATUS_EOF && py < im->ysize)
              {
                while (len > 0 && py < im->ysize)
                  {
                    int i, j, k;
                    j = buffer[bufpos++];
                    k = 0x80;
                    for (i = 0; i < 8 && px < im->xsize; i++)
                      {
                        im->image8[py][px++] = (k&j) ? 0 : 0xFF;
                        k = k >> 1;
                      }
                    len--;
                    if (px >= im->xsize)
                      {
                        bufpos += padbytes;
                        len -= padbytes;
                        py++;
                        px = 0;
                      }
                  }
                st=sane_read(self->h, buffer, 
                             remain<READSIZE ? remain : READSIZE, &len);
                if (st && (st!=SANE_STATUS_EOF))
                  {
                    sane_cancel(self->h);
                    Py_BLOCK_THREADS
                    return PySane_Error(st);
                  }
                bufpos -= lastlen;
                lastlen = len;
                remain -= len;
                /* skip possible pad bytes at the start of the buffer */
                len -= bufpos;
              }
            break;
          case 8:
            remain = p.bytes_per_line * im->ysize;
            padbytes = p.bytes_per_line - im->xsize;
            bufpos = 0;
            len = 0;
            while (st!=SANE_STATUS_EOF && py < im->ysize)
              {
                while (len > 0 && py < im->ysize)
                  {
                    cplen = len;
                    if (px + cplen >= im->xsize)
                        cplen = im->xsize - px;
                    memcpy(&im->image8[py][px], &buffer[bufpos], cplen);
                    len -= cplen;
                    bufpos += cplen;
                    px += cplen;
                    if (px >= im->xsize)
                      {
                        px = 0;
                        py++;
                        bufpos += padbytes;
                        len -= padbytes;
                      }
                  }
                bufpos = -len;

                st=sane_read(self->h, buffer, 
                             remain<READSIZE ? remain : READSIZE, &len);
                if (st && (st!=SANE_STATUS_EOF))
                  {
                    sane_cancel(self->h);
                    Py_BLOCK_THREADS
                    return PySane_Error(st);
                  }
                remain -= len;
                len -= bufpos;
              }
              break;
          case 16:
            remain = p.bytes_per_line * im->ysize;
            padbytes = p.bytes_per_line - 2 * im->xsize;
            bufpos = endian.c[0];
            lastlen = len = 0;
            while (st!=SANE_STATUS_EOF && py < im->ysize)
              {
                while (len > 0 && py < im->ysize)
                  {
                    im->image8[py][px++] = buffer[bufpos];
                    bufpos += 2;
                    len -= 2;
                    if (px >= im->xsize)
                      {
                        bufpos += padbytes;
                        len -= padbytes;
                        py++;
                        px = 0;
                      }
                  }
                st=sane_read(self->h, buffer, 
                             remain<READSIZE ? remain : READSIZE, &len);
                if (st && (st!=SANE_STATUS_EOF))
                  {
                    sane_cancel(self->h);
                    Py_BLOCK_THREADS
                    return PySane_Error(st);
                  }
                remain -= len;
                bufpos -= lastlen;
                lastlen = len;
                len -= bufpos;
              }
Beispiel #12
0
/* DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET */
TW_UINT16 SANE_ImageNativeXferGet (pTW_IDENTITY pOrigin, 
                                    TW_MEMREF pData)
{
#ifndef HAVE_SANE
    return TWRC_FAILURE;
#else
    TW_UINT16 twRC = TWRC_SUCCESS;
    pTW_UINT32 pHandle = (pTW_UINT32) pData;
    SANE_Status status;
    SANE_Byte buffer[32*1024];
    int buff_len;
    HBITMAP hDIB;
    BITMAPINFO bmpInfo;
    VOID *pBits;
    HDC dc;

    TRACE("DG_IMAGE/DAT_IMAGENATIVEXFER/MSG_GET\n");

    if (activeDS.currentState != 6)
    {
        twRC = TWRC_FAILURE;
        activeDS.twCC = TWCC_SEQERROR;
    }
    else
    {
        /* Transfer an image from the source to the application */
        status = sane_start (activeDS.deviceHandle);
        if (status != SANE_STATUS_GOOD)
        {
            WARN("sane_start: %s\n", sane_strstatus (status));
            sane_cancel (activeDS.deviceHandle);
            activeDS.twCC = TWCC_OPERATIONERROR;
            return TWRC_FAILURE;
        }

        status = sane_get_parameters (activeDS.deviceHandle, &activeDS.sane_param);
        activeDS.sane_param_valid = TRUE;
        if (status != SANE_STATUS_GOOD)
        {
            WARN("sane_get_parameters: %s\n", sane_strstatus (status));
            sane_cancel (activeDS.deviceHandle);
            activeDS.twCC = TWCC_OPERATIONERROR;
            return TWRC_FAILURE;
        }

        TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
              , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
              activeDS.sane_param.depth, activeDS.sane_param.format,
              activeDS.sane_param.last_frame);

        ZeroMemory (&bmpInfo, sizeof (BITMAPINFO));
        bmpInfo.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
        bmpInfo.bmiHeader.biWidth = activeDS.sane_param.pixels_per_line;
        bmpInfo.bmiHeader.biHeight = activeDS.sane_param.lines;
        bmpInfo.bmiHeader.biPlanes = 1;
        bmpInfo.bmiHeader.biBitCount = activeDS.sane_param.depth;
        bmpInfo.bmiHeader.biCompression = BI_RGB;
        bmpInfo.bmiHeader.biSizeImage = 0;
        bmpInfo.bmiHeader.biXPelsPerMeter = 0;
        bmpInfo.bmiHeader.biYPelsPerMeter = 0;
        bmpInfo.bmiHeader.biClrUsed = 1;
        bmpInfo.bmiHeader.biClrImportant = 0;
        bmpInfo.bmiColors[0].rgbBlue = 128;
        bmpInfo.bmiColors[0].rgbGreen = 128;
        bmpInfo.bmiColors[0].rgbRed = 128;
        hDIB = CreateDIBSection ((dc = GetDC(activeDS.hwndOwner)), &bmpInfo,
                                 DIB_RGB_COLORS, &pBits, 0, 0);
        if (!hDIB)
        {
            sane_cancel (activeDS.deviceHandle);
            activeDS.twCC = TWCC_LOWMEMORY;
            return TWRC_FAILURE;
        }

        do
        {
            status = sane_read (activeDS.deviceHandle, buffer,
                                sizeof (buffer),  &buff_len);
            if (status == SANE_STATUS_GOOD)
            {
                /* FIXME: put code for converting the image data into DIB here */

            }
            else if (status != SANE_STATUS_EOF)
            {
                WARN("sane_read: %s\n", sane_strstatus (status));
                sane_cancel (activeDS.deviceHandle);
                activeDS.twCC = TWCC_OPERATIONERROR;
                return TWRC_FAILURE;
            }
        } while (status == SANE_STATUS_GOOD);

        sane_cancel (activeDS.deviceHandle);
        ReleaseDC (activeDS.hwndOwner, dc);
        *pHandle = (TW_UINT32)hDIB;
        twRC = TWRC_XFERDONE;
        activeDS.twCC = TWCC_SUCCESS;
        activeDS.currentState = 7;
    }
    return twRC;
#endif
}
Beispiel #13
0
/* DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET */
TW_UINT16 SANE_ImageMemXferGet (pTW_IDENTITY pOrigin, 
                                 TW_MEMREF pData)
{
#ifndef HAVE_SANE
    return TWRC_FAILURE;
#else
    TW_UINT16 twRC = TWRC_SUCCESS;
    pTW_IMAGEMEMXFER pImageMemXfer = (pTW_IMAGEMEMXFER) pData;
    SANE_Status status = SANE_STATUS_GOOD;

    TRACE ("DG_IMAGE/DAT_IMAGEMEMXFER/MSG_GET\n");

    if (activeDS.currentState < 6 || activeDS.currentState > 7)
    {
        twRC = TWRC_FAILURE;
        activeDS.twCC = TWCC_SEQERROR;
    }
    else
    {
        LPBYTE buffer;
        int buff_len = 0;
        int consumed_len = 0;
        LPBYTE ptr;
        int rows;

        /* Transfer an image from the source to the application */
        if (activeDS.currentState == 6)
        {

            /* trigger scanning dialog */
            activeDS.progressWnd = ScanningDialogBox(NULL,0);

            ScanningDialogBox(activeDS.progressWnd,0);

            status = sane_start (activeDS.deviceHandle);
            if (status != SANE_STATUS_GOOD)
            {
                WARN("sane_start: %s\n", sane_strstatus (status));
                sane_cancel (activeDS.deviceHandle);
                activeDS.twCC = TWCC_OPERATIONERROR;
                return TWRC_FAILURE;
            }

            status = sane_get_parameters (activeDS.deviceHandle,
                    &activeDS.sane_param);
            activeDS.sane_param_valid = TRUE;

            if (status != SANE_STATUS_GOOD)
            {
                WARN("sane_get_parameters: %s\n", sane_strstatus (status));
                sane_cancel (activeDS.deviceHandle);
                activeDS.twCC = TWCC_OPERATIONERROR;
                return TWRC_FAILURE;
            }

            TRACE("Acquiring image %dx%dx%d bits (format=%d last=%d) from sane...\n"
              , activeDS.sane_param.pixels_per_line, activeDS.sane_param.lines,
              activeDS.sane_param.depth, activeDS.sane_param.format,
              activeDS.sane_param.last_frame);

            activeDS.currentState = 7;
        }

        /* access memory buffer */
        if (pImageMemXfer->Memory.Length < activeDS.sane_param.bytes_per_line)
        {
            sane_cancel (activeDS.deviceHandle);
            activeDS.twCC = TWCC_BADVALUE;
            return TWRC_FAILURE;
        }

        if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
        {
            FIXME("Memory Handle, may not be locked correctly\n");
            buffer = LocalLock(pImageMemXfer->Memory.TheMem);
        }
        else
            buffer = pImageMemXfer->Memory.TheMem;
       
        memset(buffer,0,pImageMemXfer->Memory.Length);

        ptr = buffer;
        consumed_len = 0;
        rows = pImageMemXfer->Memory.Length / activeDS.sane_param.bytes_per_line;

        /* must fill full lines */
        while (consumed_len < (activeDS.sane_param.bytes_per_line*rows) && 
                status == SANE_STATUS_GOOD)
        {
            status = sane_read (activeDS.deviceHandle, ptr, 
                    (activeDS.sane_param.bytes_per_line*rows) - consumed_len ,
                    &buff_len);
            consumed_len += buff_len;
            ptr += buff_len;
        }

        if (status == SANE_STATUS_GOOD || status == SANE_STATUS_EOF)
        {
            pImageMemXfer->Compression = TWCP_NONE;
            pImageMemXfer->BytesPerRow = activeDS.sane_param.bytes_per_line;
            pImageMemXfer->Columns = activeDS.sane_param.pixels_per_line;
            pImageMemXfer->Rows = rows;
            pImageMemXfer->XOffset = 0;
            pImageMemXfer->YOffset = 0;
            pImageMemXfer->BytesWritten = consumed_len;

            ScanningDialogBox(activeDS.progressWnd, consumed_len);

            if (status == SANE_STATUS_EOF)
            {
                ScanningDialogBox(activeDS.progressWnd, -1);
                TRACE("sane_read: %s\n", sane_strstatus (status));
                sane_cancel (activeDS.deviceHandle);
                twRC = TWRC_XFERDONE;
            }
            activeDS.twCC = TWRC_SUCCESS;
        }
        else if (status != SANE_STATUS_EOF)
        {
            ScanningDialogBox(activeDS.progressWnd, -1);
            WARN("sane_read: %s\n", sane_strstatus (status));
            sane_cancel (activeDS.deviceHandle);
            activeDS.twCC = TWCC_OPERATIONERROR;
            twRC = TWRC_FAILURE;
        }
    }

    if (pImageMemXfer->Memory.Flags & TWMF_HANDLE)
        LocalUnlock(pImageMemXfer->Memory.TheMem);
    
    return twRC;
#endif
}
Beispiel #14
0
extern char *internalGetScannerDetails(char *device, char *lang) {

  char *answer = NULL;
  SANE_Status status;
  char *deviceList = o_strdup("");; 
  int hlp = 0, resolution = 300, minRes=50, maxRes=50, phashAvailable=0;
  char *resolution_s, *maxRes_s, *minRes_s;
  SANE_Handle *openDeviceHandle;

  o_log(DEBUGM, "sane_open of \"%s\"", device);
  status = sane_open (device, (SANE_Handle)&openDeviceHandle);
  if(status != SANE_STATUS_GOOD) {
    o_log(ERROR, "Could not open: '%s' with error: %s", device, sane_strstatus(status));
    free(deviceList);
    return NULL;
  }


  //
  // Find resolution ranges
  //
  for (hlp = 0; hlp < 9999; hlp++) {

    const SANE_Option_Descriptor *sod;

    sod = sane_get_option_descriptor (openDeviceHandle, hlp);
    if (sod == NULL)
      break;

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

    if ( 0 == strcmp(sod->name, SANE_NAME_SCAN_RESOLUTION) ) {

      // Some kind of sliding range
      if (sod->constraint_type == SANE_CONSTRAINT_RANGE) {
        o_log(DEBUGM, "Resolution setting detected as 'range'");

        // Fixed resolution
        if (sod->type == SANE_TYPE_FIXED)
          maxRes = (int)SANE_UNFIX (sod->constraint.range->max);
        else
          maxRes = sod->constraint.range->max;
      }

      // A fixed list of options
      else if (sod->constraint_type == SANE_CONSTRAINT_WORD_LIST) {
        int lastIndex = sod->constraint.word_list[0];
        o_log(DEBUGM, "Resolution setting detected as 'word list': lastIndex = %d",lastIndex);

        // maxRes = sod->constraint.word_list[lastIndex];
        // resolution list cannot be treated as low to high ordered list 
        // remark: impl capability to select scan resolution in webInterface
        int n=0;
        maxRes = 0;
        for (n=1; n<=lastIndex; n++ ) {
          o_log(DEBUGM, "index results %d --> %d", n ,(int)sod->constraint.word_list[n]);
          if ( maxRes < sod->constraint.word_list[n] ) {
            maxRes=sod->constraint.word_list[n];
          }
        }

      }

      break; // we've found our resolution - no need to search more
    }
  }
  o_log(DEBUGM, "Determined max resultion to be %d", maxRes);


  // Define a default
  if(resolution >= maxRes)
    resolution = maxRes;
  if(resolution <= minRes)
    resolution = minRes;

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

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



  //
  // What languages can we OCR for?
  //
  char *availableLangs = o_strdup("");
#ifdef CAN_OCR
  struct simpleLinkedList *languages = getOCRAvailableLanguages();
  while (languages != NULL ) {
    if ( checkOCRLanguage( languages->data ) == 0 ) {
      o_concatf(&availableLangs, "<lang>%s</lang>", languages->data);
    }
    languages = sll_getNext(languages);
  }
  sll_destroy( languages );
#endif /* CAN_OCR */


  //
  // Can we give the option of doing 'find simmilar'?
  //
#ifdef CAN_PHASH
  phashAvailable = 1;
#endif /* CAN_PHASH */

  // Build Reply
  //
  resolution_s = itoa(resolution,10);
  maxRes_s = itoa(maxRes,10);
  minRes_s = itoa(minRes,10);

  o_concatf(&deviceList, "<Resolution><max>%s</max><min>%s</min><default>%s</default></Resolution><OCRLanguages>%s</OCRLanguages><phash>%d</phash>", maxRes_s, minRes_s, resolution_s, availableLangs, phashAvailable);

  free(maxRes_s);
  free(minRes_s);
  free(resolution_s);
  free(availableLangs);

  // The escaped string placeholder will be interprited in the sane dispatcher client
  answer = o_printf("<?xml version='1.0' encoding='utf-8'?>\n<Response><ScannerDetails>%s</ScannerDetails></Response>", deviceList);
  free(deviceList);

  return answer;

}
Beispiel #15
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"); 
}
Beispiel #16
0
SANE_Status
sane_start (SANE_Handle handle)
{
  struct hp5590_scanner	*scanner = handle;
  SANE_Status		ret;
  unsigned int		bytes_per_line;

  DBG (DBG_proc, "%s\n", __FUNCTION__);

  if (!scanner)
    return SANE_STATUS_INVAL;

  if (   scanner->scanning == SANE_TRUE
      && (  scanner->source == SOURCE_ADF
	 || scanner->source == SOURCE_ADF_DUPLEX))
    {
      DBG (DBG_verbose, "%s: Scanner is scanning, check if more data is available\n",
	   __FUNCTION__);
      ret = hp5590_is_data_available (scanner->dn, scanner->proto_flags);
      if (ret == SANE_STATUS_GOOD)
	{
	  DBG (DBG_verbose, "%s: More data is available\n", __FUNCTION__);
	  scanner->transferred_image_size = scanner->image_size;
	  return SANE_STATUS_GOOD;
	}

      if (ret != SANE_STATUS_NO_DOCS)
	return ret;
    }

  sane_cancel (handle);

  if (scanner->wait_for_button)
    {
      enum button_status status;
      for (;;)
	{
	  ret = hp5590_read_buttons (scanner->dn,
	  		     	     scanner->proto_flags,
				     &status);
	  if (ret != SANE_STATUS_GOOD)
	    return ret;

	  if (status == BUTTON_CANCEL)
	    return SANE_STATUS_CANCELLED;

	  if (status != BUTTON_NONE && status != BUTTON_POWER)
	    break;
	  sleep (1);
	}
    }

  DBG (DBG_verbose, "Init scanner\n");  
  ret = hp5590_init_scanner (scanner->dn, scanner->proto_flags,
  			     NULL, SCANNER_NONE);
  if (ret != SANE_STATUS_GOOD)
    return ret;

  ret = hp5590_power_status (scanner->dn, scanner->proto_flags);
  if (ret != SANE_STATUS_GOOD)
    return ret;

  DBG (DBG_verbose, "Wakeup\n");
  ret = hp5590_select_source_and_wakeup (scanner->dn, scanner->proto_flags,
  					 scanner->source,
					 scanner->extend_lamp_timeout);
  if (ret != SANE_STATUS_GOOD)
    return ret;
 
  ret = hp5590_set_scan_params (scanner->dn,
  				scanner->proto_flags,
  				scanner->info,
			      	scanner->tl_x * scanner->dpi,
			      	scanner->tl_y * scanner->dpi,
			      	(scanner->br_x - scanner->tl_x) * scanner->dpi,
			      	(scanner->br_y - scanner->tl_y) * scanner->dpi,
			      	scanner->dpi,
		              	scanner->depth, scanner->preview ? MODE_PREVIEW : MODE_NORMAL,
			      	scanner->source);
  if (ret != SANE_STATUS_GOOD)
    {
      hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
      return ret;
    }

  ret = calc_image_params (scanner, NULL, NULL,
			   &bytes_per_line, NULL,
			   &scanner->image_size);
  if (ret != SANE_STATUS_GOOD)
    {
      hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
      return ret;
    }

  scanner->transferred_image_size = scanner->image_size;

  if (   scanner->depth == DEPTH_COLOR_24
      || scanner->depth == DEPTH_COLOR_48)
    {
      DBG (1, "Color 24/48 bits: checking if image size is correctly "
	   "aligned on number of colors\n");
      if (bytes_per_line % 3)
	{
	  DBG (DBG_err, "Color 24/48 bits: image size doesn't lined up on number of colors (3) "
	       "(image size: %u, bytes per line %u)\n",
	       scanner->image_size, bytes_per_line);
          hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
	  return SANE_STATUS_INVAL;
	}
      DBG (1, "Color 24/48 bits: image size is correctly aligned on number of colors "
	   "(image size: %u, bytes per line %u)\n",
	   scanner->image_size, bytes_per_line);

      DBG (1, "Color 24/48 bits: checking if image size is correctly "
	   "aligned on bytes per line\n");
      if (scanner->image_size % bytes_per_line)
	{
	  DBG (DBG_err, "Color 24/48 bits: image size doesn't lined up on bytes per line "
	       "(image size: %u, bytes per line %u)\n",
	       scanner->image_size, bytes_per_line);
          hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
	  return SANE_STATUS_INVAL;
	}
      DBG (1, "Color 24/48 bits: image size correctly aligned on bytes per line "
	   "(images size: %u, bytes per line: %u)\n",
	   scanner->image_size, bytes_per_line);
    }
 
  DBG (DBG_verbose, "Final image size: %u\n", scanner->image_size);

  DBG (DBG_verbose, "Reverse calibration maps\n");
  ret = hp5590_send_reverse_calibration_map (scanner->dn, scanner->proto_flags);
  if (ret != SANE_STATUS_GOOD)
    {
      hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
      return ret;
    }

  DBG (DBG_verbose, "Forward calibration maps\n");
  ret = hp5590_send_forward_calibration_maps (scanner->dn, scanner->proto_flags);
  if (ret != SANE_STATUS_GOOD)
    {
      hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
      return ret;
    }

  scanner->scanning = SANE_TRUE;

  DBG (DBG_verbose, "Starting scan\n");
  ret = hp5590_start_scan (scanner->dn, scanner->proto_flags);
  /* Check for paper jam */
  if (	  ret == SANE_STATUS_DEVICE_BUSY
      && (   scanner->source == SOURCE_ADF
	  || scanner->source == SOURCE_ADF_DUPLEX))
    return SANE_STATUS_JAMMED;

  if (ret != SANE_STATUS_GOOD)
    {
      hp5590_reset_scan_head (scanner->dn, scanner->proto_flags);
      return ret;
    }

  return SANE_STATUS_GOOD;
}
Beispiel #17
0
static void*
sane_idainit(FILE *fp, char *filename, unsigned int page, struct ida_image_info *info,
             int thumbnail)
{
    const SANE_Option_Descriptor *opt;
    SANE_Int flags, count;
    struct sane_state *h;
    int rc,i,value,dpi = 0;

    h = malloc(sizeof(*h));
    memset(h,0,sizeof(*h));

    if (SANE_STATUS_GOOD != (rc = sane_init(NULL,NULL))) {
        fprintf(stderr,"sane_init: %s\n",sane_strstatus(rc));
        goto oops;
    }
    if (SANE_STATUS_GOOD != (rc = sane_open(filename,&h->sane))) {
        fprintf(stderr,"sane_open: %s\n",sane_strstatus(rc));
        goto oops;
    }

    /* set options */
    opt = sane_get_option_descriptor(h->sane,0);
    rc = sane_control_option(h->sane, 0, SANE_ACTION_GET_VALUE,
                             &count, &flags);
    for (i = 1; i < count; i++) {
        opt = sane_get_option_descriptor(h->sane,i);
        if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_TL_X)) {
            value = opt->constraint.range->min;
            sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE,
                                &value, &flags);
        } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_TL_Y)) {
            value = opt->constraint.range->min;
            sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE,
                                &value, &flags);
        } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_BR_X)) {
            value = opt->constraint.range->max;
            sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE,
                                &value, &flags);
        } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_BR_Y)) {
            value = opt->constraint.range->max;
            sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE,
                                &value, &flags);
        } else if (opt->name && 0 == strcmp(opt->name,SANE_NAME_PREVIEW)) {
            value = SANE_FALSE;
            sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE,
                                &value, &flags);
        } else if (opt->cap & SANE_CAP_AUTOMATIC)
            sane_control_option(h->sane, i, SANE_ACTION_SET_AUTO,
                                NULL, &flags);
        if (opt->name && 0 == strcmp(opt->name,SANE_NAME_SCAN_RESOLUTION)) {
            if (sane_res) {
                dpi = sane_res;
                sane_control_option(h->sane, i, SANE_ACTION_SET_VALUE,
                                    &dpi, &flags);
            }
            sane_control_option(h->sane, i, SANE_ACTION_GET_VALUE,
                                &dpi, &flags);
        }
        if (debug)
            dump_desc(h->sane,i,opt);
    }

    if (SANE_STATUS_GOOD != (rc = sane_start(h->sane))) {
        fprintf(stderr,"sane_start: %s\n",sane_strstatus(rc));
        goto oops;
    }
    h->started = 1;

    if (SANE_STATUS_GOOD != (rc = sane_get_parameters(h->sane,&h->parm))) {
        fprintf(stderr,"sane_get_parameters: %s\n",sane_strstatus(rc));
        goto oops;
    }

    if (h->parm.format != SANE_FRAME_GRAY &&
            h->parm.format != SANE_FRAME_RGB) {
        fprintf(stderr,"sane: unsupported frame format (%d)\n",h->parm.format);
        goto oops;
    }
    if (h->parm.depth != 8) {
        fprintf(stderr,"sane: unsupported color depth (%d)\n",h->parm.depth);
        goto oops;
    }
    if (-1 == h->parm.lines) {
        fprintf(stderr,"sane: can't handle unknown image size\n");
        goto oops;
    }

    info->width  = h->parm.pixels_per_line;
    info->height = h->parm.lines;
    if (dpi)
        info->dpi  = dpi;
    h->buf = malloc(h->parm.bytes_per_line * BUF_LINES);
    if (debug)
        fprintf(stderr,"sane: scanning %dx%d %s\n",info->width,info->height,
                (h->parm.format == SANE_FRAME_GRAY) ? "gray" : "color");

    return h;

oops:
    if (h->buf)
        free(h->buf);
    if (h->started)
        sane_cancel(h->sane);
    if (h->sane)
        sane_close(h->sane);
    sane_exit();
    free(h);
    return NULL;
}
Beispiel #18
0
void
testsane (const char *dev_name)
{
  int hlp, x;
  SANE_Status bla;
  SANE_Int blubb;
  SANE_Handle hand;
  SANE_Parameters pars;
  const SANE_Option_Descriptor *sod;
  const SANE_Device **device_list;
  char buffer[2048];

  bla = sane_init (&blubb, auth_callback);
  fprintf (stderr, "Init : stat=%d ver=%x\nPress Enter to continue...",
	   bla, blubb);
  getchar ();
  if (bla != SANE_STATUS_GOOD)
    return;

  bla = sane_get_devices (&device_list, SANE_FALSE);
  fprintf (stderr, "GetDev : stat=%s\n", sane_strstatus (bla));
  if (bla != SANE_STATUS_GOOD)
    return;

  bla = sane_open (dev_name, &hand);
  fprintf (stderr, "Open : stat=%s hand=%p\n", sane_strstatus (bla), hand);
  if (bla != SANE_STATUS_GOOD)
    return;

  bla = sane_set_io_mode (hand, 0);
  fprintf (stderr, "SetIoMode : stat=%s\n", sane_strstatus (bla));

  for (hlp = 0; hlp < 9999; hlp++)
    {
      sod = sane_get_option_descriptor (hand, hlp);
      if (sod == NULL)
	break;
      fprintf (stderr, "Gopt(%d) : stat=%p\n", hlp, sod);
      fprintf (stderr, "name : %s\n", sod->name);
      fprintf (stderr, "title: %s\n", sod->title);
      fprintf (stderr, "desc : %s\n", sod->desc);

      fprintf (stderr, "type : %d\n", sod->type);
      fprintf (stderr, "unit : %d\n", sod->unit);
      fprintf (stderr, "size : %d\n", sod->size);
      fprintf (stderr, "cap  : %d\n", sod->cap);
      fprintf (stderr, "ctyp : %d\n", sod->constraint_type);
      switch (sod->constraint_type)
	{
	case SANE_CONSTRAINT_NONE:
	  break;
	case SANE_CONSTRAINT_STRING_LIST:
	  fprintf (stderr, "stringlist:\n");
	  break;
	case SANE_CONSTRAINT_WORD_LIST:
	  fprintf (stderr, "wordlist (%d) : ", sod->constraint.word_list[0]);
	  for (x = 1; x <= sod->constraint.word_list[0]; x++)
	    fprintf (stderr, " %d ", sod->constraint.word_list[x]);
	  fprintf (stderr, "\n");
	  break;
	case SANE_CONSTRAINT_RANGE:
	  fprintf (stderr, "range: %d-%d %d \n", sod->constraint.range->min,
		   sod->constraint.range->max, sod->constraint.range->quant);
	  break;
	}
    }

  bla = sane_get_parameters (hand, &pars);
  fprintf (stderr,
	   "Parm : stat=%s form=%d,lf=%d,bpl=%d,pixpl=%d,lin=%d,dep=%d\n",
	   sane_strstatus (bla),
	   pars.format, pars.last_frame,
	   pars.bytes_per_line, pars.pixels_per_line,
	   pars.lines, pars.depth);
  if (bla != SANE_STATUS_GOOD)
    return;

  bla = sane_start (hand);
  fprintf (stderr, "Start : stat=%s\n", sane_strstatus (bla));
  if (bla != SANE_STATUS_GOOD)
    return;

  do
    {
      bla = sane_read (hand, buffer, sizeof (buffer), &blubb);
      /*printf("Read : stat=%s len=%d\n",sane_strstatus (bla),blubb); */
      if (bla != SANE_STATUS_GOOD)
	{
	  if (bla == SANE_STATUS_EOF)
	    break;
	  return;
	}
      fwrite (buffer, 1, blubb, stdout);
    }
  while (1);

  sane_cancel (hand);
  fprintf (stderr, "Cancel.\n");

  sane_close (hand);
  fprintf (stderr, "Close\n");

  for (hlp = 0; hlp < 20; hlp++)
    fprintf (stderr, "STRS %d=%s\n", hlp, sane_strstatus (hlp));

  fprintf (stderr, "Exit.\n");
}