pix
pix
andrew yager.com - andrew's home on the web
 
spacer Home

Tuesday, 02 December 2008

pix
pix
image bar at top of page
pix
pix
pix
Main Menu
Home
Blog
General News
Christianity Stuff
IT Stuff
Personal Stuff
Links
Contact Me
Search
News Feeds
Latest Updates
Who's Online
Login Form





Lost Password?
No account yet? Register
Syndicate

 

 
Web Based SANE scanner script PDF Print E-mail
Written by Andrew Yager   
Monday, 08 October 2007

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:

  1. Set up and test SANE (on RedHat this meant downloading and installing from the source ball to get the latest support for our scanner)
  2. 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)
  3. Set up PHP (on RedHat 5, this meant running yum install php php-cli and possibly a few other things too...)
  4. 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.
  5. Place this script into a web accessable directory (on this system I just put it in /var/www/html)
  6. 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>
Last Updated ( Monday, 08 October 2007 )
 
< Prev   Next >

pix
pix

copyright 2006 andrew yager and rwts