You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Windows STI API的Python基础图像采集实现求助

Working with Vidar Diagnostic Pro Advantage via STI API in Python (PyWin32)

Hey there! As someone coming from Linux and new to Windows API interop, I get how daunting this can feel at first. Let's walk through how to use PyWin32 to interact with the STI (Still Image Architecture) API for your scanner, since WIA isn't an option here.

First, a quick STI primer

STI is a lower-level Windows API for still image devices, and it uses both COM interfaces and raw Win32 functions. PyWin32 gives us two main tools to work with this: win32com.client for COM objects, and ctypes for calling unmanaged Win32 functions directly. We'll use both where needed.


Step 1: Enumerate STI Devices

First, let's make sure Python can see your Vidar scanner via STI. We'll use the IStiDeviceControl COM interface to list devices:

import win32com.client
import pythoncom

def enumerate_sti_devices():
    try:
        # Initialize COM (required for Windows API calls)
        pythoncom.CoInitialize()
        
        # Create the STI device manager
        sti_manager = win32com.client.Dispatch("Sti.StiDeviceManager")
        
        # Get the collection of STI devices
        devices = sti_manager.Devices
        
        print("Found STI devices:")
        for idx, device in enumerate(devices):
            print(f"{idx+1}. Name: {device.Name}, DeviceID: {device.DeviceID}")
            
        return devices
    except Exception as e:
        print(f"Error enumerating devices: {str(e)}")
    finally:
        pythoncom.CoUninitialize()

# Run the enumeration
sti_devices = enumerate_sti_devices()

Run this script—you should see your Vidar scanner listed. Note down the DeviceID or index, since we'll need it to connect to the device.

Step 2: Connect to the Scanner & Initialize a Scan Session

Next, we'll open the device and prepare it for scanning. We'll need to use some raw Win32 functions via ctypes here, since some STI operations aren't exposed via COM:

import ctypes
from ctypes import wintypes

# Define necessary STI constants (from Windows SDK headers)
STI_DIRECT = 0x00000001
STI_DEVICE_CREATE_BEST_ACCESS = 0x00000002

# Load the sti.dll
sti_dll = ctypes.WinDLL("sti.dll")

# Define function prototypes for STI API calls
sti_dll.StiCreateInstance.restype = wintypes.HRESULT
sti_dll.StiCreateInstance.argtypes = [
    wintypes.LPCWSTR,  # Device ID
    wintypes.LPVOID,   # Reserved (NULL)
    wintypes.DWORD,    # Access mode (STI_DIRECT)
    wintypes.DWORD,    # Creation flags
    wintypes.LPVOID,   # Pointer to IStiDevice interface
]

def open_sti_device(device_id):
    try:
        pythoncom.CoInitialize()
        
        # Prepare pointer to receive the IStiDevice interface
        sti_device = ctypes.c_void_p()
        hr = sti_dll.StiCreateInstance(
            device_id,
            None,
            STI_DIRECT,
            STI_DEVICE_CREATE_BEST_ACCESS,
            ctypes.byref(sti_device)
        )
        
        if hr != 0:  # HRESULT S_OK is 0
            raise Exception(f"Failed to open device. HRESULT: {hr}")
            
        print("Successfully connected to the scanner!")
        return sti_device
    except Exception as e:
        print(f"Error opening device: {str(e)}")
    finally:
        pythoncom.CoUninitialize()

# Use the DeviceID from Step 1 here
target_device_id = "YOUR_SCANNER_DEVICE_ID"
device_handle = open_sti_device(target_device_id)

Step 3: Configure Scan Settings & Trigger a Scan

Now, we need to send scan commands to the device. For basic scanning, we'll use the IStiDevice::RawReadData method to get the image data. Note that STI requires handling the device's native image format—for Vidar scanners, this is often TIFF or raw bitmap data.

Here's a simplified example to capture a scan and save it to a file:

def capture_scan(device_handle, output_path):
    try:
        # Convert the raw pointer to a COM object (IStiDevice)
        sti_device = win32com.client.CastTo(device_handle, "IStiDevice")
        
        # Initialize scan (send a command to the device to start scanning)
        # Note: Exact commands depend on your scanner's STI implementation
        # You may need to send a vendor-specific command here
        # For basic scans, some scanners respond to STI_CMD_SCAN
        sti_device.DeviceIoControl(0x00000001, None, None)  # Adjust control code as needed
        
        # Read the scanned image data
        buffer_size = 1024 * 1024  # 1MB buffer (adjust based on expected image size)
        buffer = ctypes.create_string_buffer(buffer_size)
        bytes_read = wintypes.DWORD()
        
        hr = sti_device.RawReadData(buffer, buffer_size, ctypes.byref(bytes_read))
        if hr != 0:
            raise Exception(f"Failed to read scan data. HRESULT: {hr}")
            
        # Save the raw data to a file (you may need to convert to TIFF/BMP first)
        with open(output_path, "wb") as f:
            f.write(buffer[:bytes_read.value])
            
        print(f"Scan saved to {output_path}")
    except Exception as e:
        print(f"Error capturing scan: {str(e)}")

# Capture a scan and save to output.tif
capture_scan(device_handle, "output.tif")

Important Notes & Troubleshooting

  • Vendor-Specific Commands: STI is device-agnostic, but some scanners require vendor-specific control codes or settings. You may need to refer to the Vidar scanner's STI documentation (included with their driver) for exact commands to trigger scans, set resolution, or define scan areas.
  • COM Initialization: Always call pythoncom.CoInitialize() before using COM objects, and pythoncom.CoUninitialize() afterward to clean up resources.
  • Admin Rights: Some STI operations require elevated privileges—run your Python script as Administrator if you get access denied errors.
  • Image Processing: The raw data from RawReadData may need post-processing. For TIFF data, you can use libraries like Pillow to load and manipulate the image for batch processing:
    from PIL import Image
    
    with Image.open("output.tif") as img:
        # Perform batch operations (resize, convert format, etc.)
        img.save("processed_scan.png")
    

Final Tips

Since you're used to Linux, think of STI as similar to sane (Scanner Access Now Easy) but for Windows—lower-level, requiring device-specific knowledge in some cases. PyWin32 bridges the gap between Python and Windows' native APIs, so take time to experiment with the COM interfaces and Win32 functions.

内容的提问来源于stack exchange,提问作者moo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 10:06:59