ごった煮

色々な事を書いてます

UWPでバーコードを読んでみる

10 mobileでバーコードバトラー的なものが安く作れないか考えた末にとりあえずバーコードを読む知見を得たのでまとめます。

基本は、Webに転がってるサンプルを流用しますが、それだけだと引っかかった部分がメインです。

ちなみに通常バーコードを読むためのスキャナ的な奴は、数千円から数万円まで幅広い価格帯で普通にお金かかる & PCとかで使うとキーボード入力としてデータが飛んでくる等々最高に使い辛いので普通にWebカメラとか使った方が楽っぽいです。

実装順序

  1. 必要なパッケージを追加する
  2. カメラを初期化、起動
  3. バーコード読み取り

 

こんな感じです。

 

必要なパッケージ

必要なパッケージは、以下の二つです。両方NuGetから入れます。

  1. ZXing.Net
  2. WriteableBitmapEx

ZXingは、カメラからバーコード読み取りをしたりするためのライブラリの.NET版です。 NugetだとZXingとZXing.Netが出てきますが、.Netがついてる方がUWPで使えるやつです。

WriteableBitmapExは、WriteableBitmapをストリームのデータから引っ張り出すことができるようになる拡張が実装されたあれです。

 

カメラの初期化

初期化の前にアプリマニフェストにアクセス許可を追加します。

今回は、MediaCaptureクラスを使うのでカメラとマイクのアクセスに対して許可を出します。

カメラだけでもMediaCaptureクラスは、マイクも許可しないと怒られるので注意

 

マニフェストを書き換えたら下のコードみたいな感じでカメラを初期化してオープンにします。

InitializeAsyncに何も引数を渡さないと適当に繋がってるカメラからどれかが初期化されるみたいな挙動らしいです。

 

カメラからの入力は、CaptureElementのSourceに設定しているのでXAMLに適当に貼り付けましょう。

今回は、CapturePreviewっていう名前になってます。(下記のコードで

 

        private async Task InitCamera()
        {
            if(capture != null)
            {
                return;
            }

        capture = new MediaCapture();
        var devices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
        var cameraId = devices.ElementAt(0);

        var setting = new MediaCaptureInitializationSettings();
        setting.VideoDeviceId = cameraId.Id;

        try
        {
            await capture.InitializeAsync(setting);
            CapturePreview.Source = capture;

            await capture.StartPreviewAsync();

            ReadBarcode();
        }
        catch(Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

 

バーコードを読み取る

バーコードバトラーがしたいってことは、バーコードを読まなきゃなので以下のコードをタイマーで定期的に回します。

 

        private async void ReadBarcode()
        {
            var property = ImageEncodingProperties.CreateJpegXR();
            property.Width = 480;
            property.Height = 360;

            var rndStream = new InMemoryRandomAccessStream();

            try
            {
                await capture.CapturePhotoToStreamAsync(property, rndStream);
                rndStream.Seek(0);

                var bitmap = new BitmapImage();
                bitmap.SetSource(rndStream);

                var writeableBitmap = new WriteableBitmap(480, 360);

                writeableBitmap = await writeableBitmap.FromStream(rndStream);

                var reader = new BarcodeReader();

                var result = reader.Decode(writeableBitmap);

                if(result != null)
                {
                    Debug.WriteLine(result.ToString());
                    num++;
                    ReadedCount.Text = num.ToString();
                }
            }
            catch
            {

            }
        }

 

まとめ

CameraCaptureUIから取得したデータを使う場合は、また今度ということで。

例外処理とか甘々なんでそこらへんアプリに組み込むときは、気を付けましょう。

 

今回は、タイマーを定期的に回して読み取っているのでできればもっと頭のいい実装がしたい(小並感

あとこれIoT Coreで動くんですかね