アプリからスキャンする

このトピックでは、フラットベッド、フィーダー、または自動構成のスキャン ソースを使用して、アプリからコンテンツをスキャンする方法について説明します。

スキャナー デバイスを取得する

アプリからスキャンするには、まず、コンピューターに接続されている使用可能なスキャナーを取得する必要があります。 Windows Image Acquisition (WIA) ドライバーでローカルにインストールされているスキャナーのみが一覧表示され、アプリで使用できます。

接続されたスキャナーを取得するには、システム DevicePicker UI を使用するか、Enumerate devices に示されているその他の Windows.Devices.Enumeration API を使用します。 どちらの場合も、 DeviceClass.ImageScanner 値をフィルターとして使用して、DevicePicker または DeviceWatcher に画像スキャナー デバイスのみが表示されるようにすることができます。

デバイス列挙 API は、コンピューターに接続されているデバイスを表す DeviceInformation オブジェクトを提供します。 スキャナーの DeviceInformation オブジェクトを取得したら、それを使用して ImageScanner オブジェクトを作成できます。 ImageScanner はアプリ コード内のスキャナーを表し、スキャンに使用するプロパティとメソッドにアクセスできます。

使用可能なスキャナーを選択する

この例では、システム DevicePicker を使用して、ユーザーが接続されているスキャナーを選択できるようにします。

DeviceInformation scannerDeviceInfo;
ImageScanner selectedScannerDevice;

private async Task InitializeScannerDevice()
{
    scannerDeviceInfo = await PickScannerDevice();
    if (scannerDeviceInfo is not null)
    {
        selectedScannerDevice = await ImageScanner.FromIdAsync(scannerDeviceInfo.Id);
        StatusBar.Message = $"Scanner selected: {scannerDeviceInfo.Name}.";
    }
    else
    {
        // Either no scanner is attached, or the user cancelled the device picker.
        StatusBar.Message = $"No scanner is selected.";
    }
}

private async Task<DeviceInformation> PickScannerDevice()
{
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(App.MainWindow);
    DevicePicker devicePicker = new();
    // Initialize the device picker with the window handle (HWND).
    WinRT.Interop.InitializeWithWindow.Initialize(devicePicker, hWnd);

    // Filter to show only image scanner devices in the picker.
    devicePicker.Filter.SupportedDeviceClasses.Add(DeviceClass.ImageScanner);

    scannerDeviceInfo = await devicePicker.PickSingleDeviceAsync(new Rect());
    return scannerDeviceInfo;
}

使用可能なスキャナーを列挙する

この例では、スキャナー デバイスの列挙は、Windows の DeviceWatcher クラスを使用して実行されます。Devices.Enumeration 名前空間。 詳細については、「 デバイスの追加」を参照してください。

  1. まず、これらの using ステートメントをクラス定義ファイルに追加します。
    using Windows.Devices.Enumeration;
    using Windows.Devices.Scanners;
  1. 次に、スキャナーの列挙を開始するデバイス ウォッチャーを実装します。
ObservableCollection<DeviceInformation> scannerDeviceList = new();

private async void WatchScanners()
{
    scannerDeviceList.Clear();
    deviceWatcher = DeviceInformation.CreateWatcher(DeviceClass.ImageScanner);

    deviceWatcher.Added += DeviceWatcher_Added;
    deviceWatcher.Removed += DeviceWatcher_Removed;
    deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;

    if (deviceWatcher.Status == DeviceWatcherStatus.Created)
    {
        deviceWatcher.Start();
    }
}
  1. デバイスの列挙が完了したときのイベント ハンドラーを作成します。
private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
{
    DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
    {
        if (scannerDeviceList.Count == 0)
        {
            StatusBar.Message = "No scanners found. Please make sure that your scanner is on and properly connected.";
        }
        else
        {
            StatusBar.Message = "Enumeration of scanners is complete.";
        }
    });
}
  1. スキャナーが追加または削除されたときのイベント ハンドラーを作成します。
private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate args)
{
    DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
    {
        scannerDeviceList.Remove(scannerDeviceList.Where(x => x.Id == args.Id).FirstOrDefault());
        StatusBar.Message = $"Scanner removed: {args.Id}";
    });
}

private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation args)
{
    DispatcherQueue.TryEnqueue(DispatcherQueuePriority.Normal, () =>
    {
        scannerDeviceList.Add(args);
        StatusBar.Message = $"Scanner added: {args.Name}";
    });
}

スキャン

スキャナーの構成とスキャンを行うには、Windows.Devices.Scanners 名前空間の API を使用します。 ImageScanner オブジェクトは、アプリ コード内のスキャナーを表し、スキャンに使用するプロパティとメソッドにアクセスできます。

前のセクションで示したように、ImageScanner.FromIdAsync を呼び出し、使用するスキャナーの DeviceInformation.Id を渡すことで、ImageScanner のインスタンスを作成します。

ImageScanner selectedScannerDevice;
selectedScannerDevice = await ImageScanner.FromIdAsync(scannerDeviceInfo.Id);

スキャンを実行するには、 ImageScanner.ScanFileToFolderAsync を呼び出し、スキャンのソースと宛先フォルダーを指定します。 ここでは、スキャン結果の保存先として Scans というフォルダーが画像ライブラリに作成されます。  

StorageFolder folder = await KnownFolders.PicturesLibrary.CreateFolderAsync("Scans", CreationCollisionOption.OpenIfExists);
                
ImageScannerScanResult result = await selectedScannerDevice.ScanFilesToFolderAsync(ImageScannerScanSource.Default,
        folder);

ソースをスキャンする

スキャナーは、フラットベッド、フィーダー、またはその両方をスキャン ソースとして持つことができます。 一部のスキャナーでは、 自動構成のスキャンもサポートされています。 これらのスキャン ソースは ImageScannerScanSource 列挙によって識別され、次のクラスによって表されます。

スキャン ソース オブジェクトを使用すると、次のことができます。

  • スキャン ソースがスキャナーでサポートされているかどうかを確認します。
    selectedScannerDevice.IsScanSourceSupported(ImageScannerScanSource.AutoConfigured);
    
  • スキャン ソースがプレビュー スキャンをサポートしているかどうかを確認します。
    selectedScannerDevice.IsPreviewSupported(ImageScannerScanSource.Feeder);
    
  • スキャン元のソースを指定します。
    selectedScannerDevice.ScanFilesToFolderAsync(ImageScannerScanSource.Flatbed, folder);
    

Important

既定以外のソースからプレビューまたはスキャンする場合は、まず、プレビュー スキャンと指定されたスキャン ソースがサポートされていることを確認する必要があります。

ImageScannerFlatbedConfiguration オブジェクトと ImageScannerFeederConfiguration オブジェクトを使用して、対応するスキャン ソースの多くのプロパティを読み取って設定することもできます。

既定のスキャン ソース

スキャナーの既定のスキャン ソースを取得するには、 ImageScanner.DefaultScanSource プロパティを使用します。 ImageScannerScanSource.Default 列挙値を使用して、既定のスキャン ソースを使用するように指定することもできます。

たとえば、次の 2 つの呼び出しは同等です。

selectedScannerDevice.ScanFilesToFolderAsync(ImageScannerScanSource.Default, folder);
selectedScannerDevice.ScanFilesToFolderAsync(selectedScannerDevice.DefaultScanSource, folder);

自動構成されたスキャン

自動構成設定を使用するには、スキャナーが自動構成に対して有効になっている必要があり、フラットベッドスキャナーとフィーダー スキャナーの両方を装備していない必要があります。 詳細については、「 自動構成スキャン」を参照してください。

アプリは、デバイスの Auto-Configured Scanning を使用して、最適なスキャン設定でスキャンできます。 このオプションを使用すると、デバイス自体は、スキャンされるコンテンツに基づいて、カラー モードやスキャン解像度などの最適なスキャン設定を決定できます。 デバイスは、新しいスキャン ジョブごとに実行時にスキャン設定を選択します。

Note

すべてのスキャナーがこの機能をサポートしているわけではないため、 IsScanSourceSupported を呼び出して、この設定を使用する前にスキャナーがこの機能をサポートしているかどうかを確認する必要があります。

この例では、まずスキャナーが自動構成に対応しているかどうかを確認し、対応している場合にのみスキャンを実行します。

if (selectedScannerDevice.IsScanSourceSupported(ImageScannerScanSource.AutoConfigured))
{
    // Scan API call to start scanning with Auto-Configured settings.
    ImageScannerScanResult result = await selectedScannerDevice.ScanFilesToFolderAsync(
        ImageScannerScanSource.AutoConfigured, folder);
}

スキャンをプレビューする

スキャナー デバイスでサポートされている場合は、フォルダーにスキャンする前にユーザーがスキャンをプレビューできるようにします。 この例では、アプリは、 Feeder スキャン ソースがプレビューをサポートしているかどうかを確認し、サポートされている場合はスキャンをプレビューします。

if (selectedScannerDevice.IsPreviewSupported(ImageScannerScanSource.Feeder))
{
    IRandomAccessStream stream = new InMemoryRandomAccessStream();
    // Scan API call to get preview from the Feeder.
    ImageScannerScanResult result = 
        await selectedScannerDevice.ScanPreviewToStreamAsync(ImageScannerScanSource.Feeder, stream);
    if (result.Succeeded)
    {
        // ScanPreviewImage is a XAML Image control (not shown).
        SetImageSourceFromStream(stream, ScanPreviewImage);
        StatusBar.Message = "Preview scan is complete.";
    }
    else
    {
        StatusBar.Message = $"Failed to preview from Feeder.";
    }
}
else
{
    StatusBar.Message = $"The selected scanner does not support preview from Feeder.";
}

このメソッドは、アプリ UI でプレビューを表示する方法を示します。

static async public void SetImageSourceFromStream(IRandomAccessStream stream, Image img)
{
    BitmapImage bitmap = await GetImageFromFile(stream);

    if ((bitmap.PixelHeight > img.Height) || (bitmap.PixelWidth > img.Width))
    {
        img.Stretch = Stretch.Uniform;
    }
    else
    {
        img.Stretch = Stretch.None;
    }
    img.Source = bitmap;
}

画像ライブラリへのスキャン

ユーザーは、FolderPicker クラスを使用して任意のフォルダーを動的にスキャンできますが、マニフェストで Pictures Library 機能を宣言して、ユーザーがそのフォルダーをスキャンできるようにする必要があります。 アプリの機能の詳細については、「 App 機能宣言」を参照してください。