Using Apple's Virtual Scanner to Test Document Scanning Apps and SDKs on macOS

Apple provided a sample project demonstrating how to create a virtual scanner device a long time ago. The last revision was on June 12, 2012. In this article, we will build the sample project using the latest Xcode on macOS Sequoia and use it to test front-end document scanning applications like Image Capture and Dynamic Web TWAIN online demo.

macOS Virtual Scanner Demo Video

Prerequisites

Building the macOS Virtual Scanner

  1. Unzip the sample project and open it in Xcode.
  2. Build the source code. You will encounter the following error:

     Call to undeclared function 'require_action'; ISO C99 and later do not support implicit function declarations
    

    Call to undeclared function 'require_action'

    This error occurs because the require_action macro is defined in the Carbon framework, which has been deprecated. To fix the issue, define the macro in both VirtualScanner.m and EntryPoints.m:

     #define require_action(condition, exceptionLabel, action) \
         do { \
             if ( __builtin_expect(!(condition), 0) ) { \
                 action; \
                 goto exceptionLabel; \
             } \
         } while(0)
    
  3. The project includes a test.tiff file as the input source. Replace it with your own image.

    test.tiff

  4. Build the project to generate VirtualScanner.app. According to Apple’s documentation, the app must be placed in the /Library/Image Capture/Devices/ directory. However, this does not work as expected. To make the virtual scanner appear in the Image Capture app, run the project directly in Xcode instead.

    VirtualScanner.app in Image Capture

Testing the macOS Virtual Scanner

Known Issues

While running the macOS Virtual Scanner, we can only click the Scan button once with Dynamic Web TWAIN API. After acquiring a document, _ICD_ScannerCloseDevice is triggered, and the virtual scanner is subsequently terminated.

Source Code

https://github.com/yushulx/virtual-scanner/tree/main/macos