Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」...
Search
monoqlo
September 01, 2018
Programming
10
25k
「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」 / iOSDC 2018
iOSDC 2018 2018/09/01 14:40〜 Track B レギュラートーク(15分)
monoqlo
September 01, 2018
Tweet
Share
More Decks by monoqlo
See All by monoqlo
入門 SwiftUI Alignment Guide / iOSDC2022
monoqlo
10
4.4k
Hey Siri!マルチプラットフォームでのSiriショートカットの地雷を教えて / iOSDC2021
monoqlo
0
630
あなたのアプリ、✨リブランディング✨できますか? / iosdc2020
monoqlo
9
1.4k
実践 CallKit/PushKit ときどき🐛退治 / iOSDC 2019
monoqlo
4
3.3k
WWDC2016のススメ
monoqlo
0
92
Other Decks in Programming
See All in Programming
Swift Concurrencyとレースコンディション
objectiveaudio
1
410
How to Break into Reading Open Source
kaspth
1
210
RAGの回答精度評価用のQAデータセットを生成AIに作らせた話
kurahara
0
250
What is Parser
yui_knk
9
4.1k
Jakarta EE meets AI
ivargrimstad
0
370
Amazon Neptuneで始める初めてのグラフDB ー グラフDBを使う意味を考える ー
satoshi256kbyte
2
260
unique パッケージから学ぶ interning と weak reference @ Asakusa.go#3
karamaru
2
790
ブラウザ互換の重要性 - あらゆるユーザーに価値を届けるために必要なこと
yamanoku
0
110
LangGraphでのHuman-in-the-Loopの実装
os1ma
3
1.1k
【TID2024】模擬講義:プログラマと一緒にゲームをデザインしてみよう!
akatsukigames_tech
0
620
dRuby 入門者によるあなたの身近にあるdRuby 入門
makicamel
4
350
Web技術を駆使してユーザーの画面を「録画」する
yukukotani
13
6.6k
Featured
See All Featured
How to train your dragon (web standard)
notwaldorf
85
5.6k
Making the Leap to Tech Lead
cromwellryan
128
8.8k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
29
2.6k
Art, The Web, and Tiny UX
lynnandtonic
294
20k
Atom: Resistance is Futile
akmur
261
25k
Fontdeck: Realign not Redesign
paulrobertlloyd
80
5.1k
How STYLIGHT went responsive
nonsquared
93
5.1k
The Invisible Customer
myddelton
119
13k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
278
13k
Building Adaptive Systems
keathley
36
2.1k
Building Applications with DynamoDB
mza
90
6k
BBQ
matthewcrist
83
9.1k
Transcript
@monoqlo QRίʔυಡΈऔΓʁ ָউͰ͢Α AVFoundationΛ৴ͨ͡ ͓Ε͕όΧͩͬͨ
None
ḪΔ͜ͱ ಥવͰ͕͢
1
2017 3 ݄
ָউͰ͢Α✌✌ QRίʔυಡΈऔΔ ΞϓϦͭ͘ΕΔʁ
͜ͷ࣌ߟ͍͑ͯͨ͜ͱ
AVFoundation Ͱ༨༟Ͱ͠ΐ • AVCaptureSession • AVCaptureMetadataOutput • AVMetadataMachineReadableCodeObject • etc…
QRίʔυ ͞Εͨ
https://www.55truck.com/shaken.html
https://www.55truck.com/shaken.html
None
"8/-/1/-/- /- /999999/02” "2/- //160114/1001/BKG-NKR85” "AN/0168/- /- /0381/13/09” "2/ɹɹ̔̌̌ͤ̒̐̎” “̒/1/NKR85-7011300/4JJ1/1"
http://mangalifewin.takeshobo.co.jp/rensai/popute3/
"8/-/1/-/- /- /999999/02” "2/- //160114/1001/BKG-NKR85” "AN/0168/- /- /0381/13/09” "2/ɹɹ̔̌̌ͤ̒̐̎” “̒/1/NKR85-7011300/4JJ1/1"
"2/- //160114/1001/BKG-NKR85AN/0168/- /- /0381/13/098/-/1/-/- /- /999999/02” "2/ɹɹ̔̌̌ͤ̒̐̎̒/1/NKR85-7011300/4JJ1/1”
φχϞϊ ͜Ε…
None
http://www.qrcode.com
None
ͬͱ QRίʔυ ΛΖ͏
ใٕज़ʵࣗಈೝࣝٴͼσʔλऔಘٕज़ʵ ̧̦ίʔυόʔίʔυγϯϘϧମܥ༷ JIS ن֨ X0510
http://www.jisc.go.jp/
શ 115 ϖʔδ…
QRίʔυͷΈ μΠδΣετ൛
ࠇനϞδϡʔϧͷೝࣝ START ܕࣜใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ
“Ϟʔυ” ղऍ ෮߸͢ΔͨΊʹॏཁͳͷ͕
“Ϟʔυ” ͱ
• ECI • ߏత࿈ • FNC1 • (ऴύλʔϯ) • ࣈ
• ӳࣈ • 8ϏοτόΠτ • ࣈ Ϟʔυ = σʔλΛ֨ೲ͢Δܗࣜ • ѹॖޮ্Λతͱ͠ɺଟͷϞʔυ͕ఆٛ͞Ε͍ͯΔ • QRίʔυੜ࣌ɺσʔλʹ߹Θͤͯ࠷దͳͷΛબ͢Δ • ϔομʔͱͯ͠จࣈࢦࣔࢠͱͱʹσʔλʹՃ͢Δ • Έ߹Θͤͯ༻Մʢex. ӳࣈ + ࣈʣ ߏత࿈
• ࣈ • ӳࣈ • 8ϏοτόΠτ • ࣈ • ECI
• ߏత࿈ • FNC1 • (ऴύλʔϯ) Ϟʔυ = σʔλΛ֨ೲ͢Δܗࣜ • ѹॖޮ্Λతͱ͠ɺଟͷϞʔυ͕ఆٛ͞Ε͍ͯΔ • QRίʔυੜ࣌ɺσʔλʹ߹Θͤͯ࠷దͳͷΛબ͢Δ • ϔομʔͱͯ͠จࣈࢦࣔࢠͱͱʹσʔλʹՃ͢Δ • Έ߹Θͤͯ༻Մʢex. ӳࣈ + ࣈʣ ߏత࿈
ߏత࿈ Ϟʔυ
ϔομʔ༷ 1. Ϟʔυࢦࣔࢠʢ0011ʣɿ4bit 2. γϯϘϧྻࢦࣔࢠɿ8bit 1. γϯϘϧҐஔɿ4bit 2. ࿈݁͞ΕΔγϯϘϧͷ߹ܭɿ4bit 3.
ύϦςΟɿ8bit ׂલͷσʔλΛόΠτ͝ͱʹXORԋࢉͨ͠
None
ϓϩύςΟ var corners: [CGPoint] A Swift array of corner points.
var stringValue: String? Returns the error corrected data decoded into a human- readable string.
ͦΜͳͷͳ͍ AVMetadataMachineReadableCodeObject ʹ
ࠇനϞδϡʔϧͷೝࣝ START ܕࣜใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ AVMetadataMachine ReadableCodeObject ͷ
stringValue ෳ߹ޙͷίϨ
ϥΠϒϥϦΛ୳͢ ߏత࿈Λ͏·͘ѻ͑Δ
None Swift ͷϥΠϒϥϦ
None
ZXingObjC ٹੈओ TheLevelUp/ZXingObjC: An Objective-C Port of ZXing
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return }
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … }
γϯϘϧҐஔ/߹ܭͱύϦςΟ͕औΕΔ @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard
let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return } // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } @objc func captureResult(_ capture: ZXCapture!, result: ZXResult!) { guard let _ = result else { return } // ׂQRίʔυͷ߹ɺZXResult#resultMetadata ͷҎԼ2ͭΛ֬ೝͯ͠ // Ͳͷ෦ͷQRίʔυ͕ಡΈࠐ·Εͨͷ͔ఆ͢Δ͜ͱ͕Ͱ͖Δ // - kResultMetadataTypeStructuredAppendSequence // - kResultMetadataTypeStructuredAppendParity // sequence: ಡΈऔͬͨQRίʔυͷ൪߸ 4bit + τʔλϧͷQRίʔυ 4bit let bit = String(sequenceValue, radix: 2) let pad = String(repeating: "0", count: (8 - bit.count)) let sequence = pad + bit let current = Int(sequence.prefix(4), radix: 2)! let total = Int(sequence.suffix(from: 4), radix: 2)! … } guard let metaData = result.resultMetadata, let sequenceValue = metaData[Int(kResultMetadataTypeStructuredAppendSequence.rawValue)] as? Int, let parity = metaData[Int(kResultMetadataTypeStructuredAppendParity.rawValue)] as? Int else { return }
ղܾ ͬͨʔʂʂ
ຊʹʁ
ZXingObjC ͷऑ • ಡΈऔΓਫ਼͕͋·Γߴ͘ͳ͍ • AVFoundation σϯιʔެࣜΞϓϦʹൺΔͱ݁ߏ ͕͔͔࣌ؒΔ͜ͱ͕͋Δ • ։ൃ͕࣮࣭ࢭ·͍ͬͯΔ
• Swift ʹஔ͖͍͑ͨͱ͔ॻ͔ΕͯΔ͚Ͳ͍ͭʹͳΔ ͔·ͬͨ͘Θ͔Βͳ͍
ઈ ະདྷ͕ͳ͍
ઈ ະདྷ͕ͳ͍ ʁ
ઈ ະདྷ͕ͳ͍ ʁ 2017 ·Ͱͷ͓
࣌ྲྀΕ… 2018 9 ݄ 1
iOS ͷόʔδϣϯγΣΞભҠ ݄ ݄ ݄
݄ ݄ ݄ ݄ ݄ ݄ iOS 11 iOS 10 iOS 9 or Earlier ※ 20189݄༧ଌ
iOS 10 ͷαϙʔτ ͦΖͦΖΕ·͢ΑͶʁ ࠓ݄ iOS 12 ͕ϦϦʔε͞Ε·͢
CIQRCodeDescriptor ਅͷٹੈओ in AVMetadataMachineReadableCodeObject
ϓϩύςΟ var corners: [CGPoint] A Swift array of corner points.
var stringValue: String? Returns the error corrected data decoded into a human- readable string. var descriptor: CIBarcodeDescriptor? A barcode description for use in Core Image.
CIQRCodeDescriptor ͱ
CIQRCodeDescriptor ͱ • iOS 11 ͰՃ͞ΕͨڧྗͳΫϥε • நΫϥε CIBarcodeDescriptor ͷαϒΫϥε
• QRίʔυΛੜ͢ΔͨΊʹඞཁेͳσʔλΛ࣋ͭ • CIFilter Ͱ QRίʔυը૾Λੜ͢Δ͜ͱͰ͖Δ
CIQRCodeDescriptor ͱ • iOS 11 ͰՃ͞ΕͨڧྗͳΫϥε • நΫϥε CIBarcodeDescriptor ͷαϒΫϥε
• CIFilter Ͱ QRίʔυը૾Λੜ͢Δ͜ͱͰ͖Δ func generateQRCodeImage(from descriptor: CIQRCodeDescriptor) -> UIImage? { let inputParams: [String: Any] = ["inputBarcodeDescriptor": descriptor] let barcodeCreationFilter = CIFilter(name: "CIBarcodeGenerator", parameters: inputParams) guard let outputImage = barcodeCreationFilter?.outputImage, let cgImage = CIContext().createCGImage(outputImage, from: outputImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
େࣄͳͷ͜ͷ 2 ͭ var errorCorrectedPayload: Data The error-corrected payload containing
the data encoded in the QR code. var symbolVersion: Int The version of the QR code.
ࠇനϞδϡʔϧͷೝࣝ START ܕࣜใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ AVMetadataMachine ReadableCodeObject ͷ
stringValue ෳ߹ޙͷίϨ
ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ errorCorrectedPayload ίίͷσʔλʂ
େࣄͳͷ͜ͷ 2 ͭ var errorCorrectedPayload: Data The error-corrected payload containing
the data encoded in the QR code. var symbolVersion: Int The version of the QR code.
େࣄͳͷ͜ͷ 2 ͭ var errorCorrectedPayload: Data The error-corrected payload containing
the data encoded in the QR code. var symbolVersion: Int The version of the QR code.
จࣈࢦࣔࢠͷϏοτ ܕ൪ TZNCPM7FSTJPO ࣈ Ϟʔυ ӳࣈ Ϟʔυ ϏοτόΠτ Ϟʔυ ࣈ
Ϟʔυ ʙ ʙ ʙ
symbolVersion + errorCorrectedPayload σίʔυͰ͖Δ
ͱ͍͏͜ͱ…ʁ
iOS 11 Ҏ߱ͷੈքͰ 1. AVCaptureSession ͰಡΈऔΔ ߴਫ਼Ͱ͍
iOS 11 Ҏ߱ͷੈքͰ AVMetadata Machine ReadableCode Object 2. CIQRCodeDescriptor #errorCorrectedPayload
ΛऔΓग़͢ 1. AVCaptureSession ͰಡΈऔΔ
iOS 11 Ҏ߱ͷੈքͰ AVMetadata Machine ReadableCode Object 2. CIQRCodeDescriptor #errorCorrectedPayload
ΛऔΓग़͢ σίʔυ͢Δ 1. AVFoundation ͰಡΈऔΔ ͕Μͬͯ 3.
ղܾ ͬͨʔʂʂࠓͦ͜
σίʔυ͢Δ ͕Μͬͯ 3. ͕Μͬͯ
͕ΜΔ = ࣗલͰσίʔυॲཧΛॻ͘
ࣗલσίʔυͷํ • શϞʔυʹରԠ͠Α͏ͱࢥͬͨΒʢͨͿΜʣ݁ߏେม… • ͱ͍͏͔σϯιʔެࣜΞϓϦରԠͯ͠ͳ͍ • ࠷ݶಡΈऔΓ͍ͨQRίʔυͷσίʔυॲཧͰଥڠ • ಠࣗΤϯίʔυ͞ΕͨQRίʔυσίʔυͰ͖Δ͠ɺ ෯͕͕Δʢͱ͔ॻ͍ͯΔ͏ͪʹσϯιʔ͕Ԍ্͠·ͨ͠ʣ
=> https://srad.jp/submission/78134/
σίʔυͷҰྫ https://github.com/ monoqlo/QRCodeReader
࣌ؒ͋Ε গ͚ͩ͠ DEMO
·ͱΊ
0. iOS 10 ͷαϙʔτΛΔʢҰ൪େࣄʣ
·ͱΊʢiOS 11 Ҏ߱ͷੈքʣ 1. AVCaptureSession ͰಡΈऔΔ AVMetadata Machine ReadableCode Object
2. CIQRCodeDescriptor #errorCorrectedPayload ΛऔΓग़͢ ͕Μͬͯσίʔυ͢Δ 3.
Appendix • Speaker Info @monoqlo • This Slide URL https://speakerdeck.com/monoqlo/iosdc-2018