Example #1
0
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;
}
Example #2
0
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);
	}
    }
}
Example #3
0
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);
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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;
}
Example #7
0
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;
}
Example #8
0
/* 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;
}
Example #9
0
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;
}
Example #10
0
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;
}
Example #11
0
/*--------------------------------------------------------------------------*/
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;
}
Example #12
0
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;
}
Example #13
0
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;
}
Example #14
0
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);
}
Example #16
0
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;
}
Example #17
0
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();
}
Example #18
0
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);
}
Example #19
0
File: _sane.c Project: Bouke/Pillow
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);
Example #20
0
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;
}
Example #21
0
extern char *internalGetScannerDetails(char *device, char *lang) {

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

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


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

    const SANE_Option_Descriptor *sod;

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

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

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

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

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

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

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

      }

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


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

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

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



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


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

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

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

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

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

  return answer;

}
Example #22
0
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);
}
Example #23
0
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;
}
Example #24
0
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);
}
Example #25
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;
}
Example #26
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;
}
Example #27
0
/* 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;
}
Example #28
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;
}
Example #29
0
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;
}
Example #30
0
/* 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;
}