ITHCWY: Robert Ellison's Blog

Catfood: PdfScan 1.40

Catfood: PdfScan 1.40

Catfood PdfScan 1.40 is a small bug fix release. PdfScan converts documents to PDFs with the help of a flatbed or automatic document feeder (ADF) scanner.

Catfood: WebCamSaver and PdfScan

Two new Catfood releases.

Catfood WebCamSaver 3.10 adds support for simultaneous updates in 4 and 16-cam modes. The WebCam Directory has also been completely overhauled. WebCamSaver is a rather voyeuristic screensaver that lets you watch live feeds from around the world. As well as a screensaver the feed is available in my World Webcams Google Gadget.

Catfood PdfScan 1.20 follows hot on the heels of 1.10. The main update is showing a preview of each scanned page which is super handy if you always forget which way pages are supposed to go in your document feeder. Mentioning no names…

Catfood: Earth, PdfScan and Weather

Three recent Catfood Software updates:

Catfood Earth 3.10 includes rotation to longitude / solar time, volcanoes, a screen saver, time zone updates and more. Catfood Earth uses satellite imagery and a variety of data feeds to render jaw-dropping live desktop wallpaper.

Catfood Earth 3.10

Catfood PdfScan 1.10 saves your selected paper size and feeder choices. There is also an option to keep PdfScan open after saving a scan, something that had been bugging me when slogging through large digitization projects. PdfScan is a free tool for scanning stuff into a PDF file.

Catfood PdfScan 1.10

Catfood Weather 2.00 includes weather alerts and an updated UI. Catfood Weather provides a free, taskbar based weather forecast for US locations.

Catfood Weather 2.00

Scanning multiple pages into a PDF file

PdfScan is a simple tool for scanning pages into a PDF file. You can scan single pages from a flatbed scanner or several pages from a document feeder. The page size applies to both the scan and the page(s) added to the PDF.

I wrote PdfScan because I know I'm going to be scanning a lot of documents over the next couple of weeks. Previously I used a tool called ScanToPDF from O Imaging but their licensing pissed me off so much that I'd rather waste time reinventing the wheel than pay them for another copy.

PdfScan - Scan pages to a PDF

This is a beta — it works with my scanner and my documents. There's no installer, so extract the ZIP file and run the EXE to use it. PdfScan requires the .NET 4.0 Framework. If you get an error when you run PdfScan.exe try installing .NET 4 and then run it again.

If enough people use this I'll make it a bit more friendly, add an installer and release it through Catfood. If you like it leave a comment below. If it doesn't work for you leave a comment or email me and I'll try to help.

(Update September 12, 2010: I've tided PdfScan up and released it through Catfood Software. Download from Catfood PdfScan.)

PdfScan uses PDFsharp from empira Software. Thanks chaps!

Scanning from the ADF using WIA in C#

Scanner ready for WIA image acquisition

I've been going nuts trying to scan from the document feeder on my Canon imageClass MF4150. Everything worked as expected from the flatbed, no dice trying to persuade the ADF to kick in. I found some sample code but it was oriented towards devices that can detect when a document is available in the feeder. Evidently my Canon doesn't expose this and so needs to be told the source to use.

The way to do this is to set the WIA_DPS_DOCUMENT_HANDLING_SELECT property to FEEDER. You then read WIA_DPS_DOCUMENT_HANDLING_STATUS to check that it's in the right mode and initiate the scan. This did not work for toffee.

After much experimentation I discovered a solution. I had been setting device properties and then setting item properties before requesting the scan. Switching the order - item then device - made everything work.

Here's the function to scan one page:

private XImage ScanOne()
{
    XImage ximage = null;

    try
    {
        // find our device (scanner previously selected with commonDialog.ShowSelectDevice)
        DeviceManager manager = new DeviceManager();
        DeviceInfo deviceInfo = null;
        foreach (DeviceInfo info in manager.DeviceInfos)
        {
            if (info.DeviceID == _deviceId)
            {
                deviceInfo = info;
            }
        }

        if (deviceInfo != null)
        {                    
            Device device = deviceInfo.Connect();
            CommonDialog commonDialog = new CommonDialog();

            Item item = device.Items[1];
            int dpi = 150;

            // configure item
            SetItemIntProperty(ref item, 6146, 2); // greyscale
            SetItemIntProperty(ref item, 6147, dpi); // 150 dpi
            SetItemIntProperty(ref item, 6148, dpi); // 150 dpi
            SetItemIntProperty(ref item, 6151, (int)(dpi * _width)); // scan width
            SetItemIntProperty(ref item, 6152, (int)(dpi * _height)); // scan height
            SetItemIntProperty(ref item, 4104, 8); // bit depth

            int deviceHandling = _adf ? 1 : 2; // 1 for ADF, 2 for flatbed

            // configure device
            SetDeviceIntProperty(ref device, 3088, deviceHandling); 
            int handlingStatus = GetDeviceIntProperty(ref device, 3087);

            if (handlingStatus == deviceHandling)
            {
                ImageFile image = commonDialog.ShowTransfer(item, formatJpeg, true);

                // save image to a temp file and then load into an XImage
                string tempPath = System.IO.Path.GetTempFileName();
                File.Delete(tempPath);
                tempPath = System.IO.Path.ChangeExtension(tempPath, "jpg");
                image.SaveFile(tempPath);
                ximage = XImage.FromFile(tempPath);

                _tempFilesToDelete.Add(tempPath);
            }
        }
    }
    catch (COMException ex)
    {
        ximage = null;

        // paper empty
        if ((uint)ex.ErrorCode != 0x80210003)
        {
            throw;
        }
    }

    return ximage;
}

A few notes — XImage is a type from PDFSharp. I wrote this as part of a PDF scanner that I'll post next so the scanned images are saved and then loaded into an XImage for rendering to the PDF document. The magic numbers come from WiaDef.h in the Platform SDK. If the ADF is out of pages this method sets the return image to null and eats the exception. This is because the function is called repeatedly to scan in pages until the ADF is empty if _adf is true (otherwise it grabs one image from the flatbed). 

If you've been banging your head against a wall trying to get WIA to work with a document feeder I hope this helps.

Updated 2015-05-20: Full source code at https://github.com/abfo/pdfscan