static PyObject * SaneDev_get_parameters(SaneDevObject *self, PyObject *args) { SANE_Status st; SANE_Parameters p; char *format="unknown format"; if (!PyArg_ParseTuple(args, "")) return NULL; if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } Py_BEGIN_ALLOW_THREADS st=sane_get_parameters(self->h, &p); Py_END_ALLOW_THREADS if (st) return PySane_Error(st); switch (p.format) { case(SANE_FRAME_GRAY): format="gray"; break; case(SANE_FRAME_RGB): format="color"; break; case(SANE_FRAME_RED): format="red"; break; case(SANE_FRAME_GREEN): format="green"; break; case(SANE_FRAME_BLUE): format="blue"; break; } return Py_BuildValue("si(ii)ii", format, p.last_frame, p.pixels_per_line, p.lines, p.depth, p.bytes_per_line); }
static PyObject * SaneDev_get_option(SaneDevObject *self, PyObject *args) { SANE_Status st; const SANE_Option_Descriptor *d; PyObject *value=NULL; int n; void *v; if (!PyArg_ParseTuple(args, "i", &n)) { return NULL; } if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } d=sane_get_option_descriptor(self->h, n); v=malloc(d->size+1); st=sane_control_option(self->h, n, SANE_ACTION_GET_VALUE, v, NULL); if (st) { free(v); return PySane_Error(st); } switch(d->type) { case(SANE_TYPE_BOOL): case(SANE_TYPE_INT): value=Py_BuildValue("i", *( (SANE_Int*)v) ); break; case(SANE_TYPE_FIXED): value=Py_BuildValue("d", SANE_UNFIX((*((SANE_Fixed*)v))) ); break; case(SANE_TYPE_STRING): value=Py_BuildValue("s", v); break; case(SANE_TYPE_BUTTON): case(SANE_TYPE_GROUP): value=Py_BuildValue("O", Py_None); break; } free(v); return value; }
static PyObject * SaneDev_fileno(SaneDevObject *self, PyObject *args) { SANE_Status st; SANE_Int fd; if (!PyArg_ParseTuple(args, "")) return NULL; if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } st=sane_get_select_fd(self->h, &fd); if (st) return PySane_Error(st); return PyInt_FromLong(fd); }
static PyObject * SaneDev_set_auto_option(SaneDevObject *self, PyObject *args) { SANE_Status st; const SANE_Option_Descriptor *d; SANE_Int i; int n; if (!PyArg_ParseTuple(args, "i", &n)) return NULL; if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } d=sane_get_option_descriptor(self->h, n); st=sane_control_option(self->h, n, SANE_ACTION_SET_AUTO, NULL, &i); if (st) {return PySane_Error(st);} return Py_BuildValue("i", i); }
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; }
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; }
static PyObject * SaneDev_set_option(SaneDevObject *self, PyObject *args) { SANE_Status st; const SANE_Option_Descriptor *d; SANE_Int i; PyObject *value; int n; void *v; if (!PyArg_ParseTuple(args, "iO", &n, &value)) return NULL; if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } d=sane_get_option_descriptor(self->h, n); v=malloc(d->size+1); switch(d->type) { case(SANE_TYPE_BOOL): if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_BOOL requires an integer"); free(v); return NULL; } /* fall through */ case(SANE_TYPE_INT): if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_INT requires an integer"); free(v); return NULL; } *( (SANE_Int*)v) = PyInt_AsLong(value); break; case(SANE_TYPE_FIXED): if (!PyFloat_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_FIXED requires a floating point number"); free(v); return NULL; } *( (SANE_Fixed*)v) = SANE_FIX(PyFloat_AsDouble(value)); break; case(SANE_TYPE_STRING): if (!PyString_Check(value)) { PyErr_SetString(PyExc_TypeError, "SANE_STRING requires a string"); free(v); return NULL; } strncpy(v, PyString_AsString(value), d->size-1); ((char*)v)[d->size-1] = 0; break; case(SANE_TYPE_BUTTON): case(SANE_TYPE_GROUP): break; } st=sane_control_option(self->h, n, SANE_ACTION_SET_VALUE, v, &i); if (st) {free(v); return PySane_Error(st);} free(v); return Py_BuildValue("i", i); }