|
After a bit of discussion on the OSIA list today, I've decided to publish our PHP web based interface to SANE on the web. It's really basic, and scans and displays, but it works :-) And it sucks less than all the other web interfaces for SANE scanning out there. It's released under the GPL 3.0, and requires SANE front ends and back ends to be working correctly, and a *working* install of ImageMagick. (This does not include the standard distribution with RedHat or CentOS!).
To use: - Set up and test SANE (on RedHat this meant downloading and installing from the source ball to get the latest support for our scanner)
- Set up and test ImageMagick, particularly file type conversion (you need to get from PNM to PDF - so test that!) (on RedHat this meant compiling from binary sources as the version provided by yum is out of date and broken)
- Set up PHP (on RedHat 5, this meant running yum install php php-cli and possibly a few other things too...)
- Allow your web user to run the SANE binaries as root via sudo. There may be a way around this, but I couldn't find it - the problem came that every time we rebooted the system, only the root user had access to write to the USB proc interface. I played around with trying to change the default permissions, but in the end gave up and sudo was an easier solution for a closed internal system that has no external security risks.
- Place this script into a web accessable directory (on this system I just put it in /var/www/html)
- Create a directory called "scanout" to store the results of the scanning. I put it in /var/www/html, but if you put it somewhere else modify the script below. It will contain the results of the scan plus image thumbnails of the first page.
While I might be able to help you if something goes wrong, I'm really providing this script so that someone else doesn't have to do all the work I did, and if it works for you great, and if not - well, maybe you can make it work and let me know. If you make it better, and would like to share your betterness with the whole world, please let me know and I'll update it. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <?php /*********** 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 3 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, see <http://www.gnu.org/licenses/>. */ ?>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title>Scan A Document</title> <script type="text/javascript" charset="utf-8"> function hoverBlock(fileName) { var el = document.getElementById(fileName); el.style.background='#CCC'; el=null; } function unhoverBlock(fileName) { var el = document.getElementById(fileName); el.style.background='#FFF'; el=null; } function clickBlock(fileName) { window.open('scanout/'+fileName,'scanImage', 'width=800,height=600'); } function toggleOutput() { var el = document.getElementById('output'); var toggle = document.getElementById('showOutput'); if (el.style.display=='none'||el.style.display=='') { el.style.display='block'; toggle.innerHTML='Hide output from scanner'; } else { el.style.display='none'; toggle.innerHTML='Show output from scanner'; } el=null; toggle=null; } </script> <style type="text/css" media="screen"> .imageBlock { display:block; float: left; width: 200px; height:100px; border: 1px solid black; padding: 5px; text-align:center; margin-right: 5px; cursor: pointer; } .bigImage { display:block; float: left; width: 500px; height:500px; border: 1px solid black; padding: 5px; text-align:center; margin-right: 5px; cursor: pointer; } .error { display: block; background: #FCC; padding: 10px; border: 1px solid #F00; } .note { display: block; background: #CCF; padding: 10px; border: 1px solid #00F; } .output { display: none; } #showOutput { display: inline; padding: 5px; margin: 5px; border: 1px solid black; font-size:10px; font-weight: bold; background-color: #CCC; cursor: pointer; } body { font-family: Arial, "MS Trebuchet", sans-serif; margin: 5px; } </style> </head> <body> <?php if (isset($_POST["scan"])) { $findScanner = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("pipe", "w") // stderr is a file to write to ); $env=array(); $process = proc_open("sudo /usr/bin/sane-find-scanner", $findScanner, $pipes, '/tmp', $env); if (is_resource($process)) { $data = stream_get_contents($pipes[2]); $data .= stream_get_contents($pipes[1]); } proc_close($process); $match = preg_match('/libusb:\d+:\d+/', $data, $matches); if ($match&&count($matches)) { $address=$matches[0]; } echo "<h1>Scanner Output</h1>"; $fileName = "file-".date("y-m-d.H.i.s"); $descriptorspec = array( 0 => array("pipe", "r"), // stdin is a pipe that the child will read from 1 => array("pipe", "w"), // stdout is a pipe that the child will write to 2 => array("pipe", "w") // stderr is a file to write to ); $cwd = '/tmp'; $env = array();
$process = proc_open("sudo /usr/bin/scanadf -d fujitsu:$address --output-file ". "/var/www/html/scanout/$fileName-%04d -l 0mm -t 0mm -x 210mm -y 297mm". " --pagewidth 210mm --pageheight 297mm --source \"$_POST[format]\" ". "--mode $_POST[mode] --resolution $_POST[quality]", $descriptorspec, $pipes, $cwd, $env); if (is_resource($process)) { $errors = stream_get_contents($pipes[2]); $output = stream_get_contents($pipes[1]); } echo "<div id='showOutput' onclick='toggleOutput()'>Show output from scanner</div>"; echo "<div id='output' class='output'>"; echo "<h2>Output from scanner</h2>"; echo "<pre>$data$output$errors</pre>"; echo "<div class='note'><strong>Note:</strong> Ignore lines about rounding sizes</em></div>"; echo "</div>"; echo "<div> </div>"; $dirList = scandir("/var/www/html/scanout"); $inputFiles = array(); $firstFile = ""; foreach ($dirList as $file) { if (stristr($file, $fileName)) { //this is one of our input files if ($firstFile=="") $firstFile = $file; array_push($inputFiles, $file); } }
if (count($inputFiles)) { $path=""; foreach ($inputFiles as $file) { $path .= "pnm:/var/www/html/scanout/$file "; } $output = `/usr/bin/convert pnm:/var/www/html/scanout/$firstFile -resize '>300x' -strip /var/www/html/scanout/$firstFile.jpg`; $output .= `/usr/bin/convert -page a4 $path /var/www/html/scanout/$fileName.pdf`; echo "<div class='bigImage' id='$fileName' onMouseOver='hoverBlock(\"$fileName\");' "; echo "onclick='clickBlock(\"$fileName.pdf\")' onmouseout='unhoverBlock(\"$fileName\")' >"; echo "<img src='scanout/$firstFile.jpg' width=300 alt='scan image' /><br />$fileName.pdf</div>"; } else { echo "<div class='error'><strong>An error occured:</strong> No pages were scanned. Is there a document in the scanner?</div>"; } ob_flush(); $dirList=array_reverse($dirList); echo "<div style=\"clear:both\"></div>"; echo "<h2>Previously Scanned Files:</h2>"; foreach ($dirList as $file) { if (stristr($file, '.pdf')) { $img = str_replace('.pdf','-0001.jpg',$file); echo "<div class='imageBlock' id='$file' onMouseOver='hoverBlock(\"$file\");' onclick='clickBlock(\"$file\")' "; echo "onmouseout='unhoverBlock(\"$file\")' ><img src='scanout/$img' width=50 /><br />$file</div>"; ob_flush(); } } echo ""; } ?> <div style="clear:both;"></div> <h1>Scan an Image</h1> <form action="index.php" method="post"> Document Type: <select name="format"> <option value="ADF Duplex" selected="selected">Double Sided</option> <option value="ADF Front">Single Sided</option> </select><br /> Color Mode: <select name="mode"> <option value="Lineart" selected="selected">Lineart</option> <option value="Halftone">Halftone</option> <option value="Gray">Greyscale</option> <option value="Color">Colour</option> </select><br /> Quality: <select name="quality"> <option value="72dpi">Low</option> <option value="150dpi" selected="selected">Standard</option> <option value="300dpi">High</option> </select> <input type="hidden" name="scan" value="yes" /> <input type="submit" value="Scan!" /> </form> </body> </html> |