summaryrefslogtreecommitdiff
path: root/japi
diff options
context:
space:
mode:
authorJörg Frings-Fürst <debian@jff-webhosting.net>2014-10-06 14:00:40 +0200
committerJörg Frings-Fürst <debian@jff-webhosting.net>2014-10-06 14:00:40 +0200
commit6e9c41a892ed0e0da326e0278b3221ce3f5713b8 (patch)
tree2e301d871bbeeb44aa57ff9cc070fcf3be484487 /japi
Initial import of sane-backends version 1.0.24-1.2
Diffstat (limited to 'japi')
-rw-r--r--japi/ImageCanvas.java110
-rw-r--r--japi/ImageCanvasClient.java54
-rw-r--r--japi/Jscanimage.java1166
-rw-r--r--japi/Makefile.am47
-rw-r--r--japi/Makefile.in738
-rw-r--r--japi/README.JAVA55
-rw-r--r--japi/Sane.c493
-rw-r--r--japi/Sane.java144
-rw-r--r--japi/SaneDevice.java55
-rw-r--r--japi/SaneOption.java145
-rw-r--r--japi/SaneParameters.java68
-rw-r--r--japi/SaneRange.java53
-rw-r--r--japi/ScanIt.java391
-rw-r--r--japi/Test.java175
14 files changed, 3694 insertions, 0 deletions
diff --git a/japi/ImageCanvas.java b/japi/ImageCanvas.java
new file mode 100644
index 0000000..56cf34c
--- /dev/null
+++ b/japi/ImageCanvas.java
@@ -0,0 +1,110 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+/**
+ ** ImageCanvas.java - A canvas that displays an image.
+ **
+ ** Written: 11/4/97 - JSF
+ **/
+
+import java.awt.Canvas;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.image.ImageProducer;
+
+/*
+ * Here's a canvas that just shows an image.
+ */
+
+public class ImageCanvas extends Canvas
+ {
+ Image image = null; // The image to display.
+ ImageCanvasClient client = null; // 1 client for now.
+
+ /*
+ * Create with empty image.
+ */
+ ImageCanvas()
+ {
+ }
+
+ /*
+ * Create image from an image producer.
+ */
+ void setImage(ImageProducer iprod, ImageCanvasClient c)
+ {
+ client = c;
+ image = createImage(iprod);
+ repaint();
+ }
+
+ /*
+ * Paint.
+ */
+ public void paint(Graphics g)
+ {
+ System.out.println("In ImageCanvas.paint()");
+ Dimension dim = getSize();
+ g.drawRect(0, 0, dim.width - 1, dim.height - 1);
+ if (image != null)
+ {
+ g.drawImage(image, 1, 1, dim.width - 2, dim.height - 2, this);
+ }
+ }
+
+ /*
+ * Image has been updated.
+ */
+ public boolean imageUpdate(Image theimg, int infoflags,
+ int x, int y, int w, int h)
+ {
+ System.out.println("In imageUpdate()");
+ boolean done = ((infoflags & (ERROR | FRAMEBITS | ALLBITS)) != 0);
+// repaint();
+ paint(getGraphics());
+ if (done && client != null) // Tell client when done.
+ {
+ client.imageDone((infoflags & ERROR) != 0);
+ client = null;
+ }
+ return (!done);
+ }
+ }
diff --git a/japi/ImageCanvasClient.java b/japi/ImageCanvasClient.java
new file mode 100644
index 0000000..f9caebe
--- /dev/null
+++ b/japi/ImageCanvasClient.java
@@ -0,0 +1,54 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+/**
+ ** ImageCanvasClient.java - A client of the canvas that displays an image.
+ **
+ ** Written: 11/20/97 - JSF
+ **/
+
+/*
+ * This interface lets its owner know when an image canvas is through
+ * being painted.
+ */
+interface ImageCanvasClient
+ {
+ void imageDone(boolean failed); // Image is complete.
+ }
diff --git a/japi/Jscanimage.java b/japi/Jscanimage.java
new file mode 100644
index 0000000..d3ab32d
--- /dev/null
+++ b/japi/Jscanimage.java
@@ -0,0 +1,1166 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+/**
+ ** Jscanimage.java - Java scanner program using SANE.
+ **
+ ** Written: 10/31/97 - JSF
+ **/
+
+import java.awt.*;
+import java.awt.event.*;
+import java.util.*;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ColorModel;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.text.NumberFormat;
+import javax.swing.*;
+import javax.swing.border.*;
+import javax.swing.event.*;
+
+/*
+ * Main program.
+ */
+public class Jscanimage extends Frame implements WindowListener,
+ ActionListener, ItemListener, ImageCanvasClient
+ {
+ //
+ // Static data.
+ //
+ private static Sane sane; // The main class.
+ private static SaneDevice devList[];// List of devices.
+ //
+ // Instance data.
+ //
+ private Font font; // For dialog items.
+ private int saneHandle; // Handle of open device.
+ private ScanIt scanIt = null; // Does the actual scan.
+ // File to output to.
+ private FileOutputStream outFile = null;
+ private String outDir = null; // Stores dir. for output dialog.
+ private Vector controls; // Dialog components for SANE controls.
+ private double unitLength = 1; // # of mm for units to display
+ // (mm = 1, cm = 10, in = 25.4).
+ private ImageCanvas imageDisplay = null;
+ // "Scan", "Preview" buttons.
+ private JButton scanButton, previewButton;
+ private JButton browseButton; // For choosing output filename.
+ private JTextField outputField; // Field for output filename.
+ private MenuItem exitMenuItem; // Menu items.
+ private CheckboxMenuItem toolTipsMenuItem;
+ private CheckboxMenuItem mmMenuItem;
+ private CheckboxMenuItem cmMenuItem;
+ private CheckboxMenuItem inMenuItem;
+
+ /*
+ * Main program.
+ */
+ public static void main(String args[])
+ {
+ if (!initSane()) // Initialize SANE.
+ return;
+ Jscanimage prog = new Jscanimage();
+ prog.pack();
+ prog.show();
+ }
+
+ /*
+ * Create main window.
+ */
+ public Jscanimage()
+ {
+ super("SANE Scanimage");
+ addWindowListener(this);
+ // Open SANE device.
+ saneHandle = initSaneDevice(devList[0].name);
+ if (saneHandle == 0)
+ System.exit(-1);
+ // Create scanner class.
+ scanIt = new ScanIt(sane, saneHandle);
+ init();
+ }
+
+ /*
+ * Clean up.
+ */
+ public void finalize()
+ {
+ if (sane != null)
+ {
+ if (saneHandle != 0)
+ sane.close(saneHandle);
+ sane.exit();
+ sane = null;
+ }
+ saneHandle = 0;
+ if (outFile != null)
+ {
+ try
+ {
+ outFile.close();
+ }
+ catch (IOException e)
+ { }
+ outFile = null;
+ }
+ System.out.println("In finalize()");
+ }
+
+ /*
+ * Return info.
+ */
+ public Sane getSane()
+ { return sane; }
+ public int getSaneHandle()
+ { return saneHandle; }
+ public double getUnitLength()
+ { return unitLength; }
+
+ /*
+ * Initialize SANE.
+ */
+ private static boolean initSane()
+ {
+ sane = new Sane();
+ int version[] = new int[1]; // Array to get version #.
+ int status = sane.init(version);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("getDevices() failed. Status= " + status);
+ return (false);
+ }
+ // Get list of devices.
+ // Allocate room for 50.
+ devList = new SaneDevice[50];
+ status = sane.getDevices(devList, false);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("getDevices() failed. Status= " + status);
+ return (false);
+ }
+ for (int i = 0; i < 50 && devList[i] != null; i++)
+ {
+ System.out.println("Device '" + devList[i].name + "' is a " +
+ devList[i].vendor + " " + devList[i].model + " " +
+ devList[i].type);
+ }
+ return (true);
+ }
+
+ /*
+ * Open device.
+ *
+ * Output: Handle, or 0 if error.
+ */
+ private int initSaneDevice(String name)
+ {
+ int handle[] = new int[1];
+ // Open 1st device, for now.
+ int status = sane.open(name, handle);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("open() failed. Status= " + status);
+ return (0);
+ }
+ setTitle("SANE - " + name);
+ System.out.println("Open handle=" + handle[0]);
+ return (handle[0]);
+ }
+
+ /*
+ * Add a labeled option to the main dialog.
+ */
+ private void addLabeledOption(JPanel group, String title, Component opt,
+ GridBagConstraints c)
+ {
+ JLabel label = new JLabel(title);
+ c.gridwidth = GridBagConstraints.RELATIVE;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ c.weightx = .1;
+ group.add(label, c);
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = .4;
+ group.add(opt, c);
+ }
+
+ /*
+ * Get options for device.
+ */
+ private boolean initSaneOptions()
+ {
+ JPanel group = null;
+ GridBagConstraints c = new GridBagConstraints();
+ c.weightx = .4;
+ c.weighty = .4;
+ // Get # of device options.
+ int numDevOptions[] = new int[1];
+ int status = sane.getControlOption(saneHandle, 0, numDevOptions, null);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("controlOption() failed. Status= "
+ + status);
+ return (false);
+ }
+ System.out.println("Number of device options=" + numDevOptions[0]);
+ // Do each option.
+ for (int i = 0; i < numDevOptions[0]; i++)
+ {
+ SaneOption opt = sane.getOptionDescriptor(saneHandle, i);
+ if (opt == null)
+ {
+ System.out.println("getOptionDescriptor() failed for "
+ + i);
+ continue;
+ }
+/*
+ System.out.println("Option title: " + opt.title);
+ System.out.println("Option desc: " + opt.desc);
+ System.out.println("Option type: " + opt.type);
+ */
+ String title; // Set up title.
+ if (opt.unit == SaneOption.UNIT_NONE)
+ title = opt.title;
+ else // Show units.
+ title = opt.title + " [" +
+ opt.unitString(unitLength) + ']';
+ switch (opt.type)
+ {
+ case SaneOption.TYPE_GROUP:
+ // Group for a set of options.
+ group = new JPanel(new GridBagLayout());
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.fill = GridBagConstraints.BOTH;
+ c.anchor = GridBagConstraints.CENTER;
+ add(group, c);
+ group.setBorder(new TitledBorder(title));
+ break;
+ case SaneOption.TYPE_BOOL:
+ // A checkbox.
+ SaneCheckBox cbox = new SaneCheckBox(opt.title,
+ this, i, opt.desc);
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.fill = GridBagConstraints.NONE;
+ c.anchor = GridBagConstraints.WEST;
+ if (group != null)
+ group.add(cbox, c);
+ addControl(cbox);
+ break;
+ case SaneOption.TYPE_FIXED:
+ // Fixed-point value.
+ if (opt.size != 4)
+ break; // Not sure about this.
+ switch (opt.constraintType)
+ {
+ case SaneOption.CONSTRAINT_RANGE:
+ // A scale.
+ SaneSlider slider = new FixedSaneSlider(
+ opt.rangeConstraint.min,
+ opt.rangeConstraint.max,
+ opt.unit == SaneOption.UNIT_MM,
+ this, i, opt.desc);
+ addLabeledOption(group, title, slider, c);
+ addControl(slider);
+ break;
+ case SaneOption.CONSTRAINT_WORD_LIST:
+ // Select from a list.
+ SaneFixedBox list = new SaneFixedBox(
+ this, i, opt.desc);
+ addLabeledOption(group, title, list, c);
+ addControl(list);
+ break;
+ }
+ break;
+ case SaneOption.TYPE_INT:
+ // Integer value.
+ if (opt.size != 4)
+ break; // Not sure about this.
+ switch (opt.constraintType)
+ {
+ case SaneOption.CONSTRAINT_RANGE:
+ // A scale.
+ SaneSlider slider = new SaneSlider(
+ opt.rangeConstraint.min,
+ opt.rangeConstraint.max,
+ this, i, opt.desc);
+ addLabeledOption(group, title, slider, c);
+ addControl(slider);
+ break;
+ case SaneOption.CONSTRAINT_WORD_LIST:
+ // Select from a list.
+ SaneIntBox list = new SaneIntBox(
+ this, i, opt.desc);
+ addLabeledOption(group, title, list, c);
+ addControl(list);
+ break;
+ }
+ break;
+ case SaneOption.TYPE_STRING:
+ // Text entry or choice box.
+ switch (opt.constraintType)
+ {
+ case SaneOption.CONSTRAINT_STRING_LIST:
+ // Make a list.
+ SaneStringBox list = new SaneStringBox(
+ this, i, opt.desc);
+ addLabeledOption(group, title, list, c);
+ addControl(list);
+ break;
+ case SaneOption.CONSTRAINT_NONE:
+ SaneTextField tfield = new SaneTextField(16,
+ this, i, opt.desc);
+ addLabeledOption(group, title, tfield, c);
+ addControl(tfield);
+ break;
+ }
+ break;
+ case SaneOption.TYPE_BUTTON:
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = new Insets(8, 4, 4, 4);
+ JButton btn = new SaneButton(title, this, i, opt.desc);
+ group.add(btn, c);
+ c.insets = null;
+ break;
+ default:
+ break;
+ }
+ }
+ return (true);
+ }
+
+ /*
+ * Set up "Output" panel.
+ */
+ private JPanel initOutputPanel()
+ {
+ JPanel panel = new JPanel(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+ // Want 1 row.
+ c.gridx = GridBagConstraints.RELATIVE;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.WEST;
+// c.fill = GridBagConstraints.HORIZONTAL;
+ c.weightx = .4;
+ c.weighty = .4;
+ panel.setBorder(new TitledBorder("Output"));
+ panel.add(new Label("Filename"), c);
+ outputField = new JTextField("out.pnm", 16);
+ panel.add(outputField, c);
+ c.insets = new Insets(0, 8, 0, 0);
+ browseButton = new JButton("Browse");
+ browseButton.addActionListener(this);
+ panel.add(browseButton, c);
+ return (panel);
+ }
+
+ /*
+ * Initialize main window.
+ */
+ private void init()
+ {
+ controls = new Vector(); // List of SaneComponent's.
+ // Try a light blue:
+ setBackground(new Color(140, 200, 255));
+ // And a larger font.
+ font = new Font("Helvetica", Font.PLAIN, 12);
+ setFont(font);
+ initMenu();
+ // Main panel will be 1 column.
+ setLayout(new GridBagLayout());
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.fill = GridBagConstraints.BOTH;
+ c.weightx = .4;
+ c.weighty = .4;
+ // Panel for output:
+ JPanel outputPanel = initOutputPanel();
+ add(outputPanel, c);
+ initSaneOptions(); // Get SANE options, set up dialog.
+ initButtons(); // Put buttons at bottom.
+ }
+
+ /*
+ * Add a control to the dialog and set its initial value.
+ */
+ private void addControl(SaneComponent comp)
+ {
+ controls.addElement(comp);
+ comp.setFromControl(); // Get initial value.
+ }
+
+ /*
+ * Reinitialize components from SANE controls.
+ */
+ private void reinit()
+ {
+ Enumeration ctrls = controls.elements();
+ while (ctrls.hasMoreElements()) // Do each control.
+ {
+ SaneComponent comp = (SaneComponent) ctrls.nextElement();
+ comp.setFromControl();
+ }
+ }
+
+ /*
+ * Set up the menubar.
+ */
+ private void initMenu()
+ {
+ MenuBar mbar = new MenuBar();
+ Menu file = new Menu("File");
+ mbar.add(file);
+ exitMenuItem = new MenuItem("Exit");
+ exitMenuItem.addActionListener(this);
+ file.add(exitMenuItem);
+ Menu pref = new Menu("Preferences");
+ mbar.add(pref);
+ toolTipsMenuItem = new CheckboxMenuItem("Show tooltips", true);
+ toolTipsMenuItem.addItemListener(this);
+ pref.add(toolTipsMenuItem);
+ Menu units = new Menu("Length unit");
+ pref.add(units);
+ mmMenuItem = new CheckboxMenuItem("millimeters", true);
+ mmMenuItem.addItemListener(this);
+ units.add(mmMenuItem);
+ cmMenuItem = new CheckboxMenuItem("centimeters", false);
+ cmMenuItem.addItemListener(this);
+ units.add(cmMenuItem);
+ inMenuItem = new CheckboxMenuItem("inches", false);
+ inMenuItem.addItemListener(this);
+ units.add(inMenuItem);
+ setMenuBar(mbar);
+ }
+
+ /*
+ * Set up buttons panel at very bottom.
+ */
+ private void initButtons()
+ {
+ // Buttons are at bottom.
+ JPanel bottomPanel = new JPanel(new GridBagLayout());
+ // Indent around buttons.
+ GridBagConstraints c = new GridBagConstraints();
+ c.gridwidth = GridBagConstraints.REMAINDER;
+ c.insets = new Insets(8, 8, 8, 8);
+ c.weightx = .4;
+ c.weighty = .2;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ add(bottomPanel, c);
+ c.weighty = c.weightx = .4;
+ c.fill = GridBagConstraints.BOTH;
+ c.gridwidth = c.gridheight = 1;
+ // Create image display box.
+ imageDisplay = new ImageCanvas();
+ bottomPanel.add(imageDisplay, c);
+ // Put btns. to right in 1 column.
+ JPanel buttonsPanel = new JPanel(new GridLayout(0, 1, 8, 8));
+ bottomPanel.add(buttonsPanel, c);
+ scanButton = new JButton("Scan");
+ buttonsPanel.add(scanButton);
+ scanButton.addActionListener(this);
+ previewButton = new JButton("Preview Window");
+ buttonsPanel.add(previewButton);
+ previewButton.addActionListener(this);
+ }
+
+ /*
+ * Set a SANE integer option.
+ */
+ public void setControlOption(int optNum, int val)
+ {
+ int [] info = new int[1];
+ if (sane.setControlOption(saneHandle, optNum,
+ SaneOption.ACTION_SET_VALUE, val, info)
+ != Sane.STATUS_GOOD)
+ System.out.println("setControlOption() failed.");
+ checkOptionInfo(info[0]);
+ }
+
+ /*
+ * Set a SANE text option.
+ */
+ public void setControlOption(int optNum, String val)
+ {
+ int [] info = new int[1];
+ if (sane.setControlOption(saneHandle, optNum,
+ SaneOption.ACTION_SET_VALUE, val, info)
+ != Sane.STATUS_GOOD)
+ System.out.println("setControlOption() failed.");
+ checkOptionInfo(info[0]);
+ }
+
+ /*
+ * Check the 'info' word returned from setControlOption().
+ */
+ private void checkOptionInfo(int info)
+ {
+ // Does everything completely change?
+ if ((info & SaneOption.INFO_RELOAD_OPTIONS) != 0)
+ reinit();
+ // Need to update status line?
+ if ((info & SaneOption.INFO_RELOAD_PARAMS) != 0)
+ ; // ++++++++FILL IN.
+ }
+
+ /*
+ * Handle a user action.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ if (e.getSource() == scanButton)
+ {
+ System.out.println("Rescanning");
+ // Get file name.
+ String fname = outputField.getText();
+ if (fname == null || fname.length() == 0)
+ fname = "out.pnm";
+ try
+ {
+ outFile = new FileOutputStream(fname);
+ }
+ catch (IOException oe)
+ {
+ System.out.println("Error creating file: " + fname);
+ outFile = null;
+ return;
+ }
+ // Disable "Scan" button.
+ scanButton.setEnabled(false);
+ scanIt.setOutputFile(outFile);
+ imageDisplay.setImage(scanIt, this);
+ }
+ else if (e.getSource() == browseButton)
+ {
+ File file; // For working with names.
+ FileDialog dlg = new FileDialog(this, "Output Filename",
+ FileDialog.SAVE);
+ if (outDir != null) // Set to last directory.
+ dlg.setDirectory(outDir);
+ // Get current name.
+ String fname = outputField.getText();
+ if (fname != null)
+ {
+ file = new File(fname);
+ dlg.setFile(file.getName());
+ String dname = file.getParent();
+ if (dname != null)
+ dlg.setDirectory(outDir);
+ }
+ dlg.show(); // Wait for result.
+ fname = dlg.getFile();
+ // Store dir. for next time.
+ outDir = dlg.getDirectory();
+ if (fname != null)
+ {
+ file = new File(outDir, fname);
+ String curDir;
+ String fullName;
+ try
+ {
+ curDir = (new File(".")).getCanonicalPath();
+ fullName = file.getCanonicalPath();
+ // Not in current directory?
+ if (!curDir.equals(
+ (new File(fullName)).getParent()))
+ fname = fullName;
+ }
+ catch (IOException ex)
+ { curDir = "."; fname = file.getName(); }
+ outputField.setText(fname);
+ }
+ }
+ else if (e.getSource() == exitMenuItem)
+ {
+ finalize(); // Just to be safe.
+ System.exit(0);
+ }
+ }
+
+ /*
+ * Handle checkable menu items.
+ */
+ public void itemStateChanged(ItemEvent e)
+ {
+ if (e.getSource() == mmMenuItem)
+ { // Wants mm.
+ unitLength = 1;
+ if (e.getStateChange() == ItemEvent.SELECTED)
+ {
+ cmMenuItem.setState(false);
+ inMenuItem.setState(false);
+ reinit(); // Re-display controls.
+ }
+ else // Don't let him deselect.
+ mmMenuItem.setState(true);
+ }
+ if (e.getSource() == cmMenuItem)
+ { // Wants cm.
+ unitLength = 10;
+ if (e.getStateChange() == ItemEvent.SELECTED)
+ {
+ mmMenuItem.setState(false);
+ inMenuItem.setState(false);
+ reinit(); // Re-display controls.
+ }
+ else
+ cmMenuItem.setState(true);
+ }
+ if (e.getSource() == inMenuItem)
+ { // Wants inches.
+ unitLength = 25.4;
+ if (e.getStateChange() == ItemEvent.SELECTED)
+ {
+ mmMenuItem.setState(false);
+ cmMenuItem.setState(false);
+ reinit(); // Re-display controls.
+ }
+ else // Don't let him deselect.
+ inMenuItem.setState(true);
+ }
+ }
+
+ /*
+ * Scan is complete.
+ */
+ public void imageDone(boolean error)
+ {
+ if (error)
+ System.out.println("Scanning error.");
+ if (outFile != null) // Close file.
+ try
+ {
+ outFile.close();
+ }
+ catch (IOException e)
+ { }
+ scanButton.setEnabled(true); // Can scan again.
+ }
+
+ /*
+ * Default window event handlers.
+ */
+ public void windowClosed(WindowEvent event)
+ {
+ finalize(); // Just to be safe.
+ }
+ public void windowDeiconified(WindowEvent event) { }
+ public void windowIconified(WindowEvent event) { }
+ public void windowActivated(WindowEvent event) { }
+ public void windowDeactivated(WindowEvent event) { }
+ public void windowOpened(WindowEvent event) { }
+ // Handle closing event.
+ public void windowClosing(WindowEvent event)
+ {
+ finalize(); // Just to be safe.
+ System.exit(0);
+ }
+ }
+
+/*
+ * Interface for our dialog controls.
+ */
+interface SaneComponent
+ {
+ public void setFromControl(); // Ask SANE control for current value.
+ }
+
+/*
+ * A checkbox in our dialog.
+ */
+class SaneCheckBox extends JCheckBox implements ActionListener,
+ SaneComponent
+ {
+ private Jscanimage dialog; // That which created us.
+ private int optNum; // Option #.
+
+ /*
+ * Create with given state.
+ */
+ public SaneCheckBox(String title, Jscanimage dlg, int opt, String tip)
+ {
+ super(title, false);
+ dialog = dlg;
+ optNum = opt;
+ // Set tool tip.
+ if (tip != null && tip.length() != 0)
+ super.setToolTipText(tip);
+ addActionListener(this); // Listen to ourself.
+ }
+
+ /*
+ * Update Sane device option with current setting.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ System.out.println("In SaneCheckBox::actionPerformed()");
+ int val = isSelected() ? 1 : 0;
+ dialog.setControlOption(optNum, val);
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ int [] val = new int[1];
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, val, null)
+ == Sane.STATUS_GOOD)
+ setSelected(val[0] != 0);
+ }
+ }
+
+/*
+ * A slider in our dialog. This base class handles integer ranges.
+ * It consists of a slider and a label which shows the current value.
+ */
+class SaneSlider extends JPanel implements SaneComponent, ChangeListener
+ {
+ protected Jscanimage dialog; // That which created us.
+ protected int optNum; // Option #.
+ protected JSlider slider; // The slider itself.
+ protected JLabel label; // Shows current value.
+
+ /*
+ * Create with given state.
+ */
+ public SaneSlider(int min, int max, Jscanimage dlg, int opt, String tip)
+ {
+ super(new GridBagLayout()); // Create panel.
+ dialog = dlg;
+ optNum = opt;
+ GridBagConstraints c = new GridBagConstraints();
+ // Want 1 row.
+ c.gridx = GridBagConstraints.RELATIVE;
+ c.gridy = 0;
+ c.anchor = GridBagConstraints.CENTER;
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.weighty = .8;
+ c.weightx = .2; // Give less weight to value label.
+ label = new JLabel("00", SwingConstants.RIGHT);
+ add(label, c);
+ c.weightx = .8; // Give most weight to slider.
+ c.fill = GridBagConstraints.HORIZONTAL;
+ slider = new JSlider(JSlider.HORIZONTAL, min, max,
+ min + (max - min)/2);
+ add(slider, c);
+ // Set tool tip.
+ if (tip != null && tip.length() != 0)
+ super.setToolTipText(tip);
+ slider.addChangeListener(this); // Listen to ourself.
+ }
+
+ /*
+ * Update Sane device option.
+ */
+ public void stateChanged(ChangeEvent e)
+ {
+ int val = slider.getValue();
+ label.setText(String.valueOf(val));
+ dialog.setControlOption(optNum, val);
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ int [] val = new int[1]; // Get current SANE control value.
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, val, null)
+ == Sane.STATUS_GOOD)
+ {
+ slider.setValue(val[0]);
+ label.setText(String.valueOf(val[0]));
+ }
+ }
+ }
+
+/*
+ * A slider with fixed-point values:
+ */
+class FixedSaneSlider extends SaneSlider
+ {
+ private static final int SCALE_MIN = -32000;
+ private static final int SCALE_MAX = 32000;
+ double min, max; // Min, max in floating-point.
+ boolean optMM; // Option is in millimeters, so should
+ // be scaled to user's pref.
+ private NumberFormat format; // For printing label.
+ /*
+ * Create with given fixed-point range.
+ */
+ public FixedSaneSlider(int fixed_min, int fixed_max, boolean mm,
+ Jscanimage dlg, int opt, String tip)
+ {
+ // Create with large integer range.
+ super(SCALE_MIN, SCALE_MAX, dlg, opt, tip);
+ format = NumberFormat.getInstance();
+ // For now, show 1 decimal point.
+ format.setMinimumFractionDigits(1);
+ format.setMaximumFractionDigits(1);
+ // Store actual range.
+ min = dlg.getSane().unfix(fixed_min);
+ max = dlg.getSane().unfix(fixed_max);
+ optMM = mm;
+ }
+
+ /*
+ * Update Sane device option.
+ */
+ public void stateChanged(ChangeEvent e)
+ {
+ double val = (double) slider.getValue();
+ // Convert to actual control scale.
+ val = min + ((val - SCALE_MIN)/(SCALE_MAX - SCALE_MIN)) * (max - min);
+ label.setText(format.format(optMM ?
+ val/dialog.getUnitLength() : val));
+ dialog.setControlOption(optNum, dialog.getSane().fix(val));
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ int [] ival = new int[1]; // Get current SANE control value.
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, ival, null)
+ == Sane.STATUS_GOOD)
+ {
+ double val = dialog.getSane().unfix(ival[0]);
+ // Show value with user's pref.
+ label.setText(format.format(optMM ?
+ val/dialog.getUnitLength() : val));
+ val = SCALE_MIN + ((val - min)/(max - min)) *
+ (SCALE_MAX - SCALE_MIN);
+ slider.setValue((int) val);
+ }
+ }
+ }
+
+/*
+ * A Button in our dialog.
+ */
+class SaneButton extends JButton implements ActionListener
+ {
+ private Jscanimage dialog; // That which created us.
+ private int optNum; // Option #.
+
+ /*
+ * Create with given state.
+ */
+ public SaneButton(String title, Jscanimage dlg, int opt, String tip)
+ {
+ super(title);
+ dialog = dlg;
+ optNum = opt;
+ // Set tool tip.
+ if (tip != null && tip.length() != 0)
+ super.setToolTipText(tip);
+ addActionListener(this); // Listen to ourself.
+ }
+
+ /*
+ * Update Sane device option.
+ */
+ public void actionPerformed(ActionEvent e)
+ {
+ dialog.setControlOption(optNum, 0);
+ System.out.println("In SaneButton::actionPerformed()");
+ }
+ }
+
+/*
+ * A combo-box for showing a list of items.
+ */
+abstract class SaneComboBox extends JComboBox
+ implements SaneComponent, ItemListener
+ {
+ protected Jscanimage dialog; // That which created us.
+ protected int optNum; // Option #.
+
+ /*
+ * Create it.
+ */
+ public SaneComboBox(Jscanimage dlg, int opt, String tip)
+ {
+ dialog = dlg;
+ optNum = opt;
+ // Set tool tip.
+ if (tip != null && tip.length() != 0)
+ super.setToolTipText(tip);
+ addItemListener(this);
+ }
+
+ /*
+ * Select desired item by its text.
+ */
+ protected void select(String text)
+ {
+ int cnt = getItemCount();
+ for (int i = 0; i < cnt; i++)
+ if (text.equals(getItemAt(i)))
+ {
+ setSelectedIndex(i);
+ break;
+ }
+ }
+
+ abstract public void setFromControl();
+ abstract public void itemStateChanged(ItemEvent e);
+ }
+
+/*
+ * A list of strings.
+ */
+class SaneStringBox extends SaneComboBox
+ {
+
+ /*
+ * Create it.
+ */
+ public SaneStringBox(Jscanimage dlg, int opt, String tip)
+ {
+ super(dlg, opt, tip);
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ // Let's get the whole list.
+ SaneOption opt = dialog.getSane().getOptionDescriptor(
+ dialog.getSaneHandle(), optNum);
+ if (opt == null)
+ return;
+ removeAllItems(); // Clear list.
+ // Go through list from option.
+ for (int i = 0; opt.stringListConstraint[i] != null; i++)
+ addItem(opt.stringListConstraint[i]);
+ // Get value.
+ byte buf[] = new byte[opt.size + 1];
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, buf, null)
+ == Sane.STATUS_GOOD)
+ select(new String(buf));
+ }
+
+ /*
+ * An item was selected.
+ */
+ public void itemStateChanged(ItemEvent e)
+ {
+ // Get current selection.
+ String val = (String) getSelectedItem();
+ if (val != null)
+ dialog.setControlOption(optNum, val);
+ }
+ }
+
+/*
+ * A list of integers.
+ */
+class SaneIntBox extends SaneComboBox
+ {
+
+ /*
+ * Create it.
+ */
+ public SaneIntBox(Jscanimage dlg, int opt, String tip)
+ {
+ super(dlg, opt, tip);
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ // Let's get the whole list.
+ SaneOption opt = dialog.getSane().getOptionDescriptor(
+ dialog.getSaneHandle(), optNum);
+ if (opt == null)
+ return;
+ removeAllItems(); // Clear list.
+ // Go through list from option.
+ int cnt = opt.wordListConstraint[0];
+ for (int i = 0; i < cnt; i++)
+ addItem(String.valueOf(opt.wordListConstraint[i + 1]));
+ // Get value.
+ int [] val = new int[1]; // Get current SANE control value.
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, val, null)
+ == Sane.STATUS_GOOD)
+ select(String.valueOf(val[0]));
+ }
+
+ /*
+ * An item was selected.
+ */
+ public void itemStateChanged(ItemEvent e)
+ {
+ // Get current selection.
+ String val = (String) getSelectedItem();
+ if (val != null)
+ try
+ {
+ Integer v = Integer.valueOf(val);
+ dialog.setControlOption(optNum, v.intValue());
+ }
+ catch (NumberFormatException ex) { }
+ }
+ }
+
+/*
+ * A list of fixed-point floating point numbers.
+ */
+class SaneFixedBox extends SaneComboBox
+ {
+
+ /*
+ * Create it.
+ */
+ public SaneFixedBox(Jscanimage dlg, int opt, String tip)
+ {
+ super(dlg, opt, tip);
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ // Let's get the whole list.
+ SaneOption opt = dialog.getSane().getOptionDescriptor(
+ dialog.getSaneHandle(), optNum);
+ if (opt == null)
+ return;
+ removeAllItems(); // Clear list.
+ // Go through list from option.
+ int cnt = opt.wordListConstraint[0];
+ for (int i = 0; i < cnt; i++)
+ addItem(String.valueOf(dialog.getSane().unfix(
+ opt.wordListConstraint[i + 1])));
+ // Get value.
+ int [] val = new int[1]; // Get current SANE control value.
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, val, null)
+ == Sane.STATUS_GOOD)
+ select(String.valueOf(dialog.getSane().unfix(val[0])));
+ }
+
+ /*
+ * An item was selected.
+ */
+ public void itemStateChanged(ItemEvent e)
+ {
+ // Get current selection.
+ String val = (String) getSelectedItem();
+ if (val != null)
+ try
+ {
+ Double v = Double.valueOf(val);
+ dialog.setControlOption(optNum,
+ dialog.getSane().fix(v.doubleValue()));
+ }
+ catch (NumberFormatException ex) { }
+ }
+ }
+
+/*
+ * A text-entry field in our dialog.
+ */
+class SaneTextField extends JTextField implements SaneComponent
+ {
+ private Jscanimage dialog; // That which created us.
+ private int optNum; // Option #.
+
+ /*
+ * Create with given state.
+ */
+ public SaneTextField(int width, Jscanimage dlg, int opt, String tip)
+ {
+ super(width); // Set initial text, # chars.
+ dialog = dlg;
+ optNum = opt;
+ // Set tool tip.
+ if (tip != null && tip.length() != 0)
+ super.setToolTipText(tip);
+ }
+
+ /*
+ * Update Sane device option with current setting when user types.
+ */
+ public void processKeyEvent(KeyEvent e)
+ {
+ super.processKeyEvent(e); // Handle it normally.
+ if (e.getID() != KeyEvent.KEY_TYPED)
+ return; // Just do it after keystroke.
+ String userText = getText(); // Get what's there, & save copy.
+ String newText = new String(userText);
+ dialog.setControlOption(optNum, newText);
+ if (!newText.equals(userText)) // Backend may have changed it.
+ setText(newText);
+ }
+
+ /*
+ * Update from Sane control's value.
+ */
+ public void setFromControl()
+ {
+ byte buf[] = new byte[1024];
+ if (dialog.getSane().getControlOption(
+ dialog.getSaneHandle(), optNum, buf, null)
+ == Sane.STATUS_GOOD)
+ {
+ String text = new String(buf);
+ System.out.println("SaneTextField::setFromControl: " + text);
+ setText(text); // Set text in field.
+ setScrollOffset(0);
+ }
+ }
+ }
diff --git a/japi/Makefile.am b/japi/Makefile.am
new file mode 100644
index 0000000..5d66e82
--- /dev/null
+++ b/japi/Makefile.am
@@ -0,0 +1,47 @@
+## Makefile.am -- an automake template for Makefile.in file
+## Copyright (C) 2009 Chris Bagwell and Sane Developers.
+##
+## This file is part of the "Sane" build infra-structure. See
+## included LICENSE file for license information.
+
+#
+# Makefile for a Java project with native methods.
+#
+
+V_MAJOR = @V_MAJOR@
+V_MINOR = @V_MINOR@
+V_REV = @V_REV@
+
+JAVAROOT=.
+CLASSPATH_ENV=.
+JAVAH=javah -jni -cp $(CLASSPATH_ENV)
+
+# We'll need something in 'configure' for the Java includes.
+AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include \
+ -I$(top_srcdir)/include -I${JDK_HOME}/include \
+ -I${JDK_HOME}/include/genunix
+AM_LDFLAGS = @STRICT_LDFLAGS@ -version-number $(V_MAJOR):$(V_MINOR):$(VREV)
+
+JAVA_SRC = SaneDevice.java SaneOption.java SaneRange.java\
+ Sane.java SaneParameters.java ScanIt.java \
+ ImageCanvas.java ImageCanvasClient.java \
+ Test.java Jscanimage.java
+
+dist_noinst_JAVA = $(JAVA_SRC)
+
+LIBSANE = ../backend/libsane.la
+
+EXTRA_DIST = Makefile.in README.JAVA
+
+lib_LTLIBRARIES = libsanej.la
+
+BUILT_SOURCES = Sane.h
+CLEANFILES = Sane.h
+nodist_libsanej_la_SOURCES = Sane.h
+libsanej_la_SOURCES = Sane.c
+libsanej_la_LIBADD = $(LIBSANE)
+
+# Make sure that java classes get created before create Sane.h
+Sane.h: classdist_noinst.stamp
+ $(JAVAH) Sane
+
diff --git a/japi/Makefile.in b/japi/Makefile.in
new file mode 100644
index 0000000..550bd8d
--- /dev/null
+++ b/japi/Makefile.in
@@ -0,0 +1,738 @@
+# Makefile.in generated by automake 1.13.4 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# Makefile for a Java project with native methods.
+#
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = japi
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/mkinstalldirs $(top_srcdir)/depcomp \
+ $(dist_noinst_JAVA)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/byteorder.m4 \
+ $(top_srcdir)/m4/stdint.m4 $(top_srcdir)/configure.in
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/include/sane/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libsanej_la_DEPENDENCIES = $(LIBSANE)
+am_libsanej_la_OBJECTS = Sane.lo
+nodist_libsanej_la_OBJECTS =
+libsanej_la_OBJECTS = $(am_libsanej_la_OBJECTS) \
+ $(nodist_libsanej_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/include/sane
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libsanej_la_SOURCES) $(nodist_libsanej_la_SOURCES)
+DIST_SOURCES = $(libsanej_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+JAVAC = javac
+am__java_sources = $(dist_noinst_JAVA)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AVAHI_CFLAGS = @AVAHI_CFLAGS@
+AVAHI_LIBS = @AVAHI_LIBS@
+AWK = @AWK@
+BACKENDS = @BACKENDS@
+BACKEND_CONFS_ENABLED = @BACKEND_CONFS_ENABLED@
+BACKEND_LIBS_ENABLED = @BACKEND_LIBS_ENABLED@
+BACKEND_MANS_ENABLED = @BACKEND_MANS_ENABLED@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DISTCLEAN_FILES = @DISTCLEAN_FILES@
+DLLTOOL = @DLLTOOL@
+DL_LIBS = @DL_LIBS@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+DVIPS = @DVIPS@
+DYNAMIC_FLAG = @DYNAMIC_FLAG@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GPHOTO2_CPPFLAGS = @GPHOTO2_CPPFLAGS@
+GPHOTO2_LDFLAGS = @GPHOTO2_LDFLAGS@
+GPHOTO2_LIBS = @GPHOTO2_LIBS@
+GREP = @GREP@
+HAVE_GPHOTO2 = @HAVE_GPHOTO2@
+IEEE1284_LIBS = @IEEE1284_LIBS@
+INCLUDES = @INCLUDES@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_LOCKPATH = @INSTALL_LOCKPATH@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+JPEG_LIBS = @JPEG_LIBS@
+LATEX = @LATEX@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIBUSB_1_0_CFLAGS = @LIBUSB_1_0_CFLAGS@
+LIBUSB_1_0_LIBS = @LIBUSB_1_0_LIBS@
+LIBV4L_CFLAGS = @LIBV4L_CFLAGS@
+LIBV4L_LIBS = @LIBV4L_LIBS@
+LINKER_RPATH = @LINKER_RPATH@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCKPATH_GROUP = @LOCKPATH_GROUP@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINDEX = @MAKEINDEX@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MATH_LIB = @MATH_LIB@
+MKDIR_P = @MKDIR_P@
+MSGFMT = @MSGFMT@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+NUMBER_VERSION = @NUMBER_VERSION@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PRELOADABLE_BACKENDS = @PRELOADABLE_BACKENDS@
+PRELOADABLE_BACKENDS_ENABLED = @PRELOADABLE_BACKENDS_ENABLED@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+RANLIB = @RANLIB@
+RESMGR_LIBS = @RESMGR_LIBS@
+SANEI_SANEI_JPEG_LO = @SANEI_SANEI_JPEG_LO@
+SANE_CONFIG_PATH = @SANE_CONFIG_PATH@
+SCSI_LIBS = @SCSI_LIBS@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SNMP_CONFIG_PATH = @SNMP_CONFIG_PATH@
+SOCKET_LIBS = @SOCKET_LIBS@
+STRICT_LDFLAGS = @STRICT_LDFLAGS@
+STRIP = @STRIP@
+SYSLOG_LIBS = @SYSLOG_LIBS@
+SYSTEMD_LIBS = @SYSTEMD_LIBS@
+TIFF_LIBS = @TIFF_LIBS@
+USB_LIBS = @USB_LIBS@
+VERSION = @VERSION@
+V_MAJOR = @V_MAJOR@
+V_MINOR = @V_MINOR@
+V_REV = @V_REV@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+configdir = @configdir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+effective_target = @effective_target@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+locksanedir = @locksanedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+JAVAROOT = .
+CLASSPATH_ENV = .
+JAVAH = javah -jni -cp $(CLASSPATH_ENV)
+
+# We'll need something in 'configure' for the Java includes.
+AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_builddir)/include \
+ -I$(top_srcdir)/include -I${JDK_HOME}/include \
+ -I${JDK_HOME}/include/genunix
+
+AM_LDFLAGS = @STRICT_LDFLAGS@ -version-number $(V_MAJOR):$(V_MINOR):$(VREV)
+JAVA_SRC = SaneDevice.java SaneOption.java SaneRange.java\
+ Sane.java SaneParameters.java ScanIt.java \
+ ImageCanvas.java ImageCanvasClient.java \
+ Test.java Jscanimage.java
+
+dist_noinst_JAVA = $(JAVA_SRC)
+LIBSANE = ../backend/libsane.la
+EXTRA_DIST = Makefile.in README.JAVA
+lib_LTLIBRARIES = libsanej.la
+BUILT_SOURCES = Sane.h
+CLEANFILES = Sane.h
+nodist_libsanej_la_SOURCES = Sane.h
+libsanej_la_SOURCES = Sane.c
+libsanej_la_LIBADD = $(LIBSANE)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu japi/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu japi/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libsanej.la: $(libsanej_la_OBJECTS) $(libsanej_la_DEPENDENCIES) $(EXTRA_libsanej_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(LINK) -rpath $(libdir) $(libsanej_la_OBJECTS) $(libsanej_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Sane.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+classnoinst.stamp: $(am__java_sources)
+ @list1='$?'; list2=; if test -n "$$list1"; then \
+ for p in $$list1; do \
+ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \
+ list2="$$list2 $$d$$p"; \
+ done; \
+ echo '$(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) '"$$list2"; \
+ $(CLASSPATH_ENV) $(JAVAC) -d $(JAVAROOT) $(AM_JAVACFLAGS) $(JAVACFLAGS) $$list2; \
+ else :; fi
+ echo timestamp > $@
+
+clean-noinstJAVA:
+ -rm -f *.class classnoinst.stamp
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) classnoinst.stamp
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ clean-noinstJAVA mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-libLTLIBRARIES
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool clean-noinstJAVA \
+ cscopelist-am ctags ctags-am distclean distclean-compile \
+ distclean-generic distclean-libtool distclean-tags distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-libLTLIBRARIES \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-libLTLIBRARIES
+
+
+# Make sure that java classes get created before create Sane.h
+Sane.h: classdist_noinst.stamp
+ $(JAVAH) Sane
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/japi/README.JAVA b/japi/README.JAVA
new file mode 100644
index 0000000..4c838f4
--- /dev/null
+++ b/japi/README.JAVA
@@ -0,0 +1,55 @@
+--
+12/17/97
+
+Most of Jscanimage's main dialog is coded, but only tested with PNM (which
+means most of the newly supported option types haven't been tried yet).
+Scanning (with PNM) does seem to work, although large files definitely take
+longer in JAVA then with "xscanimage".
+
+Main things left to do:
+ 1. Provide the "preview" dialog.
+ 2. Try it out with a real scanner, especially with large images.
+ 3. Try it on a platform other than Linux.
+
+--
+11/18/97
+
+This snapshot contains a partially functional "Jscanimage", which is intended
+to be a Java clone of "xscanimage". Only some of the controls are implemented
+(sliders, check-boxes, text-entry), and I've only tested it using small images
+with the "pnm" backend; but, it does seem to be functional, and to output .pnm
+files.
+
+There are also some small changes to the Java API.
+
+To do (at the least):
+ 1. Handle "word list" controls.
+ 2. Handle "browse" button for file selection.
+ 3. Provide pull-down menus for choosing length units, and use them.
+ 4. Provide the "preview" dialog.
+ 5. Try it out with a real scanner, especially with large images.
+ 6. Try it on a platform other than Linux.
+
+ -- Jeff
+
+--
+10/17/97
+
+NOTE: To build the Java interface, you have to cd into this directory
+and type "make" (after running configure in the top-level directory).
+
+ --david
+--
+This is my first pass at creating a Java API for SANE. It requires JDK 1.1.x,
+as it uses the new JNI for creating native methods.
+
+This is definitely not 100% pure Java, as it's really just a set of wrappers
+which call the actual SANE backend routines. It's also very preliminary, so
+feel free to suggest changes to the interface or class definitions.
+
+The 'install' installs the shared library (libsanej.*), but I'm not sure yet
+what to do with the generated Java class files. So for now, you should be
+able to run the test program after installation by typing "java Test" within
+the "japi" directory.
+
+-- Jeff Freedman (jsf@hevanet.com)
diff --git a/japi/Sane.c b/japi/Sane.c
new file mode 100644
index 0000000..1ddb4fc
--- /dev/null
+++ b/japi/Sane.c
@@ -0,0 +1,493 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+/**
+ ** Sane.c - Native methods for the SANE Java API.
+ **
+ ** Written: 10/9/97 - JSF
+ **/
+
+#include "Sane.h"
+#include <sane/sane.h>
+#include <string.h>
+
+#include <stdio.h> /* Debugging */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: Sane
+ * Method: init
+ * Signature: ([I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_init
+ (JNIEnv *env, jobject jobj, jintArray versionCode)
+ {
+ jsize len; /* Gets array length. */
+ jint *versionCodeBody; /* Gets ->array. */
+ SANE_Int version; /* Gets version. */
+ SANE_Status status; /* Get SANE return. */
+
+ status = sane_init(&version, 0);
+ len = (*env)->GetArrayLength(env, versionCode);
+ versionCodeBody = (*env)->GetIntArrayElements(env, versionCode, 0);
+ if (len > 0) /* Return version. */
+ versionCodeBody[0] = version;
+ (*env)->ReleaseIntArrayElements(env, versionCode, versionCodeBody, 0);
+ return (status);
+ }
+/*
+ * Class: Sane
+ * Method: exit
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_Sane_exit
+ (JNIEnv *env, jobject jobj)
+ {
+ sane_exit();
+ }
+
+
+/*
+ * Class: Sane
+ * Method: getDevices
+ * Signature: ([LSaneDevice;Z)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getDevicesNative
+ (JNIEnv *env, jobject jobj, jobjectArray devList, jboolean localOnly)
+ {
+ /* Gets device list. */
+ const SANE_Device **device_list;
+ SANE_Status status; /* Gets status. */
+ int devListLen; /* Gets length of devList. */
+ jobject devObj; /* Gets each SaneDevice object. */
+ jclass devClass; /* Gets SaneDevice class. */
+ jfieldID fid; /* Gets each field ID. */
+ int i;
+
+ /* Get the list. */
+ status = sane_get_devices(&device_list, localOnly);
+ if (status != SANE_STATUS_GOOD)
+ return (status);
+ /* Get length of Java array. */
+ devListLen = (*env)->GetArrayLength(env, devList);
+ /* Return devices to user. */
+ for (i = 0; i < devListLen - 1 && device_list[i]; i++)
+ {
+ /* Get Java object, class. */
+ devObj = (*env)->GetObjectArrayElement(env, devList, i);
+ devClass = (*env)->GetObjectClass(env, devObj);
+ /* Fill in each member. */
+ fid = (*env)->GetFieldID(env, devClass, "name",
+ "Ljava/lang/String;");
+ (*env)->SetObjectField(env, devObj, fid,
+ (*env)->NewStringUTF(env, device_list[i]->name));
+ fid = (*env)->GetFieldID(env, devClass, "vendor",
+ "Ljava/lang/String;");
+ (*env)->SetObjectField(env, devObj, fid,
+ (*env)->NewStringUTF(env, device_list[i]->vendor));
+ fid = (*env)->GetFieldID(env, devClass, "model",
+ "Ljava/lang/String;");
+ (*env)->SetObjectField(env, devObj, fid,
+ (*env)->NewStringUTF(env, device_list[i]->model));
+ fid = (*env)->GetFieldID(env, devClass, "type",
+ "Ljava/lang/String;");
+ (*env)->SetObjectField(env, devObj, fid,
+ (*env)->NewStringUTF(env, device_list[i]->type));
+ }
+ /* End list with a null. */
+ (*env)->SetObjectArrayElement(env, devList, i, 0);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: open
+ * Signature: (Ljava/lang/String;[J)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_open
+ (JNIEnv *env, jobject jobj, jstring deviceName, jintArray handle)
+ {
+ SANE_Handle sane_handle; /* Gets handle. */
+ jint s_handle;
+ const char *device_name; /* Gets dev. name. */
+ int status; /* Gets return code. */
+
+ device_name = (*env)->GetStringUTFChars(env, deviceName, 0);
+ /* Open it. */
+ status = sane_open(device_name, &sane_handle);
+ (*env)->ReleaseStringUTFChars(env, deviceName, device_name);
+ /* Return handle. */
+ s_handle = (jint) sane_handle;
+ (*env)->SetIntArrayRegion(env, handle, 0, 1, &s_handle);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_Sane_close
+ (JNIEnv *env, jobject jobj, jint handle)
+ {
+ sane_close((SANE_Handle) handle);
+ }
+
+/*
+ * Class: Sane
+ * Method: getOptionNative
+ * Signature: (IILSaneOption;)V
+ */
+JNIEXPORT void JNICALL Java_Sane_getOptionNative
+ (JNIEnv *env, jobject jobj, jint handle, jint option, jobject optObj)
+ {
+ jclass optClass; /* Gets its class. */
+ jfieldID fid; /* Gets each field ID. */
+ jstring str; /* Gets strings. */
+
+ /* Get info from sane. */
+ const SANE_Option_Descriptor *sopt = sane_get_option_descriptor(
+ (SANE_Handle) handle, option);
+ /* Get class info. */
+ optClass = (*env)->GetObjectClass(env, optObj);
+ /* Fill in each member. */
+ fid = (*env)->GetFieldID(env, optClass, "name", "Ljava/lang/String;");
+ if (!sopt) /* Failed. */
+ { /* Set name to null. */
+ (*env)->SetObjectField(env, optObj, fid, 0);
+ return;
+ }
+ /* Return name. */
+ (*env)->SetObjectField(env, optObj, fid,
+ (*env)->NewStringUTF(env, sopt->name));
+ /* Return title. */
+ fid = (*env)->GetFieldID(env, optClass, "title", "Ljava/lang/String;");
+ str = sopt->title ? (*env)->NewStringUTF(env, sopt->title) : 0;
+ (*env)->SetObjectField(env, optObj, fid, str);
+ /* Return descr. */
+ fid = (*env)->GetFieldID(env, optClass, "desc", "Ljava/lang/String;");
+ (*env)->SetObjectField(env, optObj, fid,
+ (*env)->NewStringUTF(env, sopt->desc));
+ /* Return type. */
+ fid = (*env)->GetFieldID(env, optClass, "type", "I");
+ (*env)->SetIntField(env, optObj, fid, sopt->type);
+ /* Return unit. */
+ fid = (*env)->GetFieldID(env, optClass, "unit", "I");
+ (*env)->SetIntField(env, optObj, fid, sopt->unit);
+ /* Return size. */
+ fid = (*env)->GetFieldID(env, optClass, "size", "I");
+ (*env)->SetIntField(env, optObj, fid, sopt->size);
+ /* Return cap. */
+ fid = (*env)->GetFieldID(env, optClass, "cap", "I");
+ (*env)->SetIntField(env, optObj, fid, sopt->cap);
+ /* Return constraint_type. */
+ fid = (*env)->GetFieldID(env, optClass, "constraintType", "I");
+ (*env)->SetIntField(env, optObj, fid, sopt->constraint_type);
+ /*
+ * Now for the constraint itself.
+ */
+ if (sopt->constraint_type == SANE_CONSTRAINT_RANGE)
+ {
+ /* Create range object. */
+ jclass rangeClass = (*env)->FindClass(env, "SaneRange");
+ jobject range = (*env)->AllocObject(env, rangeClass);
+ /* Fill in fields. */
+ fid = (*env)->GetFieldID(env, rangeClass, "min", "I");
+ (*env)->SetIntField(env, range, fid,
+ sopt->constraint.range->min);
+ fid = (*env)->GetFieldID(env, rangeClass, "max", "I");
+ (*env)->SetIntField(env, range, fid,
+ sopt->constraint.range->max);
+ fid = (*env)->GetFieldID(env, rangeClass, "quant", "I");
+ (*env)->SetIntField(env, range, fid,
+ sopt->constraint.range->quant);
+ fid = (*env)->GetFieldID(env, optClass, "rangeConstraint",
+ "LSaneRange;");
+ /* Store range. */
+ (*env)->SetObjectField(env, optObj, fid, range);
+ }
+ else if (sopt->constraint_type == SANE_CONSTRAINT_WORD_LIST)
+ { /* Get array of integers. */
+ jintArray wordList;
+ jint *elements;
+ int i;
+ /* First word. is the length. */
+ wordList = (*env)->NewIntArray(env,
+ sopt->constraint.word_list[0]);
+ /* Copy in the integers. */
+ elements = (*env)->GetIntArrayElements(env, wordList, 0);
+ for (i = 0; i < sopt->constraint.word_list[0]; i++)
+ elements[i] = sopt->constraint.word_list[i];
+ (*env)->ReleaseIntArrayElements(env, wordList, elements, 0);
+ /* Set the field. */
+ fid = (*env)->GetFieldID(env, optClass, "wordListConstraint",
+ "[I");
+ (*env)->SetObjectField(env, optObj, fid, wordList);
+ }
+ else if (sopt->constraint_type == SANE_CONSTRAINT_STRING_LIST)
+ {
+ jclass stringClass = (*env)->FindClass(env, "java/lang/String");
+ jobjectArray stringList;
+ int len; /* Gets # elements */
+ int i;
+
+ for (len = 0; sopt->constraint.string_list[len]; len++)
+ ;
+ stringList = (*env)->NewObjectArray(env, len + 1,
+ stringClass, 0);
+ /* Add each string. */
+ for (i = 0; i < len; i++)
+ {
+ (*env)->SetObjectArrayElement(env, stringList, i,
+ (*env)->NewStringUTF(env,
+ sopt->constraint.string_list[i]));
+ }
+ /* 0 at end. */
+ (*env)->SetObjectArrayElement(env, stringList, len, 0);
+ /* Set the field. */
+ fid = (*env)->GetFieldID(env, optClass,
+ "stringListConstraint", "[Ljava/lang/String;");
+ (*env)->SetObjectField(env, optObj, fid, stringList);
+ }
+ }
+
+/*
+ * Class: Sane
+ * Method: getControlOption
+ * Signature: (II[I[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3I_3I
+ (JNIEnv *env, jobject jobj, jint handle, jint option, jintArray value,
+ jintArray info)
+ {
+ SANE_Status status; /* Gets status. */
+ SANE_Int i; /* Gets info. passed back. */
+ int v;
+
+ status = sane_control_option((SANE_Handle) handle, option,
+ SANE_ACTION_GET_VALUE, &v, &i);
+ if (value)
+ (*env)->SetIntArrayRegion(env, value, 0, 1, &v);
+ if (info)
+ (*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: getControlOption
+ * Signature: (II[B[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getControlOption__II_3B_3I
+ (JNIEnv *env, jobject jobj, jint handle, jint option, jbyteArray value,
+ jintArray info)
+ {
+ SANE_Status status; /* Gets status. */
+ SANE_Int i; /* Gets info. passed back. */
+ char *str;
+
+ str = (*env)->GetByteArrayElements(env, value, 0);
+ status = sane_control_option((SANE_Handle) handle, option,
+ SANE_ACTION_GET_VALUE, str, &i);
+ (*env)->ReleaseByteArrayElements(env, value, str, 0);
+ if (info)
+ (*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: setControlOption
+ * Signature: (IIII[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIII_3I
+ (JNIEnv *env, jobject jobj, jint handle, jint option, jint action,
+ jint value, jintArray info)
+ {
+ SANE_Status status; /* Gets status. */
+ SANE_Int i; /* Gets info. passed back. */
+ status = sane_control_option((SANE_Handle) handle, option, action,
+ &value, &i);
+ if (info)
+ (*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+ return (status);
+ }
+
+/*
+ * Get string length. This exists because sometimes strings seem to be
+ * padded with negatives.
+ */
+
+static int String_length
+ (
+ const char *str
+ )
+ {
+ const char *ptr;
+ for (ptr = str; *ptr > 0; ptr++)
+ ;
+ return ((int) (ptr - str));
+ }
+
+/*
+ * Class: Sane
+ * Method: setControlOption
+ * Signature: (IIILjava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_setControlOption__IIILjava_lang_String_2_3I
+ (JNIEnv *env, jobject jobj, jint handle, jint option, jint action,
+ jstring value, jintArray info)
+ {
+ SANE_Status status; /* Gets status. */
+ SANE_Int i; /* Gets info. passed back. */
+ const char *valuep;
+ char buf[512]; /* Hope this is big enough. */
+ int len; /* Gets string length. */
+
+ valuep = (*env)->GetStringUTFChars(env, value, 0);
+ len = String_length(valuep);
+ if (len >= sizeof(buf))
+ len = sizeof(buf) - 1;
+ strncpy(buf, valuep, len);
+ buf[len] = 0; /* Insure it's 0-delimited. */
+ status = sane_control_option((SANE_Handle) handle, option, action,
+ (void *) &buf[0], &i);
+ /* +++++++Want to return new val? */
+ (*env)->ReleaseStringUTFChars(env, value, valuep);
+ if (info)
+ (*env)->SetIntArrayRegion(env, info, 0, 1, &i);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: getParameters
+ * Signature: (ILSaneParameters;)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_getParameters
+ (JNIEnv *env, jobject jobj, jint handle, jobject paramsObj)
+ {
+ SANE_Status status; /* Gets status. */
+ SANE_Parameters params; /* Gets params. */
+ jclass paramsClass; /* Gets its class. */
+ jfieldID fid; /* Gets each field ID. */
+
+ status = sane_get_parameters((SANE_Handle) handle, &params);
+ /* Get class info. */
+ paramsClass = (*env)->GetObjectClass(env, paramsObj);
+ /* Fill in each member. */
+ fid = (*env)->GetFieldID(env, paramsClass, "format", "I");
+ (*env)->SetIntField(env, paramsObj, fid, params.format);
+ fid = (*env)->GetFieldID(env, paramsClass, "lastFrame", "Z");
+ (*env)->SetBooleanField(env, paramsObj, fid, params.last_frame);
+ fid = (*env)->GetFieldID(env, paramsClass, "bytesPerLine", "I");
+ (*env)->SetIntField(env, paramsObj, fid, params.bytes_per_line);
+ fid = (*env)->GetFieldID(env, paramsClass, "pixelsPerLine", "I");
+ (*env)->SetIntField(env, paramsObj, fid, params.pixels_per_line);
+ fid = (*env)->GetFieldID(env, paramsClass, "lines", "I");
+ (*env)->SetIntField(env, paramsObj, fid, params.lines);
+ fid = (*env)->GetFieldID(env, paramsClass, "depth", "I");
+ (*env)->SetIntField(env, paramsObj, fid, params.depth);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: start
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_start
+ (JNIEnv *env, jobject jobj, jint handle)
+ {
+ return (sane_start((SANE_Handle) handle));
+ }
+
+/*
+ * Class: Sane
+ * Method: read
+ * Signature: (I[BI[I)I
+ */
+JNIEXPORT jint JNICALL Java_Sane_read
+ (JNIEnv *env, jobject jobj, jint handle, jbyteArray data, jint maxLength,
+ jintArray length)
+ {
+ int status;
+ jbyte *dataElements;
+ int read_len; /* # bytes read. */
+
+ /* Get actual data ptr. */
+ dataElements = (*env)->GetByteArrayElements(env, data, 0);
+ /* Do the read. */
+ status = sane_read((SANE_Handle) handle, dataElements,
+ maxLength, &read_len);
+ (*env)->ReleaseByteArrayElements(env, data, dataElements, 0);
+ /* Return # bytes read. */
+ (*env)->SetIntArrayRegion(env, length, 0, 1, &read_len);
+ return (status);
+ }
+
+/*
+ * Class: Sane
+ * Method: cancel
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_Sane_cancel
+ (JNIEnv *env, jobject jobj, jint handle)
+ {
+ sane_cancel((SANE_Handle) handle);
+ }
+
+/*
+ * Class: Sane
+ * Method: strstatus
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_Sane_strstatus
+ (JNIEnv *env, jobject jobj, jint status)
+ {
+ const char *str = sane_strstatus(status);
+ return ((*env)->NewStringUTF(env, str));
+ }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/japi/Sane.java b/japi/Sane.java
new file mode 100644
index 0000000..85600e7
--- /dev/null
+++ b/japi/Sane.java
@@ -0,0 +1,144 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+//
+// Sane.java - Java version of SANE API.
+//
+// Written: 10/9/97 - JSF
+//
+
+public class Sane
+{
+ //
+ // Public constants:
+ //
+public static int FIXED_SCALE_SHIFT = 16;
+ //
+ // Sane status values:
+ //
+public static int STATUS_GOOD = 0; // everything A-OK
+public static int STATUS_UNSUPPORTED = 1;// operation is not supported
+public static int STATUS_CANCELLED = 2; // operation was cancelled
+public static int STATUS_DEVICE_BUSY = 3;// device is busy; try again later
+public static int STATUS_INVAL = 4; // data is invalid (includes no
+ // dev at open)
+public static int STATUS_EOF = 5; // no more data available (end-of-file)
+public static int STATUS_JAMMED = 6; // document feeder jammed
+public static int STATUS_NO_DOCS = 7; // document feeder out of documents
+public static int STATUS_COVER_OPEN = 8;// scanner cover is open
+public static int STATUS_IO_ERROR = 9; // error during device I/O
+public static int STATUS_NO_MEM = 10; // out of memory
+ // access to resource has been denied
+public static int STATUS_ACCESS_DENIED = 11;
+ //
+ // Initialize when class is loaded.
+ //
+static {
+ System.loadLibrary("sanej");
+ }
+ //
+ // Private methods:
+ //
+ // Get list of devices.
+private native int getDevicesNative(
+ SaneDevice[] deviceList, boolean localOnly);
+ // Get option descriptor.
+private native void getOptionNative(int handle, int option, SaneOption opt);
+ //
+ // Public methods:
+ //
+public Sane()
+ { }
+public int fix(double v)
+ { return (int) ((v) * (1 << FIXED_SCALE_SHIFT)); }
+public double unfix(int v)
+ { return (double)(v) / (1 << FIXED_SCALE_SHIFT); }
+public int versionMajor(int code)
+ { return ((code) >> 24) & 0xff; }
+public int versionMinor(int code)
+ { return ((code) >> 16) & 0xff; }
+public int versionBuild(int code)
+ { return ((code) >> 0) & 0xffff; }
+ //
+ // SANE interface.
+ //
+ // Initialize, and return STATUS_
+public native int init(int[] versionCode);
+public native void exit(); // All done.
+ // Get list of devices.
+public int getDevices(SaneDevice[] deviceList, boolean localOnly)
+ {
+ // Create objects first.
+ for (int i = 0; i < deviceList.length - 1; i++)
+ deviceList[i] = new SaneDevice();
+ return getDevicesNative(deviceList, localOnly);
+ }
+ // Open a device.
+public native int open(String deviceName, int[] handle);
+ // Close a device.
+public native void close(int handle);
+ // Get option descriptor.
+public SaneOption getOptionDescriptor(int handle, int option)
+ {
+ SaneOption opt = new SaneOption();
+ opt.name = null;
+ getOptionNative(handle, option, opt);
+ if (opt.name == null) // Error?
+ return (null);
+ return (opt);
+ }
+ // Get each type of option:
+public native int getControlOption(int handle, int option, int [] value,
+ int [] info);
+public native int getControlOption(int handle, int option, byte [] value,
+ int [] info);
+ // Set each type of option (SET_VALUE or
+ // SET_AUTO):
+public native int setControlOption(int handle, int option,
+ int action, int value, int [] info);
+public native int setControlOption(int handle, int option,
+ int action, String value, int [] info);
+public native int getParameters(int handle, SaneParameters params);
+public native int start(int handle);
+public native int read(int handle, byte [] data,
+ int maxLength, int [] length);
+public native void cancel(int handle);
+public native String strstatus(int status);
+}
diff --git a/japi/SaneDevice.java b/japi/SaneDevice.java
new file mode 100644
index 0000000..dc73365
--- /dev/null
+++ b/japi/SaneDevice.java
@@ -0,0 +1,55 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+//
+// SaneDevice.java - Device Descriptor.
+//
+// Written: 10/9/97 - JSF
+//
+
+public class SaneDevice
+{
+public String name; // unique device name
+public String vendor; // device vendor string
+public String model; // device model name
+public String type; // device type (e.g., "flatbed scanner")
+}
+
+
diff --git a/japi/SaneOption.java b/japi/SaneOption.java
new file mode 100644
index 0000000..ed460c7
--- /dev/null
+++ b/japi/SaneOption.java
@@ -0,0 +1,145 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+//
+// SaneOption.java - Sane option descriptor.
+//
+// Written: 10/9/97 - JSF
+//
+
+public class SaneOption
+ {
+ //
+ // Sane option types:
+ //
+ public static final int TYPE_BOOL = 0;
+ public static final int TYPE_INT = 1;
+ public static final int TYPE_FIXED = 2;
+ public static final int TYPE_STRING = 3;
+ public static final int TYPE_BUTTON = 4;
+ public static final int TYPE_GROUP = 5;
+ //
+ // Sane value units:
+ //
+ public static final int UNIT_NONE = 0; // the value is unit-less
+ // (e.g., # of scans)
+ public static final int UNIT_PIXEL = 1; // value is number of pixels
+ public static final int UNIT_BIT = 2; // value is number of bits
+ public static final int UNIT_MM = 3; // value is millimeters
+ public static final int UNIT_DPI = 4; // value is res. in dots/inch
+ public static final int UNIT_PERCENT = 5;// value is a percentage
+ //
+ // Option capabilities:
+ //
+ public static final int CAP_SOFT_SELECT = (1 << 0);
+ public static final int CAP_HARD_SELECT = (1 << 1);
+ public static final int CAP_SOFT_DETECT = (1 << 2);
+ public static final int CAP_EMULATED = (1 << 3);
+ public static final int CAP_AUTOMATIC = (1 << 4);
+ public static final int CAP_INACTIVE = (1 << 5);
+ public static final int CAP_ADVANCED = (1 << 6);
+ //
+ // Constraints:
+ //
+ public static final int CONSTRAINT_NONE = 0;
+ public static final int CONSTRAINT_RANGE = 1;
+ public static final int CONSTRAINT_WORD_LIST = 2;
+ public static final int CONSTRAINT_STRING_LIST = 3;
+ //
+ // Actions for controlOption():
+ //
+ public static final int ACTION_GET_VALUE = 0;
+ public static final int ACTION_SET_VALUE = 1;
+ public static final int ACTION_SET_AUTO = 2;
+
+ //
+ // Flags passed back in 'info' field param. of
+ // setControlOption():
+ //
+ public static final int INFO_INEXACT = (1 << 0);
+ public static final int INFO_RELOAD_OPTIONS = (1 << 1);
+ public static final int INFO_RELOAD_PARAMS = (1 << 2);
+
+ //
+ // Class members:
+ //
+ public String name; // name of this option (command-line name)
+ public String title; // title of this option (single-line)
+ public String desc; // description of this option (multi-line)
+ public int type; // how are values interpreted? (TYPE_)
+ public int unit; // what is the (physical) unit? (UNIT_)
+ public int size;
+ public int cap; // capabilities
+ public int constraintType;
+ // These are a union in the "C" API:
+ // Null-terminated list:
+ public String[] stringListConstraint;
+ // First element is list-length:
+ public int[] wordListConstraint;
+ public SaneRange rangeConstraint;
+ //
+ // Public methods:
+ //
+ public boolean is_active()
+ { return ((cap) & CAP_INACTIVE) == 0; }
+ public boolean is_settable()
+ { return ((cap) & CAP_SOFT_SELECT) == 0; }
+ // Return string describing units.
+ // "unitLength" is # mm. preferred.
+ public String unitString(double unitLength)
+ {
+ switch (unit)
+ {
+ case UNIT_NONE: return "none";
+ case UNIT_PIXEL: return "pixel";
+ case UNIT_BIT: return "bit";
+ case UNIT_DPI: return "dpi";
+ case UNIT_PERCENT: return "%";
+ case UNIT_MM:
+ if (unitLength > 9.9 && unitLength < 10.1)
+ return "cm";
+ else if (unitLength > 25.3 && unitLength < 25.5)
+ return "in";
+ return "mm";
+ }
+ return "";
+ }
+ }
+
diff --git a/japi/SaneParameters.java b/japi/SaneParameters.java
new file mode 100644
index 0000000..4e629c4
--- /dev/null
+++ b/japi/SaneParameters.java
@@ -0,0 +1,68 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+//
+// SaneParameters.java - Sane parameters.
+//
+// Written: 10/14/97 - JSF
+//
+
+public class SaneParameters
+{
+ //
+ // Frame values:
+ //
+public static final int FRAME_GRAY = 0; // band covering human visual range
+public static final int FRAME_RGB = 1; // pixel-interleaved
+ // red/green/blue bands
+public static final int FRAME_RED = 2; // red band only
+public static final int FRAME_GREEN = 3;// green band only
+public static final int FRAME_BLUE = 4; // blue band only
+
+ //
+ // Class members:
+ //
+public int format;
+public boolean lastFrame;
+public int bytesPerLine;
+public int pixelsPerLine;
+public int lines;
+public int depth;
+}
diff --git a/japi/SaneRange.java b/japi/SaneRange.java
new file mode 100644
index 0000000..4790e32
--- /dev/null
+++ b/japi/SaneRange.java
@@ -0,0 +1,53 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+//
+// SaneRange.java - Sane range info.
+//
+// Written: 10/9/97 - JSF
+//
+
+public class SaneRange
+{
+public int min; // minimum (element) value
+public int max; // maximum (element) value
+public int quant; // Quantization value (0 if none)
+}
+
diff --git a/japi/ScanIt.java b/japi/ScanIt.java
new file mode 100644
index 0000000..21afba0
--- /dev/null
+++ b/japi/ScanIt.java
@@ -0,0 +1,391 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+/**
+ ** ScanIt.java - Do the actual scanning for SANE.
+ **
+ ** Written: 11/3/97 - JSF
+ **/
+
+import java.util.Vector;
+import java.util.Enumeration;
+import java.awt.image.ImageProducer;
+import java.awt.image.ImageConsumer;
+import java.awt.image.ColorModel;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.BufferedWriter;
+import java.io.IOException;
+
+/*
+ * This class uses SANE to scan an image.
+ */
+public class ScanIt implements ImageProducer
+ {
+ // # lines we incr. image height.
+ private static final int STRIP_HEIGHT = 256;
+ private Sane sane;
+ private int handle = 0; // SANE device handle.
+ private Vector consumers = new Vector();
+ // File to write to.
+ private OutputStream outputFile = null;
+ private SaneParameters parms = new SaneParameters();
+ private ColorModel cm; // RGB color model.
+ private int width, height; // Dimensions.
+ private int x, y; // Position.
+ private int image[] = null; // Image that we build as we scan.
+ private int offset; // Offset within image in pixels if
+ // doing separate frames, bytes
+ // (3/word) if RBG.
+
+ /*
+ * Tell consumers our status. The scan is also terminated de-
+ * pending on the status.
+ */
+ private void tellStatus(int s)
+ {
+ Enumeration next = consumers.elements();
+ while (next.hasMoreElements())
+ {
+ ImageConsumer ic = (ImageConsumer) next.nextElement();
+ ic.imageComplete(s);
+ }
+ // Done? Stop scan.
+ if (s == ImageConsumer.STATICIMAGEDONE ||
+ s == ImageConsumer.IMAGEERROR)
+ sane.cancel(handle);
+ }
+
+ /*
+ * Tell consumers the image size.
+ */
+ private void tellDimensions(int w, int h)
+ {
+ System.out.println("tellDimensions: " + w + ", " + h);
+ Enumeration next = consumers.elements();
+ while (next.hasMoreElements())
+ {
+ ImageConsumer ic = (ImageConsumer) next.nextElement();
+ ic.setDimensions(w, h);
+ }
+ }
+
+ /*
+ * Send pixels to the clients.
+ */
+ private void tellPixels(int x, int y, int w, int h)
+ {
+/*
+ System.out.println("image length=" + image.length);
+ System.out.println("width=" + width);
+ System.out.println("tellPixels: x="+x +" y="+y + " w="+w
+ + " h="+h);
+ */
+ Enumeration next = consumers.elements();
+ while (next.hasMoreElements())
+ {
+ ImageConsumer ic = (ImageConsumer) next.nextElement();
+ ic.setPixels(x, y, w, h, cm, image, 0, width);
+ }
+ }
+
+ /*
+ * Construct.
+ */
+ public ScanIt(Sane s, int hndl)
+ {
+ sane = s;
+ handle = hndl;
+ }
+
+ /*
+ * Add a consumer.
+ */
+ public synchronized void addConsumer(ImageConsumer ic)
+ {
+ if (consumers.contains(ic))
+ return; // Already here.
+ consumers.addElement(ic);
+ }
+
+ /*
+ * Is a consumer in the list?
+ */
+ public synchronized boolean isConsumer(ImageConsumer ic)
+ { return consumers.contains(ic); }
+
+ /*
+ * Remove consumer.
+ */
+ public synchronized void removeConsumer(ImageConsumer ic)
+ { consumers.removeElement(ic); }
+
+ /*
+ * Add a consumer and start scanning.
+ */
+ public void startProduction(ImageConsumer ic)
+ {
+ System.out.println("In startProduction()");
+ addConsumer(ic);
+ scan();
+ }
+
+ /*
+ * Set file to write to.
+ */
+ public void setOutputFile(OutputStream o)
+ { outputFile = o; }
+
+ /*
+ * Ignore this:
+ */
+ public void requestTopDownLeftRightResend(ImageConsumer ic)
+ { }
+
+ /*
+ * Go to next line in image, reallocating if necessary.
+ */
+ private void nextLine()
+ {
+ x = 0;
+ ++y;
+ if (y >= height || image == null)
+ { // Got to reallocate.
+ int oldSize = image == null ? 0 : width*height;
+ height += STRIP_HEIGHT; // Add more lines.
+ int newSize = width*height;
+ int[] newImage = new int[newSize];
+ int i;
+ if (oldSize != 0) // Copy old data.
+ for (i = 0; i < oldSize; i++)
+ newImage[i] = image[i];
+ // Fill new pixels with 0's, setting
+ // alpha channel.
+ for (i = oldSize; i < newSize; i++)
+ newImage[i] = (255 << 24);
+ image = newImage;
+ System.out.println("nextLine: newSize="+newSize);
+ // Tell clients.
+ tellDimensions(width, height);
+ }
+ }
+
+ /*
+ * Process a buffer of data.
+ */
+ private boolean process(byte[] data, int readLen)
+ {
+ int prevY = y > 0 ? y : 0; // Save current Y-coord.
+ int i;
+ switch (parms.format)
+ {
+ case SaneParameters.FRAME_RED:
+ case SaneParameters.FRAME_GREEN:
+ case SaneParameters.FRAME_BLUE:
+ System.out.println("Process RED, GREEN or BLUE");
+ int cindex = 2 - (parms.format - SaneParameters.FRAME_RED);
+ // Single frame.
+ for (i = 0; i < readLen; ++i)
+ { // Doing a single color frame.
+ image[offset + i] |=
+ (((int) data[i]) & 0xff) << (8*cindex);
+ ++x;
+ if (x >= width)
+ nextLine();
+ }
+ break;
+ case SaneParameters.FRAME_RGB:
+ for (i = 0; i < readLen; ++i)
+ {
+ int b = 2 - (offset + i)%3;
+ image[(offset + i)/3] |=
+ (((int) data[i]) & 0xff) << (8*b);
+ if (b == 0)
+ {
+ ++x;
+ if (x >= width)
+ nextLine();
+ }
+ }
+ break;
+ case SaneParameters.FRAME_GRAY:
+ System.out.println("Process GREY");
+ // Single frame.
+ for (i = 0; i < readLen; ++i)
+ {
+ int v = ((int) data[i]) & 0xff;
+ image[offset + i] |= (v<<16) | (v<<8) | (v);
+ ++x;
+ if (x >= width)
+ nextLine();
+ }
+ break;
+ }
+ offset += readLen; // Update where we are.
+ // Show it.
+ System.out.println("PrevY = " + prevY + ", y = " + y);
+// tellPixels(0, prevY, width, y - prevY);
+ tellPixels(0, 0, width, height);
+ return true;
+ }
+
+ /*
+ * Start scanning.
+ */
+ public void scan()
+ {
+ int dataLen = 32*1024;
+ byte [] data = new byte[dataLen];
+ int [] readLen = new int[1];
+ int frameCnt = 0;
+ // For now, use default RGB model.
+ cm = ColorModel.getRGBdefault();
+ int status;
+ image = null;
+ do // Do each frame.
+ {
+ frameCnt++;
+ x = 0; // Init. position.
+ y = -1;
+ offset = 0;
+ System.out.println("Reading frame #" + frameCnt);
+ status = sane.start(handle);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("start() failed. Status= "
+ + status);
+ tellStatus(ImageConsumer.IMAGEERROR);
+ return;
+ }
+ status = sane.getParameters(handle, parms);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("getParameters() failed. Status= "
+ + status);
+ tellStatus(ImageConsumer.IMAGEERROR);
+ return; //++++cleanup.
+ }
+ if (frameCnt == 1) // First time?
+ {
+ width = parms.pixelsPerLine;
+ if (parms.lines >= 0)
+ height = parms.lines - STRIP_HEIGHT + 1;
+ else // Hand-scanner.
+ height = 0;
+ nextLine(); // Allocate image.
+ }
+ while ((status = sane.read(handle, data, dataLen, readLen))
+ == Sane.STATUS_GOOD)
+ {
+ System.out.println("Read " + readLen[0] + " bytes.");
+ if (!process(data, readLen[0]))
+ {
+ tellStatus(ImageConsumer.IMAGEERROR);
+ return;
+ }
+ }
+ if (status != Sane.STATUS_EOF)
+ {
+ System.out.println("read() failed. Status= "
+ + status);
+ tellStatus(ImageConsumer.IMAGEERROR);
+ return;
+ }
+ }
+ while (!parms.lastFrame);
+ height = y; // For now, send whole image here.
+ tellDimensions(width, height);
+ tellPixels(0, 0, width, height);
+ if (outputFile != null) // Write to file.
+ {
+ try
+ {
+ write(outputFile);
+ }
+ catch (IOException e)
+ { //+++++++++++++++
+ System.out.println("I/O error writing file.");
+ }
+ outputFile = null; // Clear for next time.
+ }
+ tellStatus(ImageConsumer.STATICIMAGEDONE);
+ image = null; // Allow buffer to be freed.
+ }
+
+ /*
+ * Write ppm/pnm output for last scan to a file.
+ */
+ private void write(OutputStream out) throws IOException
+ {
+ PrintWriter pout = new PrintWriter(out);
+ BufferedWriter bout = new BufferedWriter(pout);
+ int len = width*height; // Get # of pixels.
+ int i;
+ switch (parms.format)
+ {
+ case SaneParameters.FRAME_RED:
+ case SaneParameters.FRAME_GREEN:
+ case SaneParameters.FRAME_BLUE:
+ case SaneParameters.FRAME_RGB:
+ pout.print("P6\n# SANE data follows\n" +
+ width + ' ' + height + "\n255\n");
+ for (i = 0; i < len; i++)
+ {
+ int pix = image[i];
+ bout.write((pix >> 16) & 0xff);
+ bout.write((pix >> 8) & 0xff);
+ bout.write(pix & 0xff);
+ }
+ break;
+ case SaneParameters.FRAME_GRAY:
+ pout.print("P5\n# SANE data follows\n" +
+ width + ' ' + height + "\n255\n");
+ for (i = 0; i < len; i++)
+ {
+ int pix = image[i];
+ bout.write(pix & 0xff);
+ }
+ break;
+ }
+
+ bout.flush(); // Flush output.
+ pout.flush();
+ }
+ }
diff --git a/japi/Test.java b/japi/Test.java
new file mode 100644
index 0000000..52a7112
--- /dev/null
+++ b/japi/Test.java
@@ -0,0 +1,175 @@
+/* sane - Scanner Access Now Easy.
+ Copyright (C) 1997 Jeffrey S. Freedman
+ This file is part of the SANE package.
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ MA 02111-1307, USA.
+
+ As a special exception, the authors of SANE give permission for
+ additional uses of the libraries contained in this release of SANE.
+
+ The exception is that, if you link a SANE library with other files
+ to produce an executable, this does not by itself cause the
+ resulting executable to be covered by the GNU General Public
+ License. Your use of that executable is in no way restricted on
+ account of linking the SANE library code into it.
+
+ This exception does not, however, invalidate any other reasons why
+ the executable file might be covered by the GNU General Public
+ License.
+
+ If you submit changes to SANE to the maintainers to be included in
+ a subsequent release, you agree by submitting the changes that
+ those changes may be distributed with this exception intact.
+
+ If you write modifications of your own for SANE, it is your choice
+ whether to permit this exception to apply to your modifications.
+ If you do not wish that, delete this exception notice. */
+
+class Test
+{
+public static void main(String[] args)
+ {
+ Sane sane = new Sane();
+ int version[] = new int[1]; // Array to get version #.
+ int status = sane.init(version);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("getDevices() failed. Status= " + status);
+ return;
+ }
+ System.out.println("VersionMajor =" + sane.versionMajor(version[0]));
+ System.out.println("VersionMinor =" + sane.versionMinor(version[0]));
+ System.out.println("VersionBuild =" + sane.versionBuild(version[0]));
+ // Get list of devices.
+ // Allocate room for 50.
+ SaneDevice devList[] = new SaneDevice[50];
+ status = sane.getDevices(devList, false);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("getDevices() failed. Status= " + status);
+ return;
+ }
+ for (int i = 0; i < 50 && devList[i] != null; i++)
+ {
+ System.out.println("Device '" + devList[i].name + "' is a " +
+ devList[i].vendor + " " + devList[i].model + " " +
+ devList[i].type);
+ }
+ int handle[] = new int[1];
+ status = sane.open(devList[0].name, handle);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("open() failed. Status= " + status);
+ return;
+ }
+ System.out.println("Open handle=" + handle[0]);
+ // Get # of device options.
+ int numDevOptions[] = new int[1];
+ status = sane.getControlOption(handle[0], 0, numDevOptions, null);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("controlOption() failed. Status= "
+ + status);
+ return;
+ }
+ System.out.println("Number of device options=" + numDevOptions[0]);
+ for (int i = 0; i < numDevOptions[0]; i++)
+ {
+ SaneOption opt = sane.getOptionDescriptor(handle[0], i);
+ if (opt == null)
+ {
+ System.out.println("getOptionDescriptor() failed for "
+ + i);
+ continue;
+ }
+ System.out.println("Option name: " + opt.name);
+ System.out.println("Option title: " + opt.title);
+ System.out.println("Option desc: " + opt.desc);
+ switch (opt.constraintType)
+ {
+ case SaneOption.CONSTRAINT_RANGE:
+ System.out.println("Range: " +
+ opt.rangeConstraint.min + ", " +
+ opt.rangeConstraint.max + ", " +
+ opt.rangeConstraint.quant);
+ break;
+ case SaneOption.CONSTRAINT_WORD_LIST:
+ System.out.print("Word list: ");
+ for (int j = 0; j < opt.wordListConstraint[0]; j++)
+ System.out.print(opt.wordListConstraint[j]);
+ System.out.println();
+ break;
+ case SaneOption.CONSTRAINT_STRING_LIST:
+ for (int j = 0; opt.stringListConstraint[j] != null;
+ j++)
+ System.out.print("String constraint: " +
+ opt.stringListConstraint[j]);
+ break;
+ default:
+ System.out.println("No constraint.");
+ break;
+ }
+ }
+ status = sane.setControlOption(handle[0], 2,
+ SaneOption.ACTION_SET_VALUE, "../test1.pnm", null);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("setControlOption() failed. Status= "
+ + status);
+ }
+ //
+ // Main scanning loop.
+ //
+ SaneParameters parm = new SaneParameters();
+ int dataLen = 32*1024;
+ byte [] data = new byte[dataLen];
+ int [] readLen = new int[1];
+ int frameCnt = 0;
+ do
+ {
+ frameCnt++;
+ System.out.println("Reading frame #" + frameCnt);
+ status = sane.start(handle[0]);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("start() failed. Status= "
+ + status);
+ return;
+ }
+ status = sane.getParameters(handle[0], parm);
+ if (status != Sane.STATUS_GOOD)
+ {
+ System.out.println("getParameters() failed. Status= "
+ + status);
+ return; //++++cleanup.
+ }
+ while ((status = sane.read(handle[0], data, dataLen, readLen))
+ == Sane.STATUS_GOOD)
+ {
+ System.out.println("Read " + readLen[0] + " bytes.");
+ // ++++++++Process data.
+ }
+ if (status != Sane.STATUS_EOF)
+ {
+ System.out.println("read() failed. Status= "
+ + status);
+ }
+ }
+ while (!parm.lastFrame);
+
+ sane.close(handle[0]);
+ }
+}