LoginSignup
4
5

More than 1 year has passed since last update.

【Swift】QRコードの分割情報を取得する

Posted at

iOSアプリでQRコードを読み込もうとしたら、QRコードが分割されている場合があることを知りました。

お薬手帳や車検証などにも使われているみたいです。

iOSアプリでその分割情報を取得する「これだ!」って方法が見つからなかったのでまとめておきます。

「いやいや、もっといい方法があるよ」という方はコメントいただけると助かります。。。

分割QRコードについて

スクリーンショット 2021-09-08 1.11.30.png
QRコードがなんぞやっていうのは割愛します。
ググってくださいませ。

今回伝えたいのは、QRコードは分割されることがあるということです。
上記のような2つのお薬手帳用のQRコードは2つ揃って必要な情報を取得できます。

1つのQRコードが保持できる情報量は決まっているため、
上限を超える情報量を出力するためにQRコードは分割できるって話です。

分割情報はどこにある?

QRコードをバイナリにすると分かります。

バイナリ情報 説明
1バイト目の最初4ビット 3だと分割QRコード
1バイト目の後ろ4ビット 分割されているQRコードの位置(0開始)
2バイト目の最初4ビット 分割されているQRコードの最大位置
2バイト目の後ろ4ビット パリティ1
3バイト目の最初4ビット パリティ2

はい、シンプルですね。
見ての通りですが、分割情報が4ビットしかないので最大16分割までしかできません。

ここに「00110000 00011001 00110010~」で始まるQRコードがあるとします。
16進数にすると「30 19 32~」となります。

先程の表に照らし合わせると、
1バイト目の最初4ビットが3なので、このQRコードは分割されていると分かります。
1バイト目の後ろ4ビットが0なので、分割QRの1番目だと分かります。(0スタートなので1番目です)
2バイト目の最初4ビットが1なので、QRコードの総数は2つだと分かります。
2バイト目の後ろ4ビットと3バイト目の最初4ビットは、パリティです。2つ目のQRコードと同じになるのでIDっぽく使えます。

ちなみに、上記のQRコードの2つ目のバイナリ(16進表記)は以下の通りとなります。
「31 19 34~」

Swiftでどう取得するのか?

AVFoundationでQRコードを読み取るときのデリゲートメソッド内に取得方法を記載します。

    func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        if let metadataObject = metadataObjects.first {
            guard let readableObject = metadataObject as? AVMetadataMachineReadableCodeObject else { return }
            guard let readableObjectForQRCode = readableObject.descriptor as? CIQRCodeDescriptor else { return }
            // 16進数のQRコード情報を取得
            let hexQRCodeData = readableObjectForQRCode.errorCorrectedPayload.map { String(format: "%02X", $0)}

            // 分割コードかチェック(trueなら分割コード)      
            let isSeparatedQRCode = hexQRCodeData.first!.hasPrefix("3")

            // 分割コードの総数を取得
            ​​​​​​​​let secondByteFirstHex = hexQRCodeData[1].prefix(1) + 1
            ​​​​​​​​let total = Int(secondByteFirstHex, radix: 16)!

            // 分割コードの位置を取得
            let ​​​​firstByteSecondHex = hexQRCodeData[0].suffix(1)
            let position = Int(firstByteSecondHex, radix: 16)!


        }
    }

AVFoundationでQRコードを読み取る方法は以下記事を参考

https://qiita.com/ikaasamay/items/58d1a401e98673a96fd2
https://dev.classmethod.jp/articles/ios-avfoundation/
https://dev.classmethod.jp/articles/ios-avfoundation-avcapturemetadataoutput-qrcode/

まとめ

そのうちAppleがいい感じのメソッドを提供しそうな気もする。
でも、とりあえずQRコードの仕様が分かればそんな難しくないので別に不要な気もする。
いずれにせよ困っている人の参考になれば幸い!

参考記事

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5