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
27k
「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
11
5.4k
Hey Siri!マルチプラットフォームでのSiriショートカットの地雷を教えて / iOSDC2021
monoqlo
0
710
あなたのアプリ、✨リブランディング✨できますか? / iosdc2020
monoqlo
9
1.5k
実践 CallKit/PushKit ときどき🐛退治 / iOSDC 2019
monoqlo
4
3.7k
WWDC2016のススメ
monoqlo
0
110
Other Decks in Programming
See All in Programming
TypeScript だけを書いて Tauri でデスクトップアプリを作ろう / Tauri with only TypeScript
tris5572
2
570
セキュリティマネジャー廃止とクラウドネイティブ型サンドボックス活用
kazumura
1
150
Interface vs Types ~型推論が過多推論~
hirokiomote
1
240
型安全RESTで爆速プロトタイピング – Hono RPC実践
tacke_jp
0
110
テスト分析入門/Test Analysis Tutorial
goyoki
13
2.8k
Agent Rules as Domain Parser
yodakeisuke
1
440
Perplexity Slack Botを作ってAI活用を進めた話 / AI Engineering Summit プレイベント
n3xem
0
340
Passkeys for Java Developers
ynojima
2
760
Perlで痩せる
yuukis
1
670
型安全なDrag and Dropの設計を考える
yudppp
5
700
事業戦略を理解してソフトウェアを設計する
masuda220
PRO
18
5.4k
ktr0731/go-mcpでMCPサーバー作ってみた
takak2166
0
100
Featured
See All Featured
Bash Introduction
62gerente
614
210k
Designing for Performance
lara
608
69k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
The Language of Interfaces
destraynor
158
25k
Gamification - CAS2011
davidbonilla
81
5.3k
Side Projects
sachag
454
42k
Being A Developer After 40
akosma
90
590k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Git: the NoSQL Database
bkeepers
PRO
430
65k
Optimizing for Happiness
mojombo
378
70k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
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