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); }
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); }
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); }
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); }
/* * 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"); }
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); }
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; }
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; } }
/* * 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; }
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; }
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; }
/* 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 }
/* 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 }
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; }
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"); }
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; }
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; }
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"); }