Example #1
0
static PyObject *startScan (_ScanDevice * self, PyObject * args)
{
    SANE_Status st;

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

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

    /* sane_start can take several seconds, if the user initiates
       a new scan, while the scan head of a flatbed scanner moves
       back to the start position after finishing a previous scan.
       Hence it is worth to allow threads here.
     */
    Py_BEGIN_ALLOW_THREADS
    st = sane_start (self->h);
    Py_END_ALLOW_THREADS

    if (st != SANE_STATUS_GOOD &&
        st != SANE_STATUS_EOF &&
        st != SANE_STATUS_NO_DOCS)
          return raiseSaneError(st);

    return Py_BuildValue("i", st);
}
Example #2
0
    void KSaneScanThread::run()
    {
        m_dataSize = 0;
        m_readStatus = READ_ON_GOING;
        m_saneStartDone = false;

        // Start the scanning with sane_start
        m_saneStatus = sane_start(m_saneHandle);
        
        m_saneStartDone = true;
                
        if (m_readStatus == READ_CANCEL) {
            return;
        }
        
        if (m_saneStatus != SANE_STATUS_GOOD) {
            kDebug() << "sane_start=" << sane_strstatus(m_saneStatus);
            m_readStatus = READ_ERROR;
            // oneFinalScanDone() does the sane_cancel()
            return;
        }

        // Read image parameters
        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;
            // oneFinalScanDone() does the sane_cancel()
            return;
        }
        
        // calculate data size
        m_frameSize  = m_params.lines * m_params.bytes_per_line;
        if ((m_params.format == SANE_FRAME_RED) ||
            (m_params.format == SANE_FRAME_GREEN) ||
            (m_params.format == SANE_FRAME_BLUE))
        {
            m_dataSize = m_frameSize*3;
        }
        else {
            m_dataSize = m_frameSize;
        }
        
        m_data->clear();
        if (m_dataSize > 0) {
            m_data->reserve(m_dataSize);
        }
        
        m_frameRead     = 0;
        m_frame_t_count = 0;
        m_readStatus    = READ_ON_GOING;
        while (m_readStatus == READ_ON_GOING) {
            readData();
        }
    }
Example #3
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);
 }
Example #4
0
File: _sane.c Project: Bouke/Pillow
static PyObject *
SaneDev_start(SaneDevObject *self, PyObject *args)
{
  SANE_Status st;
  
  if (!PyArg_ParseTuple(args, ""))
    return NULL;
  if (self->h==NULL)
    {
      PyErr_SetString(ErrorObject, "SaneDev object is closed");
      return NULL;
    }
  /* sane_start can take several seconds, if the user initiates
     a new scan, while the scan head of a flatbed scanner moves
     back to the start position after finishing a previous scan.
     Hence it is worth to allow threads here.
  */
  Py_BEGIN_ALLOW_THREADS
  st=sane_start(self->h);
  Py_END_ALLOW_THREADS
  if (st) return PySane_Error(st);
  Py_INCREF(Py_None);
  return Py_None;
}
Example #5
0
// --------------------------------------------------------------
int32 ControlsWindow::ScanThread()
{
	SANE_Status						status;
	SANE_Handle						device;
	int 							len;
	SANE_Parameters 				parm;
	BBitmap *						image;
	bool							first_frame;
	
	device = Device();

	Lock();
	m_status_bar->Show();

	rgb_color default_color = m_status_bar->BarColor();
	
	m_scan_button->SetLabel("Cancel");
	m_status_bar->Reset("Scanning...");
	Unlock();
	
	first_frame = true;
	
	do	//  for each frame...
		{
		// start frame reading
		if ( m_cancel_scan )
			break;
		
		status = sane_start(device);
		if ( status != SANE_STATUS_GOOD )
			{
		 	fprintf (stderr, "sane_start: %s\n", sane_strstatus (status));
			break;
			};
	
		// get frame parameters
	    status = sane_get_parameters(device, &parm);
	    if (status != SANE_STATUS_GOOD)
			{
		 	fprintf (stderr, "sane_get_parameters: %s\n", sane_strstatus (status));
			break;
			};
			
		if (parm.lines >= 0)
			{
			Lock();
			m_status_bar->SetMaxValue(((parm.format == SANE_FRAME_RGB) ? 1.0 : 3.0)  * parm.bytes_per_line * parm.lines);
			Unlock();
	
			fprintf (stderr, "scanning image of size %dx%d pixels at "
	 				"%d bits/pixel\n",
	 				parm.pixels_per_line, parm.lines,
	 				8 * parm.bytes_per_line / parm.pixels_per_line);
				
			if ( first_frame )
				{
				image = new BBitmap(BRect(0, 0, parm.pixels_per_line - 1, parm.lines - 1),
						((parm.depth == 1) ? B_GRAY1 : B_RGBA32));
				
				m_parent_window->Lock();
				m_parent_window->SetImage(image);
				m_parent_window->Unlock();
				};
			}
	     else
			{
			fprintf (stderr, "scanning image %d pixels wide and "
				 "variable height at %d bits/pixel\n",
		 		parm.pixels_per_line, 8 * parm.bytes_per_line / parm.pixels_per_line);
		
			BAlert * alert = new BAlert("Well...", "Variable height scanning not supported (yet?)", "Sorry");
			alert->Go();
			break;
			};
		
	
		uint8 * buffer, * data;
		uint8 * 	ptr;
		int32		x, y;
		int			channel;
		rgb_color	red_color	= { 255, 0, 0, 255 };
		rgb_color	green_color	= { 0, 255, 0, 255 };
		rgb_color	blue_color	= { 0, 0, 255, 255 };
		BRect		updated_rect;
			
		x = y = 0;
		channel = 0;
		
		updated_rect.Set(0, 0, parm.pixels_per_line, 0);
		Lock();
		switch(parm.format)
			{
			case SANE_FRAME_RED:
				channel = 2;
				m_status_bar->SetBarColor(red_color);
				break;
			case SANE_FRAME_GREEN:
				channel = 1;
				m_status_bar->SetBarColor(green_color);
				break;
			case SANE_FRAME_BLUE:
				channel = 0;
				m_status_bar->SetBarColor(blue_color);
				break;
			default:
				channel = 0;
				m_status_bar->SetBarColor(default_color);
				break;
			};
		Unlock();								
			
		buffer = (uint8 *) malloc(parm.bytes_per_line);
	
		while (1)	// read until end of frame or error
			{
			if ( m_cancel_scan )
				break;
			
			len = 0;
			status = sane_read(device, buffer, parm.bytes_per_line, &len);
			if (status != SANE_STATUS_GOOD)
			    {
			    if (status != SANE_STATUS_EOF)
					{
					fprintf (stderr, "sane_read: %s\n", sane_strstatus (status));

					BAlert * alert = new BAlert("sane_read()", sane_strstatus(status), "Glup.");
					alert->Go();
					};
				break;
				};
					
			Lock();
			m_status_bar->Update((float) len);
			Unlock();
	
			if ( image )
				{
				image->Lock();
					
				ptr = (uint8 *) image->Bits();
				ptr += (y * image->BytesPerRow());
				ptr += (4*x);
	
				data = buffer;
				while ( len > 0 )
					{
			      	switch (parm.format)
						{
						case SANE_FRAME_RED:
						case SANE_FRAME_GREEN:
						case SANE_FRAME_BLUE:
							{
							uint8	value;
	
							if (parm.depth == 16)
								{
								value = (*((uint16 *) data)) >> 8;
								data += 2;
								len -= 2;
								}
							else
								{
								value = *((uint8 *) data);
								data++;
								len--;
								};
	
							*(ptr + channel) = value;
							*(ptr + 3)		= 255;	// Alpha channel
							break;
							};
							
						case SANE_FRAME_RGB:
							{
							uint8 red, green, blue;
							
							if (parm.depth == 16)
								{
								red = (*((uint16 *) data)) >> 8;
								data += 2;
								green = (*((uint16 *) data)) >> 8;
								data += 2;
								blue = (*((uint16 *) data)) >> 8;
								data += 2;
								len -= 6;
								}
							else
								{
								red = *((uint8 *) data);
								data++;
								green = *((uint8 *) data);
								data++;
								blue = *((uint8 *) data);
								data++;
								len -= 3;
								};
	
							*ptr 		= blue;
							*(ptr+1) 	= green;
							*(ptr+2) 	= red;	// red channel
							*(ptr+3) 	= 255;		// Alpha channel
							break;
							};
							
						case SANE_FRAME_GRAY:
							{
							uint8	value;
							
							if (parm.depth == 1 )
								{
								*ptr = *((uint8 *) data);
								data++;
								len--;
								break;
								};
							
							if (parm.depth == 16)
								{
								value = (*((uint16 *) data)) >> 8;
								data += 2;
								len -= 2;
								}
							else if ( parm.depth == 8 )
								{
								value = *((uint8 *) data);
								data++;
								len--;
								};
	
							*ptr 		= value;	// blue channel
							*(ptr+1) 	= value;	// green channel
							*(ptr+2) 	= value;	// red channel
							*(ptr+3) 	= 255;		// Alpha channel
							break;
							};
Example #6
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
}
Example #7
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
}
Example #8
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;
}
Example #9
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"); 
}
Example #10
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");
}