SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { int rc = SANE_STATUS_GOOD; int w = SANE_UNFIX (optionBotRightXValue - optionTopLeftXValue) / MM_IN_INCH * optionResolutionValue; int h = SANE_UNFIX (optionBotRightYValue - optionTopLeftYValue) / MM_IN_INCH * optionResolutionValue; handle = handle; /* Eliminate compiler warning */ DBG (3, "sane_get_parameters\n"); parms.depth = 8; parms.last_frame = SANE_TRUE; parms.pixels_per_line = w; parms.lines = h; #ifdef GRAY if (optionGrayscaleValue == SANE_TRUE) { parms.format = SANE_FRAME_GRAY; parms.bytes_per_line = w; } else #endif { parms.format = SANE_FRAME_RGB; parms.bytes_per_line = w * 3; } *params = parms; return rc; }
void kv_calc_paper_size (const PKV_DEV dev, int *w, int *h) { int i = get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE].s); if (i == 0) { /* Non-standard document */ int x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); int y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); int x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); int y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); *w = x_br - x_tl; *h = y_br - y_tl; } else { if (dev->val[OPT_LANDSCAPE].s) { *h = mmToIlu (go_paper_sizes[i].width); *w = mmToIlu (go_paper_sizes[i].height); } else { *w = mmToIlu (go_paper_sizes[i].width); *h = mmToIlu (go_paper_sizes[i].height); } } }
SANE_Status sane_start (SANE_Handle handle) { Canon_Scanner *scanner = handle; SANE_Status res; DBG (3, "sane_start\n"); res = CANON_set_scan_parameters (&scanner->scan, optionCalibrateValue, #ifdef GRAY optionGrayscaleValue, #else SANE_FALSE, #endif SANE_UNFIX (optionTopLeftXValue) / MM_IN_INCH * 600, SANE_UNFIX (optionTopLeftYValue) / MM_IN_INCH * 600, SANE_UNFIX (optionBotRightXValue) / MM_IN_INCH * 600, SANE_UNFIX (optionBotRightYValue) / MM_IN_INCH * 600, optionResolutionValue, optionAGainValue, SANE_UNFIX (optionGammaValue)); if (res != SANE_STATUS_GOOD) return res; return CANON_start_scan (&scanner->scan); }
SANE_Status sane_get_parameters( SANE_Handle handle, SANE_Parameters *paramsP ) { ST400_Device *dev = handle; DBG(DCODE, "sane_get_parameters(%p, %p)\n", handle, (void *) paramsP); if( !dev->status.open ) return SANE_STATUS_INVAL; if( !dev->status.scanning ) { double width, height, dpi; dev->params.format = SANE_FRAME_GRAY; dev->params.last_frame = SANE_TRUE; dev->params.lines = 0; dev->params.depth = dev->val[OPT_DEPTH]; width = SANE_UNFIX(dev->val[OPT_BR_X] - dev->val[OPT_TL_X]); height = SANE_UNFIX(dev->val[OPT_BR_Y] - dev->val[OPT_TL_Y]); dpi = dev->val[OPT_RESOLUTION]; /* make best-effort guess at what parameters will look like once scanning starts. */ if( dpi > 0.0 && width > 0.0 && height > 0.0 ) { double dots_per_mm = dpi / MM_PER_INCH; dev->params.pixels_per_line = width * dots_per_mm + 0.5; dev->params.lines = height * dots_per_mm + 0.5; if( dev->params.depth == 1 ) { /* Pad to an even multiple of 8. This way we can simply * copy the bytes from the scanner to the SANE buffer * (only need to invert them). */ dev->params.pixels_per_line += 7; dev->params.pixels_per_line &= ~7; /*dev->params.bytes_per_line = (dev->params.pixels_per_line + 7)/8;*/ dev->params.bytes_per_line = dev->params.pixels_per_line/8; } else dev->params.bytes_per_line = dev->params.pixels_per_line; dev->x = SANE_UNFIX(dev->val[OPT_TL_X]) * dots_per_mm + 0.5; dev->y = SANE_UNFIX(dev->val[OPT_TL_Y]) * dots_per_mm + 0.5; dev->w = dev->params.pixels_per_line; dev->h = dev->params.lines; DBG(DVAR, "parameters: bpl=%d, x=%hu, y=%hu, w=%hu, h=%hu\n", (int)dev->params.bytes_per_line, dev->x, dev->y, dev->w, dev->h); } } if( paramsP ) *paramsP = dev->params; return SANE_STATUS_GOOD; }
SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters *params) { Tamarack_Scanner *s = handle; if (!s->scanning) { double width, height, dpi; memset (&s->params, 0, sizeof (s->params)); width = SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w); height = SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w); dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->mode = make_mode (s->val[OPT_MODE].s); DBG(1, "got mode '%s' -> %d.\n", s->val[OPT_MODE].s, s->mode); /* make best-effort guess at what parameters will look like once scanning starts. */ if (dpi > 0.0 && width > 0.0 && height > 0.0) { double dots_per_mm = dpi / MM_PER_INCH; s->params.pixels_per_line = width * dots_per_mm; s->params.lines = height * dots_per_mm; } if ((s->mode == THRESHOLDED) || (s->mode == DITHERED)) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = (s->params.pixels_per_line + 7) / 8; s->params.depth = 1; } else if (s->mode == GREYSCALE) { s->params.format = SANE_FRAME_GRAY; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } else { s->params.format = SANE_FRAME_RED + s->pass; s->params.bytes_per_line = s->params.pixels_per_line; s->params.depth = 8; } s->pass = 0; } else { if (s->mode == TRUECOLOR) s->params.format = SANE_FRAME_RED + s->pass; } s->params.last_frame = (s->mode != TRUECOLOR) || (s->pass == 2); if (params) *params = s->params; DBG(1, "Got parameters: format:%d, ppl: %d, bpl:%d, depth:%d, " "last %d pass %d\n", s->params.format, s->params.pixels_per_line, s->params.bytes_per_line, s->params.depth, s->params.last_frame, s->pass); return SANE_STATUS_GOOD; }
bool KSaneOptCombo::getValue(float &val) { if (state() == STATE_HIDDEN) { return false; } // read that current value QVarLengthArray<unsigned char> data(m_optDesc->size); SANE_Status status; SANE_Int res; status = sane_control_option(m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res); if (status != SANE_STATUS_GOOD) { qDebug() << m_optDesc->name << "sane_control_option returned" << status; return false; } switch (m_optDesc->type) { case SANE_TYPE_INT: val = (float)toSANE_Word(data.data()); return true; case SANE_TYPE_FIXED: val = SANE_UNFIX(toSANE_Word(data.data())); return true; default: qDebug() << "Type" << m_optDesc->type << "not supported!"; break; } return false; }
QStringList &KSaneOptCombo::genComboStringList() { int i; m_strList.clear(); switch (m_optDesc->type) { case SANE_TYPE_INT: for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) { m_strList += getSaneComboString((int)m_optDesc->constraint.word_list[i]); } break; case SANE_TYPE_FIXED: for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) { m_strList += getSaneComboString((float)SANE_UNFIX(m_optDesc->constraint.word_list[i])); } break; case SANE_TYPE_STRING: i = 0; while (m_optDesc->constraint.string_list[i] != 0) { m_strList += getSaneComboString((unsigned char *)m_optDesc->constraint.string_list[i]); i++; } break; default : m_strList += QStringLiteral("NOT HANDELED"); break; } return m_strList; }
/* ICAP_PHYSICALHEIGHT, ICAP_PHYSICALWIDTH */ static TW_UINT16 SANE_ICAPPhysical (pTW_CAPABILITY pCapability, TW_UINT16 action, TW_UINT16 cap) { TW_UINT16 twCC = TWCC_BADCAP; #ifdef SONAME_LIBSANE TW_FIX32 res; char option_name[64]; SANE_Fixed lower, upper; SANE_Unit lowerunit, upperunit; SANE_Status status; TRACE("ICAP_PHYSICAL%s\n", cap == ICAP_PHYSICALHEIGHT? "HEIGHT" : "WIDTH"); sprintf(option_name, "tl-%c", cap == ICAP_PHYSICALHEIGHT ? 'y' : 'x'); status = sane_option_probe_scan_area(activeDS.deviceHandle, option_name, NULL, &lowerunit, &lower, NULL, NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); sprintf(option_name, "br-%c", cap == ICAP_PHYSICALHEIGHT ? 'y' : 'x'); status = sane_option_probe_scan_area(activeDS.deviceHandle, option_name, NULL, &upperunit, NULL, &upper, NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); if (upperunit != lowerunit) return TWCC_BADCAP; if (! convert_sane_res_to_twain(SANE_UNFIX(upper) - SANE_UNFIX(lower), upperunit, &res, TWUN_INCHES)) return TWCC_BADCAP; switch (action) { case MSG_QUERYSUPPORT: twCC = set_onevalue(pCapability, TWTY_INT32, TWQC_GET | TWQC_GETDEFAULT | TWQC_GETCURRENT ); break; case MSG_GET: case MSG_GETDEFAULT: /* .. fall through intentional .. */ case MSG_GETCURRENT: twCC = set_onevalue(pCapability, TWTY_FIX32, res.Whole | (res.Frac << 16)); break; } #endif return twCC; }
static SANE_Status st400_set_window( ST400_Device *dev ) { unsigned short xoff, yoff; SANE_Byte th; struct { /* 10byte command */ SANE_Byte cmd, lun, reserved1[4], tr_len[3], ctrl; /* 40byte window struct */ SANE_Byte reserved2[6], wd_len[2], winnr, reserved3; SANE_Byte x_res[2], y_res[2]; /* resolution: 200, 300, 400 */ SANE_Byte x_ul[2], y_ul[2]; /* upper left corner */ SANE_Byte width[2], height[2]; SANE_Byte reserved4, threshold; SANE_Byte reserved5, halftone; /* ht: 0 or 2 */ SANE_Byte bitsperpixel, reserved6[13]; /* bpp: 1 or 8 */ } scsi_cmd; /* The PC/Amiga source uses reserved5 to indicate A4/A5 paper size * (values 4 and 5), but a comment implies that this is only for the * scanning program and the value is ignored by the scanner. */ SANE_Status status; memset(&scsi_cmd, 0, sizeof(scsi_cmd)); scsi_cmd.cmd = CMD_SET_WINDOW; set24(scsi_cmd.tr_len, 40); set16(scsi_cmd.wd_len, 32); /* These offsets seem to be required to avoid damaging the scanner: * If a scan with 0/0 as the top left corner is started, the scanner * seems to try to move the carriage over the bottom end (not a * pretty sound). */ xoff = (11L * dev->val[OPT_RESOLUTION]) / 100; yoff = 6; th = (double)maxval(dev->model->bits) * SANE_UNFIX(dev->val[OPT_THRESHOLD]) / 100.0; scsi_cmd.winnr = 1; set16(scsi_cmd.x_res, (unsigned short)dev->val[OPT_RESOLUTION]); set16(scsi_cmd.y_res, (unsigned short)dev->val[OPT_RESOLUTION]); set16(scsi_cmd.x_ul, dev->x + xoff); set16(scsi_cmd.y_ul, dev->wy + yoff); set16(scsi_cmd.width, dev->w); set16(scsi_cmd.height, dev->wh); scsi_cmd.threshold = th; scsi_cmd.halftone = (dev->val[OPT_DEPTH] == 1) ? 0 : 2; scsi_cmd.bitsperpixel = dev->val[OPT_DEPTH]; DBG(DSCSI, "SCSI: sending SET_WINDOW (x=%hu y=%hu w=%hu h=%hu wy=%hu wh=%hu th=%d\n", dev->x, dev->y, dev->w, dev->h, dev->wy, dev->wh, (int)th); status = sanei_scsi_cmd(dev->fd, &scsi_cmd, sizeof(scsi_cmd), 0, 0); DBG(DSCSI, "SCSI: result=%s\n", sane_strstatus(status)); return status; }
bool KSaneOptCombo::setValue(float value) { unsigned char data[4]; float tmp; float minDiff; int i; int minIndex = 1; switch (m_optDesc->type) { case SANE_TYPE_INT: tmp = (float)m_optDesc->constraint.word_list[minIndex]; minDiff = qAbs(value - tmp); for (i = 2; i <= m_optDesc->constraint.word_list[0]; ++i) { tmp = (float)m_optDesc->constraint.word_list[i]; if (qAbs(value - tmp) < minDiff) { minDiff = qAbs(value - tmp); minIndex = i; } } fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]); writeData(data); readValue(); return (minDiff < 1.0); case SANE_TYPE_FIXED: tmp = (float)SANE_UNFIX(m_optDesc->constraint.word_list[minIndex]); minDiff = qAbs(value - tmp); for (i = 2; i <= m_optDesc->constraint.word_list[0]; ++i) { tmp = (float)SANE_UNFIX(m_optDesc->constraint.word_list[i]); if (qAbs(value - tmp) < minDiff) { minDiff = qAbs(value - tmp); minIndex = i; } } fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]); writeData(data); readValue(); return (minDiff < 1.0); default: qDebug() << "can not handle type:" << m_optDesc->type; break; } return false; }
/*--------------------------------------------------------------------------*/ static SANE_Int as6e_unit_convert (SANE_Fixed value) { double precise; SANE_Int return_value; precise = SANE_UNFIX (value); precise = (precise * 300) / MM_PER_INCH; return_value = precise; return return_value; }
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; }
bool KSaneOptCombo::getMinValue(float &val) { if (state() == STATE_HIDDEN) { return false; } switch (m_optDesc->type) { case SANE_TYPE_INT: val = (float)m_optDesc->constraint.word_list[1]; for (int i = 2; i <= m_optDesc->constraint.word_list[0]; i++) { val = qMin((float)m_optDesc->constraint.word_list[i], val); } break; case SANE_TYPE_FIXED: val = (float)SANE_UNFIX(m_optDesc->constraint.word_list[1]); for (int i = 2; i <= m_optDesc->constraint.word_list[0]; i++) { val = qMin((float)SANE_UNFIX(m_optDesc->constraint.word_list[i]), val); } break; default: qDebug() << "can not handle type:" << m_optDesc->type; return false; } return true; }
static PyObject *getOption (_ScanDevice * self, PyObject * args) { SANE_Status st; const SANE_Option_Descriptor *d; PyObject *value = NULL; int n; void *v; if (!PyArg_ParseTuple (args, "i", &n)) raiseError("Invalid arguments."); if (self->h == NULL) return raiseDeviceClosedError(); 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 != SANE_STATUS_GOOD) { free (v); return raiseSaneError(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; }
SANE_Status esci_set_color_correction_coefficients(Epson_Scanner * s, SANE_Word *table) { SANE_Status status; unsigned char params[2]; unsigned char data[9]; double cct[9]; DBG(8, "%s\n", __func__); if (!s->hw->cmd->set_color_correction_coefficients) { DBG(1, "%s: not supported\n", __func__); return SANE_STATUS_UNSUPPORTED; } params[0] = ESC; params[1] = s->hw->cmd->set_color_correction_coefficients; status = e2_cmd_simple(s, params, 2); if (status != SANE_STATUS_GOOD) return status; cct[0] = SANE_UNFIX(table[0]); cct[1] = SANE_UNFIX(table[1]); cct[2] = SANE_UNFIX(table[2]); cct[3] = SANE_UNFIX(table[3]); cct[4] = SANE_UNFIX(table[4]); cct[5] = SANE_UNFIX(table[5]); cct[6] = SANE_UNFIX(table[6]); cct[7] = SANE_UNFIX(table[7]); cct[8] = SANE_UNFIX(table[8]); profile_to_colorcoeff(cct, data); DBG(11, "%s: %d,%d,%d %d,%d,%d %d,%d,%d\n", __func__, data[0] , data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]); return e2_cmd_simple(s, data, 9); }
static unsigned int print_fixed_vec(const SANE_Fixed * val, SANE_Int size, char *buf, unsigned buf_size) { char *buf_start = buf; unsigned int pos = 0, chars = 0; int chars_left = buf_size; SANE_Int i, num = size / (SANE_Int) sizeof(SANE_Word); for (i = 0; i < num; i++) { chars = snprintf(buf += chars, chars_left, "%f,", SANE_UNFIX(*(SANE_Fixed *) val + i)); chars_left -= chars; /* printf("i=%d, chars=%d, chars_left=%d\n", i,chars,chars_left); */ if (chars_left <= 0 && i < (num - 1)) return buf_size; /* -1? */ } buf[chars - 1] = '\0'; /* erase last `,' */ /* printf("i=%d, chars=%d, chars_left=%d: %s\n", i,chars,chars_left,buf_start); */ return buf_size - chars_left; }
QString KSaneOptCombo::getSaneComboString(unsigned char *data) { QString tmp; if (data == 0) { return QString(); } switch (m_optDesc->type) { case SANE_TYPE_INT: return getSaneComboString((int)toSANE_Word(data)); case SANE_TYPE_FIXED: return getSaneComboString((float)SANE_UNFIX(toSANE_Word(data))); case SANE_TYPE_STRING: tmp = i18n(reinterpret_cast<char *>(data)); tmp = tmp.simplified(); return tmp; default : break; } return QString(); }
static TW_UINT16 get_width_height(double *width, double *height, BOOL max) { SANE_Status status; SANE_Fixed tlx_current, tlx_min, tlx_max; SANE_Fixed tly_current, tly_min, tly_max; SANE_Fixed brx_current, brx_min, brx_max; SANE_Fixed bry_current, bry_min, bry_max; status = sane_option_probe_scan_area(activeDS.deviceHandle, "tl-x", &tlx_current, NULL, &tlx_min, &tlx_max, NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); status = sane_option_probe_scan_area(activeDS.deviceHandle, "tl-y", &tly_current, NULL, &tly_min, &tly_max, NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); status = sane_option_probe_scan_area(activeDS.deviceHandle, "br-x", &brx_current, NULL, &brx_min, &brx_max, NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); status = sane_option_probe_scan_area(activeDS.deviceHandle, "br-y", &bry_current, NULL, &bry_min, &bry_max, NULL); if (status != SANE_STATUS_GOOD) return sane_status_to_twcc(status); if (max) *width = SANE_UNFIX(brx_max) - SANE_UNFIX(tlx_min); else *width = SANE_UNFIX(brx_current) - SANE_UNFIX(tlx_current); if (max) *height = SANE_UNFIX(bry_max) - SANE_UNFIX(tly_min); else *height = SANE_UNFIX(bry_current) - SANE_UNFIX(tly_current); return(TWCC_SUCCESS); }
static PyObject * SaneDev_get_options(SaneDevObject *self, PyObject *args) { const SANE_Option_Descriptor *d; PyObject *list, *value; int i=1; if (!PyArg_ParseTuple(args, "")) return NULL; if (self->h==NULL) { PyErr_SetString(ErrorObject, "SaneDev object is closed"); return NULL; } if (!(list = PyList_New(0))) return NULL; do { d=sane_get_option_descriptor(self->h, i); if (d!=NULL) { PyObject *constraint=NULL; int j; switch (d->constraint_type) { case(SANE_CONSTRAINT_NONE): Py_INCREF(Py_None); constraint=Py_None; break; case(SANE_CONSTRAINT_RANGE): if (d->type == SANE_TYPE_INT) constraint=Py_BuildValue("iii", d->constraint.range->min, d->constraint.range->max, d->constraint.range->quant); else constraint=Py_BuildValue("ddd", SANE_UNFIX(d->constraint.range->min), SANE_UNFIX(d->constraint.range->max), SANE_UNFIX(d->constraint.range->quant)); break; case(SANE_CONSTRAINT_WORD_LIST): constraint=PyList_New(d->constraint.word_list[0]); if (d->type == SANE_TYPE_INT) for (j=1; j<=d->constraint.word_list[0]; j++) PyList_SetItem(constraint, j-1, PyInt_FromLong(d->constraint.word_list[j])); else for (j=1; j<=d->constraint.word_list[0]; j++) PyList_SetItem(constraint, j-1, PyFloat_FromDouble(SANE_UNFIX(d->constraint.word_list[j]))); break; case(SANE_CONSTRAINT_STRING_LIST): constraint=PyList_New(0); for(j=0; d->constraint.string_list[j]!=NULL; j++) PyList_Append(constraint, #if PY_MAJOR_VERSION >= 3 PyUnicode_DecodeLatin1(d->constraint.string_list[j], strlen(d->constraint.string_list[j]), NULL)); #else PyString_FromString(d->constraint.string_list[j])); #endif break; } value=Py_BuildValue("isssiiiiO", i, d->name, d->title, d->desc, d->type, d->unit, d->size, d->cap, constraint); PyList_Append(list, value); } i++; } while (d!=NULL);
static SANE_Status calc_parameters (Mustek_Usb_Scanner * s) { SANE_String val; SANE_Status status = SANE_STATUS_GOOD; SANE_Int max_x, max_y; DBG (5, "calc_parameters: start\n"); val = s->val[OPT_MODE].s; s->params.last_frame = SANE_TRUE; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 1; s->bpp = 1; s->channels = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) { s->params.format = SANE_FRAME_GRAY; s->params.depth = 8; s->bpp = 8; s->channels = 1; } else if (!strcmp (val, SANE_VALUE_SCAN_MODE_COLOR)) { s->params.format = SANE_FRAME_RGB; s->params.depth = 8; s->bpp = 24; s->channels = 3; } else { DBG (1, "calc_parameters: invalid mode %s\n", (SANE_Char *) val); status = SANE_STATUS_INVAL; } s->tl_x = SANE_UNFIX (s->val[OPT_TL_X].w) / MM_PER_INCH; s->tl_y = SANE_UNFIX (s->val[OPT_TL_Y].w) / MM_PER_INCH; s->width = SANE_UNFIX (s->val[OPT_BR_X].w) / MM_PER_INCH - s->tl_x; s->height = SANE_UNFIX (s->val[OPT_BR_Y].w) / MM_PER_INCH - s->tl_y; if (s->width < 0) { DBG (1, "calc_parameters: warning: tl_x > br_x\n"); } if (s->height < 0) { DBG (1, "calc_parameters: warning: tl_y > br_y\n"); } max_x = s->hw->max_width * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; max_y = s->hw->max_height * SANE_UNFIX (s->val[OPT_RESOLUTION].w) / 300; s->tl_x_dots = s->tl_x * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->width_dots = s->width * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->tl_y_dots = s->tl_y * SANE_UNFIX (s->val[OPT_RESOLUTION].w); s->height_dots = s->height * SANE_UNFIX (s->val[OPT_RESOLUTION].w); if (s->width_dots > max_x) s->width_dots = max_x; if (s->height_dots > max_y) s->height_dots = max_y; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) { s->width_dots = (s->width_dots / 8) * 8; if (s->width_dots == 0) s->width_dots = 8; } if (s->tl_x_dots < 0) s->tl_x_dots = 0; if (s->tl_y_dots < 0) s->tl_y_dots = 0; if (s->tl_x_dots + s->width_dots > max_x) s->tl_x_dots = max_x - s->width_dots; if (s->tl_y_dots + s->height_dots > max_y) s->tl_y_dots = max_y - s->height_dots; s->val[OPT_TL_X].w = SANE_FIX (s->tl_x * MM_PER_INCH); s->val[OPT_TL_Y].w = SANE_FIX (s->tl_y * MM_PER_INCH); s->val[OPT_BR_X].w = SANE_FIX ((s->tl_x + s->width) * MM_PER_INCH); s->val[OPT_BR_Y].w = SANE_FIX ((s->tl_y + s->height) * MM_PER_INCH); s->params.pixels_per_line = s->width_dots; if (s->params.pixels_per_line < 0) s->params.pixels_per_line = 0; s->params.lines = s->height_dots; if (s->params.lines < 0) s->params.lines = 0; s->params.bytes_per_line = s->params.pixels_per_line * s->params.depth / 8 * s->channels; DBG (4, "calc_parameters: format=%d\n", s->params.format); DBG (4, "calc_parameters: last frame=%d\n", s->params.last_frame); DBG (4, "calc_parameters: lines=%d\n", s->params.lines); DBG (4, "calc_parameters: pixels per line=%d\n", s->params.pixels_per_line); DBG (4, "calc_parameters: bytes per line=%d\n", s->params.bytes_per_line); DBG (4, "calc_parameters: Pixels %dx%dx%d\n", s->params.pixels_per_line, s->params.lines, 1 << s->params.depth); DBG (5, "calc_parameters: exit\n"); return status; }
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; }
extern void log_option (SANE_Int index, const SANE_Option_Descriptor *option) { char *string; SANE_Word i; SANE_Int cap; string = o_strdup(""); o_concatf (&string, "Option %d:", index); if (option->name) o_concatf (&string, " name='%s'", option->name); if (option->title) o_concatf (&string, " title='%s'", option->title); switch (option->type) { case SANE_TYPE_BOOL: conCat(&string, " type=bool"); break; case SANE_TYPE_INT: conCat(&string, " type=int"); break; case SANE_TYPE_FIXED: conCat(&string, " type=fixed"); break; case SANE_TYPE_STRING: conCat(&string, " type=string"); break; case SANE_TYPE_BUTTON: conCat(&string, " type=button"); break; case SANE_TYPE_GROUP: conCat(&string, " type=group"); break; default: o_concatf (&string, " type=%d", option->type); break; } o_concatf (&string, " size=%d", option->size); switch (option->unit) { case SANE_UNIT_NONE: break; case SANE_UNIT_PIXEL: conCat(&string, " unit=pixels"); break; case SANE_UNIT_BIT: conCat(&string, " unit=bits"); break; case SANE_UNIT_MM: conCat(&string, " unit=mm"); break; case SANE_UNIT_DPI: conCat(&string, " unit=dpi"); break; case SANE_UNIT_PERCENT: conCat(&string, " unit=percent"); break; case SANE_UNIT_MICROSECOND: conCat(&string, " unit=microseconds"); break; default: o_concatf (&string, " unit=%d", option->unit); break; } switch (option->constraint_type) { case SANE_CONSTRAINT_RANGE: if (option->type == SANE_TYPE_FIXED) o_concatf (&string, " min=%f, max=%f, quant=%d", SANE_UNFIX (option->constraint.range->min), SANE_UNFIX (option->constraint.range->max), option->constraint.range->quant); else o_concatf (&string, " min=%d, max=%d, quant=%d", option->constraint.range->min, option->constraint.range->max, option->constraint.range->quant); break; case SANE_CONSTRAINT_WORD_LIST: conCat(&string, " values=["); for (i = 0; i < option->constraint.word_list[0]; i++) { if (i != 0) conCat(&string, ", "); if (option->type == SANE_TYPE_INT) o_concatf (&string, "%d", option->constraint.word_list[i+1]); else o_concatf (&string, "%f", SANE_UNFIX (option->constraint.word_list[i+1])); } conCat(&string, "]"); break; case SANE_CONSTRAINT_STRING_LIST: conCat(&string, " values=["); for (i = 0; option->constraint.string_list[i]; i++) { if (i != 0) conCat(&string, ", "); o_concatf (&string, "\"%s\"", option->constraint.string_list[i]); } conCat(&string, "]"); break; default: break; } cap = option->cap; if (cap) { struct { SANE_Int cap; const char *name; } caps[] = { { SANE_CAP_SOFT_SELECT, "soft-select"}, { SANE_CAP_HARD_SELECT, "hard-select"}, { SANE_CAP_SOFT_DETECT, "soft-detect"}, { SANE_CAP_EMULATED, "emulated"}, { SANE_CAP_AUTOMATIC, "automatic"}, { SANE_CAP_INACTIVE, "inactive"}, { SANE_CAP_ADVANCED, "advanced"}, { 0, NULL} }; int i, n = 0; conCat(&string, " cap="); for (i = 0; caps[i].cap > 0; i++) { if (cap & caps[i].cap) { cap &= ~caps[i].cap; if (n != 0) conCat(&string, ","); conCat(&string, caps[i].name); n++; } } /* Unknown capabilities */ if (cap) { if (n != 0) conCat(&string, ","); o_concatf (&string, "%x", cap); } } o_log(DEBUGM, "%s", string); free(string); // if (option->desc) // o_log(DEBUGM, " Description: %s", option->desc); }
extern SANE_Status control_option (SANE_Handle handle, const SANE_Option_Descriptor *option, SANE_Int index, SANE_Action action, void *value, int *ret) { SANE_Status status; char *old_value; switch (option->type) { case SANE_TYPE_BOOL: old_value = o_printf (*((SANE_Bool *) value) ? "SANE_TRUE" : "SANE_FALSE"); break; case SANE_TYPE_INT: old_value = o_printf ("%d", *((SANE_Int *) value)); break; case SANE_TYPE_FIXED: old_value = o_printf ("%f", SANE_UNFIX (*((SANE_Fixed *) value))); break; case SANE_TYPE_STRING: old_value = o_printf ("\"%s\"", (char *) value); break; default: old_value = o_strdup ("?"); break; } status = sane_control_option (handle, index, action, value, ret); switch (option->type) { case SANE_TYPE_BOOL: o_log(DEBUGM, "sane_control_option (%d, %s, %s) -> (%s, %s)", index, get_action_string (action), *((SANE_Bool *) value) ? "SANE_TRUE" : "SANE_FALSE", get_status_string (status), old_value); break; case SANE_TYPE_INT: o_log(DEBUGM, "sane_control_option (%d, %s, %d) -> (%s, %s)", index, get_action_string (action), *((SANE_Int *) value), get_status_string (status), old_value); break; case SANE_TYPE_FIXED: o_log(DEBUGM, "sane_control_option (%d, %s, %f) -> (%s, %s)", index, get_action_string (action), SANE_UNFIX (*((SANE_Fixed *) value)), get_status_string (status), old_value); break; case SANE_TYPE_STRING: o_log(DEBUGM, "sane_control_option (%d, %s, \"%s\") -> (%s, %s)", index, get_action_string (action), (char *) value, get_status_string (status), old_value); break; default: break; } free (old_value); if (status != SANE_STATUS_GOOD) o_log(WARNING, "Error setting option %s: %s", option->name, sane_strstatus(status)); return status; }
static SANE_Status scan_area_and_windows (Tamarack_Scanner *s) { struct def_win_par dwp; memset (&dwp,'\0',sizeof (dwp)); dwp.dwph.opc = TAMARACK_SCSI_AREA_AND_WINDOWS; set_triple (dwp.dwph.len,8 + sizeof (dwp.wdb)); set_double (dwp.wdh.wpll, sizeof (dwp.wdb)); dwp.wdb.winid = WINID; set_double (dwp.wdb.xres, (int) SANE_UNFIX (s->val[OPT_RESOLUTION].w)); set_double (dwp.wdb.yres, (int) SANE_UNFIX (s->val[OPT_RESOLUTION].w)); set_quad (dwp.wdb.ulx, (int) (47.2 * SANE_UNFIX (s->val[OPT_TL_X].w))); set_quad (dwp.wdb.uly, (int) (47.2 * SANE_UNFIX (s->val[OPT_TL_Y].w))); set_quad (dwp.wdb.width, (int) (47.2 * SANE_UNFIX (s->val[OPT_BR_X].w - s->val[OPT_TL_X].w))); set_quad (dwp.wdb.length, (int) (47.2 * SANE_UNFIX (s->val[OPT_BR_Y].w - s->val[OPT_TL_Y].w))); dwp.wdb.brightness = sign_mag (SANE_UNFIX (s->val[OPT_BRIGHTNESS].w)); dwp.wdb.contrast = sign_mag (SANE_UNFIX (s->val[OPT_CONTRAST].w)); dwp.wdb.thresh = 0x80; switch (s->mode) { case THRESHOLDED: dwp.wdb.bpp = 1; dwp.wdb.image_comp = 0; dwp.wdb.thresh = 1 + 2.55 * (SANE_UNFIX (s->val[OPT_THRESHOLD].w)); break; case DITHERED: dwp.wdb.bpp = 1; dwp.wdb.image_comp = 1; break; case GREYSCALE: dwp.wdb.bpp = 8; dwp.wdb.image_comp = 2; break; case TRUECOLOR: dwp.wdb.bpp = 8; dwp.wdb.image_comp = 2; break; default: DBG(1, "Invalid mode. %d\n", s->mode); return SANE_STATUS_INVAL; } DBG(1, "bright, thresh, contrast = %d(%5.1f), %d, %d(%5.1f)\n", dwp.wdb.brightness, SANE_UNFIX (s->val[OPT_BRIGHTNESS].w), dwp.wdb.thresh , dwp.wdb.contrast , SANE_UNFIX (s->val[OPT_CONTRAST].w)); set_double (dwp.wdb.halftone, 1); /* XXX What does this do again ? */ dwp.wdb.pad_type = 3; /* This is the only usable pad-type. */ dwp.wdb.exposure = 0x6f; /* XXX Option? */ dwp.wdb.compr_type = 0; /* XXX Shouldn't this be sizeof (dwp) */ return sanei_scsi_cmd (s->fd, &dwp, (10+8+38), 0, 0); }
/* This function is executed as a child process. The reason this is executed as a subprocess is because some (most?) generic SCSI interfaces block a SCSI request until it has completed. With a subprocess, we can let it block waiting for the request to finish while the main process can go about to do more important things (such as recognizing when the user presses a cancel button). WARNING: Since this is executed as a subprocess, it's NOT possible to update any of the variables in the main process (in particular the scanner state cannot be updated). */ static int reader_process (void *scanner) { Tamarack_Scanner *s = (Tamarack_Scanner *) scanner; int fd = s->reader_pipe; SANE_Byte *data; int lines_per_buffer, bpl; SANE_Status status; sigset_t sigterm_set; sigset_t ignore_set; struct SIGACTION act; FILE *fp; if (sanei_thread_is_forked()) close (s->pipe); sigfillset (&ignore_set); sigdelset (&ignore_set, SIGTERM); #if defined (__APPLE__) && defined (__MACH__) sigdelset (&ignore_set, SIGUSR2); #endif sigprocmask (SIG_SETMASK, &ignore_set, 0); memset (&act, 0, sizeof (act)); sigaction (SIGTERM, &act, 0); sigemptyset (&sigterm_set); sigaddset (&sigterm_set, SIGTERM); fp = fdopen (fd, "w"); if (!fp) return 1; bpl = s->params.bytes_per_line; lines_per_buffer = sanei_scsi_max_request_size / bpl; if (!lines_per_buffer) return 2; /* resolution is too high */ /* Limit the size of a single transfer to one inch. XXX Add a stripsize option. */ if (lines_per_buffer > SANE_UNFIX (s->val[OPT_RESOLUTION].w)) lines_per_buffer = SANE_UNFIX (s->val[OPT_RESOLUTION].w); DBG(3, "lines_per_buffer=%d, bytes_per_line=%d\n", lines_per_buffer, bpl); data = malloc (lines_per_buffer * bpl); for (s->line = 0; s->line < s->params.lines; s->line += lines_per_buffer) { if (s->line + lines_per_buffer > s->params.lines) /* do the last few lines: */ lines_per_buffer = s->params.lines - s->line; sigprocmask (SIG_BLOCK, &sigterm_set, 0); status = read_data (s, data, lines_per_buffer, bpl); sigprocmask (SIG_UNBLOCK, &sigterm_set, 0); if (status != SANE_STATUS_GOOD) { DBG(1, "reader_process: read_data failed with status=%d\n", status); return 3; } DBG(3, "reader_process: read %d lines\n", lines_per_buffer); if ((s->mode == TRUECOLOR) || (s->mode == GREYSCALE)) { fwrite (data, lines_per_buffer, bpl, fp); } else { /* in singlebit mode, the scanner returns 1 for black. ;-( --DM */ /* Hah! Same for Tamarack... -- REW */ int i; for (i = 0; i < lines_per_buffer * bpl; ++i) fputc (~data[i], fp); } } fclose (fp); return 0; }
SANE_Status sane_start (SANE_Handle handle) { Mustek_Usb_Scanner *s = handle; SANE_Status status; SANE_String val; Colormode color_mode; SANE_Word dpi, x, y, width, height; DBG (5, "sane_start: start\n"); /* First make sure we have a current parameter set. Some of the parameters will be overwritten below, but that's OK. */ s->total_bytes = 0; s->total_lines = 0; RIE (calc_parameters (s)); if (s->width_dots <= 0) { DBG (0, "sane_start: top left x > bottom right x --- exiting\n"); return SANE_STATUS_INVAL; } if (s->height_dots <= 0) { DBG (0, "sane_start: top left y > bottom right y --- exiting\n"); return SANE_STATUS_INVAL; } val = s->val[OPT_MODE].s; if (!strcmp (val, SANE_VALUE_SCAN_MODE_LINEART)) color_mode = GRAY8; else if (!strcmp (val, SANE_VALUE_SCAN_MODE_GRAY)) color_mode = GRAY8; else /* Color */ color_mode = RGB24; dpi = SANE_UNFIX (s->val[OPT_RESOLUTION].w); x = s->tl_x_dots; y = s->tl_y_dots; width = s->width_dots; height = s->height_dots; if (!s->hw->is_prepared) { RIE (usb_high_scan_prepare (s->hw)); RIE (usb_high_scan_reset (s->hw)); } RIE (usb_high_scan_set_threshold (s->hw, 128)); RIE (usb_high_scan_embed_gamma (s->hw, NULL)); RIE (usb_high_scan_suggest_parameters (s->hw, dpi, x, y, width, height, color_mode)); RIE (usb_high_scan_setup_scan (s->hw, s->hw->scan_mode, s->hw->x_dpi, s->hw->y_dpi, 0, s->hw->x, s->hw->y, s->hw->width)); DBG (3, "sane_start: wanted: dpi=%d, x=%d, y=%d, width=%d, height=%d, " "scan_mode=%d\n", dpi, x, y, width, height, color_mode); DBG (3, "sane_start: got: x_dpi=%d, y_dpi=%d, x=%d, y=%d, width=%d, " "height=%d, scan_mode=%d\n", s->hw->x_dpi, s->hw->y_dpi, s->hw->x, s->hw->y, s->hw->width, s->hw->height, s->hw->scan_mode); s->scanning = SANE_TRUE; s->read_rows = s->hw->height; s->hw->line_switch = s->hw->height; s->hw->line_offset = 0; s->hw->scan_buffer_len = 0; DBG (5, "sane_start: exit\n"); return SANE_STATUS_GOOD; }
/* Set scan parameters. If scan has started, use actual known parameters otherwise estimate. */ int bb_get_parameters(struct ledm_session *ps, SANE_Parameters *pp, int option) { struct bb_ledm_session *pbb = ps->bb_session; pp->last_frame = SANE_TRUE; int factor; _DBG("bb_get_parameters(option=%d)\n", option); switch(ps->currentScanMode) { case CE_K1: pp->format = SANE_FRAME_GRAY; /* lineart (GRAY8 converted to MONO by IP) */ pp->depth = 1; factor = 1; break; case CE_GRAY8: pp->format = SANE_FRAME_GRAY; /* grayscale */ pp->depth = 8; factor = 1; break; case CE_COLOR8: default: pp->format = SANE_FRAME_RGB; /* color */ pp->depth = 8; factor = 3; break; } switch (option) { case SPO_STARTED: /* called by xsane */ if (ps->currentCompression == SF_RAW && ps->currentScanMode != CE_GRAY8) { /* Set scan parameters based on scan job response values */ //pp->lines = pbb->job.lines; pp->lines = (int)(SANE_UNFIX(ps->effectiveBry - ps->effectiveTly)/MM_PER_INCH*ps->currentResolution); pp->pixels_per_line = pbb->job.pixels_per_line; pp->bytes_per_line = pbb->job.bytes_per_line; } else /* Must be SF_JFIF or ScanMode==CE_BLACK_AND_WHITE1. */ { /* Set scan parameters based on IP. Note for Linart, use IP for hpraw and jpeg. */ //pp->lines = ps->image_traits.lNumRows; pp->lines = (int)(SANE_UNFIX(ps->effectiveBry - ps->effectiveTly)/MM_PER_INCH*ps->currentResolution); pp->pixels_per_line = ps->image_traits.iPixelsPerRow; pp->bytes_per_line = BYTES_PER_LINE(pp->pixels_per_line, pp->depth * factor); } break; case SPO_STARTED_JR: /* called by sane_start */ /* Set scan parameters based on scan job response values */ pp->lines = pbb->job.lines; pp->pixels_per_line = pbb->job.pixels_per_line; pp->bytes_per_line = pbb->job.bytes_per_line; break; case SPO_BEST_GUESS: /* called by xsane & sane_start */ /* Set scan parameters based on best guess. */ pp->lines = (int)round(SANE_UNFIX(ps->effectiveBry - ps->effectiveTly)/MM_PER_INCH*ps->currentResolution); pp->pixels_per_line = (int)round(SANE_UNFIX(ps->effectiveBrx -ps->effectiveTlx)/MM_PER_INCH*ps->currentResolution); pp->bytes_per_line = BYTES_PER_LINE(pp->pixels_per_line, pp->depth * factor); break; default: break; } return 0; }
SANE_Status kv_control_option (PKV_DEV dev, SANE_Int option, SANE_Action action, void *val, SANE_Int * info) { SANE_Status status; SANE_Word cap; SANE_String_Const name; int i; SANE_Word value; DBG (DBG_proc, "sane_control_option: enter, option %s, action %s\n", go_option_name[option], action == SANE_ACTION_GET_VALUE ? "R" : "W"); if (info) { *info = 0; } if (dev->scanning) { return SANE_STATUS_DEVICE_BUSY; } if (option < 0 || option >= OPT_NUM_OPTIONS) { return SANE_STATUS_UNSUPPORTED; } cap = dev->opt[option].cap; if (!SANE_OPTION_IS_ACTIVE (cap)) { return SANE_STATUS_UNSUPPORTED; } name = dev->opt[option].name; if (!name) { name = "(no name)"; } if (action == SANE_ACTION_GET_VALUE) { switch (option) { /* word options */ case OPT_NUM_OPTS: case OPT_LONGPAPER: case OPT_LENGTHCTL: case OPT_DBLFEED: case OPT_RESOLUTION: case OPT_TL_Y: case OPT_BR_Y: case OPT_TL_X: case OPT_BR_X: case OPT_BRIGHTNESS: case OPT_CONTRAST: case OPT_DUPLEX: case OPT_LANDSCAPE: case OPT_AUTOMATIC_SEPARATION: case OPT_INVERSE: case OPT_MIRROR: case OPT_FEED_TIMEOUT: case OPT_JPEG: case OPT_FIT_TO_PAGE: *(SANE_Word *) val = dev->val[option].w; DBG (DBG_error, "opt value = %d\n", *(SANE_Word *) val); return SANE_STATUS_GOOD; /* string options */ case OPT_MODE: case OPT_FEEDER_MODE: case OPT_SCAN_SOURCE: case OPT_MANUALFEED: case OPT_HALFTONE_PATTERN: case OPT_PAPER_SIZE: case OPT_AUTOMATIC_THRESHOLD: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_LAMP: strcpy (val, dev->val[option].s); DBG (DBG_error, "opt value = %s\n", (char *) val); return SANE_STATUS_GOOD; default: return SANE_STATUS_UNSUPPORTED; } } else if (action == SANE_ACTION_SET_VALUE) { if (!SANE_OPTION_IS_SETTABLE (cap)) { DBG (DBG_error, "could not set option %s, not settable\n", go_option_name[option]); return SANE_STATUS_INVAL; } status = sanei_constrain_value (dev->opt + option, val, info); if (status != SANE_STATUS_GOOD) { DBG (DBG_error, "could not set option, invalid value\n"); return status; } switch (option) { /* Side-effect options */ case OPT_TL_Y: case OPT_BR_Y: case OPT_RESOLUTION: if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } dev->val[option].w = *(SANE_Word *) val; if (option == OPT_RESOLUTION) { if (round_to_boundry (&(dev->val[option].w), dev->support_info. step_resolution, 100, 600)) { if (info) { *info |= SANE_INFO_INEXACT; } } } else if (option == OPT_TL_Y) { if (dev->val[option].w > dev->val[OPT_BR_Y].w) { dev->val[option].w = dev->val[OPT_BR_Y].w; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } else { if (dev->val[option].w < dev->val[OPT_TL_Y].w) { dev->val[option].w = dev->val[OPT_TL_Y].w; if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } DBG (DBG_error, "option %s, input = %d, value = %d\n", go_option_name[option], (*(SANE_Word *) val), dev->val[option].w); return SANE_STATUS_GOOD; /* The length of X must be rounded (up). */ case OPT_TL_X: case OPT_BR_X: { SANE_Word xr = dev->val[OPT_RESOLUTION].w; SANE_Word tl_x = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)) * xr; SANE_Word br_x = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)) * xr; value = mmToIlu (SANE_UNFIX (*(SANE_Word *) val)) * xr; /* XR * W */ if (option == OPT_TL_X) { SANE_Word max = KV_PIXEL_MAX * xr - KV_PIXEL_ROUND; if (br_x < max) max = br_x; if (round_to_boundry (&value, KV_PIXEL_ROUND, 0, max)) { if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } else { if (round_to_boundry (&value, KV_PIXEL_ROUND, tl_x, KV_PIXEL_MAX * xr)) { if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_INEXACT; } } } dev->val[option].w = SANE_FIX (iluToMm ((double) value / xr)); if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } DBG (DBG_error, "option %s, input = %d, value = %d\n", go_option_name[option], (*(SANE_Word *) val), dev->val[option].w); return SANE_STATUS_GOOD; } case OPT_LANDSCAPE: dev->val[option].w = *(SANE_Word *) val; if (info) { *info |= SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; /* Side-effect free options */ case OPT_CONTRAST: case OPT_BRIGHTNESS: case OPT_DUPLEX: case OPT_LONGPAPER: case OPT_LENGTHCTL: case OPT_DBLFEED: case OPT_INVERSE: case OPT_MIRROR: case OPT_AUTOMATIC_SEPARATION: case OPT_JPEG: case OPT_FIT_TO_PAGE: dev->val[option].w = *(SANE_Word *) val; return SANE_STATUS_GOOD; case OPT_FEED_TIMEOUT: dev->val[option].w = *(SANE_Word *) val; return CMD_set_timeout (dev, *(SANE_Word *) val); /* String mode */ case OPT_SCAN_SOURCE: case OPT_WHITE_LEVEL: case OPT_NOISE_REDUCTION: case OPT_IMAGE_EMPHASIS: case OPT_GAMMA: case OPT_LAMP: case OPT_HALFTONE_PATTERN: case OPT_FEEDER_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); if (option == OPT_FEEDER_MODE && get_string_list_index (go_feeder_mode_list, dev->val[option].s) == 1) /* continuous mode */ { free (dev->val[OPT_SCAN_SOURCE].s); dev->val[OPT_SCAN_SOURCE].s = strdup (go_scan_source_list[0]); dev->opt[OPT_LONGPAPER].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } else { dev->opt[OPT_LONGPAPER].cap |= SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; } if (option == OPT_SCAN_SOURCE && get_string_list_index (go_scan_source_list, dev->val[option].s) == 1) /* flatbed */ { free (dev->val[OPT_FEEDER_MODE].s); dev->val[OPT_FEEDER_MODE].s = strdup (go_feeder_mode_list[0]); } return SANE_STATUS_GOOD; case OPT_MODE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_MODE].s); dev->val[OPT_MODE].s = (SANE_String) strdup (val); /* Set default options for the scan modes. */ dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_THRESHOLD].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[0]) == 0) /* binary */ { dev->opt[OPT_AUTOMATIC_THRESHOLD].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0) /* halftone */ { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_INVERSE].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_JPEG].cap |= SANE_CAP_INACTIVE; } else if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[2]) == 0) /* grayscale */ { dev->opt[OPT_GAMMA].cap &= ~SANE_CAP_INACTIVE; } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; case OPT_MANUALFEED: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_String) strdup (val); if (strcmp (dev->val[option].s, go_manual_feed_list[0]) == 0) /* off */ dev->opt[OPT_FEED_TIMEOUT].cap |= SANE_CAP_INACTIVE; else dev->opt[OPT_FEED_TIMEOUT].cap &= ~SANE_CAP_INACTIVE; if (info) *info |= SANE_INFO_RELOAD_OPTIONS; return SANE_STATUS_GOOD; case OPT_PAPER_SIZE: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[OPT_PAPER_SIZE].s); dev->val[OPT_PAPER_SIZE].s = (SANE_Char *) strdup (val); i = get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE].s); if (i == 0) { /*user def */ dev->opt[OPT_TL_X].cap &= dev->opt[OPT_TL_Y].cap &= dev->opt[OPT_BR_X].cap &= dev->opt[OPT_BR_Y].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE; dev->val[OPT_LANDSCAPE].w = 0; } else { dev->opt[OPT_TL_X].cap |= dev->opt[OPT_TL_Y].cap |= dev->opt[OPT_BR_X].cap |= dev->opt[OPT_BR_Y].cap |= SANE_CAP_INACTIVE; if (i == 4 || i == 5 || i == 7) { /*A5, A6 or B6 */ dev->opt[OPT_LANDSCAPE].cap &= ~SANE_CAP_INACTIVE; } else { dev->opt[OPT_LANDSCAPE].cap |= SANE_CAP_INACTIVE; dev->val[OPT_LANDSCAPE].w = 0; } } if (info) *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; return SANE_STATUS_GOOD; case OPT_AUTOMATIC_THRESHOLD: if (strcmp (dev->val[option].s, val) == 0) return SANE_STATUS_GOOD; free (dev->val[option].s); dev->val[option].s = (SANE_Char *) strdup (val); /* If the threshold is not set to none, some option must * disappear. */ dev->opt[OPT_WHITE_LEVEL].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap |= SANE_CAP_INACTIVE; dev->opt[OPT_HALFTONE_PATTERN].cap |= SANE_CAP_INACTIVE; if (strcmp (val, go_automatic_threshold_list[0]) == 0) { dev->opt[OPT_WHITE_LEVEL].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_NOISE_REDUCTION].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_IMAGE_EMPHASIS].cap &= ~SANE_CAP_INACTIVE; dev->opt[OPT_AUTOMATIC_SEPARATION].cap &= ~SANE_CAP_INACTIVE; if (strcmp (dev->val[OPT_MODE].s, go_scan_mode_list[1]) == 0) { dev->opt[OPT_HALFTONE_PATTERN].cap &= ~SANE_CAP_INACTIVE; } } if (info) { *info |= SANE_INFO_RELOAD_OPTIONS | SANE_INFO_RELOAD_PARAMS; } return SANE_STATUS_GOOD; default: return SANE_STATUS_INVAL; } } DBG (DBG_proc, "sane_control_option: exit, bad\n"); return SANE_STATUS_UNSUPPORTED; }
SANE_Status sane_get_parameters (SANE_Handle handle, SANE_Parameters * params) { Leo_Scanner *dev = handle; DBG (DBG_proc, "sane_get_parameters: enter\n"); if (!(dev->scanning)) { /* Setup the parameters for the scan. These values will be re-used * in the SET WINDOWS command. */ if (dev->val[OPT_PREVIEW].w == SANE_TRUE) { dev->x_resolution = 28; dev->y_resolution = 28; dev->x_tl = 0; dev->y_tl = 0; dev->x_br = mmToIlu (SANE_UNFIX (x_range.max)); dev->y_br = mmToIlu (SANE_UNFIX (y_range.max)); } else { dev->x_resolution = dev->val[OPT_RESOLUTION].w; dev->y_resolution = dev->val[OPT_RESOLUTION].w; dev->x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); dev->y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); dev->x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); dev->y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); } /* Check the corners are OK. */ if (dev->x_tl > dev->x_br) { int s; s = dev->x_tl; dev->x_tl = dev->x_br; dev->x_br = s; } if (dev->y_tl > dev->y_br) { int s; s = dev->y_tl; dev->y_tl = dev->y_br; dev->y_br = s; } dev->width = dev->x_br - dev->x_tl; dev->length = dev->y_br - dev->y_tl; /* Prepare the parameters for the caller. */ memset (&dev->params, 0, sizeof (SANE_Parameters)); dev->params.last_frame = SANE_TRUE; switch (dev->scan_mode) { case LEO_BW: case LEO_HALFTONE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = dev->width & ~0x7; dev->params.bytes_per_line = dev->params.pixels_per_line / 8; dev->params.depth = 1; break; case LEO_GRAYSCALE: dev->params.format = SANE_FRAME_GRAY; dev->params.pixels_per_line = dev->width; dev->params.bytes_per_line = dev->params.pixels_per_line; dev->params.depth = 8; break; case LEO_COLOR: dev->params.format = SANE_FRAME_RGB; dev->params.pixels_per_line = dev->width; dev->params.bytes_per_line = dev->params.pixels_per_line * 3; dev->params.depth = 8; break; } dev->params.lines = dev->length; } /* Return the current values. */ if (params) { *params = (dev->params); } DBG (DBG_proc, "sane_get_parameters: exit\n"); return SANE_STATUS_GOOD; }
/* Set window data */ void kv_set_window_data (PKV_DEV dev, KV_SCAN_MODE scan_mode, int side, unsigned char *windowdata) { int paper = go_paper_val[get_string_list_index (go_paper_list, dev->val[OPT_PAPER_SIZE]. s)]; /* Page side */ windowdata[0] = side; /* X and Y resolution */ Ito16 (dev->val[OPT_RESOLUTION].w, &windowdata[2]); Ito16 (dev->val[OPT_RESOLUTION].w, &windowdata[4]); /* Width and length */ if (paper == 0) { /* Non-standard document */ int x_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_X].w)); int y_tl = mmToIlu (SANE_UNFIX (dev->val[OPT_TL_Y].w)); int x_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_X].w)); int y_br = mmToIlu (SANE_UNFIX (dev->val[OPT_BR_Y].w)); int width = x_br - x_tl; int length = y_br - y_tl; /* Upper Left (X,Y) */ Ito32 (x_tl, &windowdata[6]); Ito32 (y_tl, &windowdata[10]); Ito32 (width, &windowdata[14]); Ito32 (length, &windowdata[18]); Ito32 (width, &windowdata[48]); /* device specific */ Ito32 (length, &windowdata[52]); /* device specific */ } /* Brightness */ windowdata[22] = 255 - GET_OPT_VAL_W (dev, OPT_BRIGHTNESS); windowdata[23] = windowdata[22]; /* threshold, same as brightness. */ /* Contrast */ windowdata[24] = GET_OPT_VAL_W (dev, OPT_CONTRAST); /* Image Composition */ windowdata[25] = (unsigned char) scan_mode; /* Depth */ windowdata[26] = kv_get_depth (scan_mode); /* Halftone pattern. */ if (scan_mode == SM_DITHER) { windowdata[28] = GET_OPT_VAL_L (dev, OPT_HALFTONE_PATTERN, halftone_pattern); } /* Inverse */ if (scan_mode == SM_BINARY || scan_mode == SM_DITHER) { windowdata[29] = GET_OPT_VAL_W (dev, OPT_INVERSE); } /* Bit ordering */ windowdata[31] = 1; /*Compression Type */ if (!(dev->opt[OPT_JPEG].cap & SANE_CAP_INACTIVE) && GET_OPT_VAL_W (dev, OPT_JPEG)) { windowdata[32] = 0x81; /*jpeg */ /*Compression Argument */ windowdata[33] = GET_OPT_VAL_W (dev, OPT_JPEG); } /* Gamma */ if (scan_mode == SM_DITHER || scan_mode == SM_GRAYSCALE) { windowdata[44] = GET_OPT_VAL_L (dev, OPT_GAMMA, gamma); } /* Feeder mode */ windowdata[57] = GET_OPT_VAL_L (dev, OPT_FEEDER_MODE, feeder_mode); /* Stop skew -- disabled */ windowdata[41] = 0; /* Scan source */ if (GET_OPT_VAL_L (dev, OPT_SCAN_SOURCE, scan_source)) { /* flatbed */ windowdata[41] |= 0x80; } else { windowdata[41] &= 0x7f; } /* Paper size */ windowdata[47] = paper; if (paper) /* Standard Document */ windowdata[47] |= 1 << 7; /* Long paper */ if (GET_OPT_VAL_W (dev, OPT_LONGPAPER)) { windowdata[47] |= 0x20; } /* Length control */ if (GET_OPT_VAL_W (dev, OPT_LENGTHCTL)) { windowdata[47] |= 0x40; } /* Landscape */ if (GET_OPT_VAL_W (dev, OPT_LANDSCAPE)) { windowdata[47] |= 1 << 4; } /* Double feed */ if (GET_OPT_VAL_W (dev, OPT_DBLFEED)) { windowdata[56] = 0x10; } /* Fit to page */ if (GET_OPT_VAL_W (dev, OPT_FIT_TO_PAGE)) { windowdata[56] |= 1 << 2; } /* Manual feed */ windowdata[62] = GET_OPT_VAL_L (dev, OPT_MANUALFEED, manual_feed) << 6; /* Mirror image */ if (GET_OPT_VAL_W (dev, OPT_MIRROR)) { windowdata[42] = 0x80; } /* Image emphasis */ windowdata[43] = GET_OPT_VAL_L (dev, OPT_IMAGE_EMPHASIS, image_emphasis); /* White level */ windowdata[60] = GET_OPT_VAL_L (dev, OPT_WHITE_LEVEL, white_level); if (scan_mode == SM_BINARY || scan_mode == SM_DITHER) { /* Noise reduction */ windowdata[61] = GET_OPT_VAL_L (dev, OPT_NOISE_REDUCTION, noise_reduction); /* Automatic separation */ if (scan_mode == SM_DITHER && GET_OPT_VAL_W (dev, OPT_AUTOMATIC_SEPARATION)) { windowdata[59] = 0x80; } } /* Automatic threshold. Must be last because it may override * some previous options. */ if (scan_mode == SM_BINARY) { windowdata[58] = GET_OPT_VAL_L (dev, OPT_AUTOMATIC_THRESHOLD, automatic_threshold); } if (windowdata[58] != 0) { /* Automatic threshold is enabled. */ windowdata[22] = 0; /* brightness. */ windowdata[23] = 0; /* threshold, same as brightness. */ windowdata[24] = 0; /* contrast */ windowdata[27] = windowdata[28] = 0; /* Halftone pattern. */ windowdata[43] = 0; /* Image emphasis */ windowdata[59] = 0; /* Automatic separation */ windowdata[60] = 0; /* White level */ windowdata[61] = 0; /* Noise reduction */ } /* lamp -- color dropout */ windowdata[45] = GET_OPT_VAL_L (dev, OPT_LAMP, lamp) << 4; /*Stop Mode: After 1 page */ windowdata[63] = 1; }