Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」...
Search
monoqlo
September 01, 2018
Programming
31k
11
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」 / iOSDC 2018
iOSDC 2018 2018/09/01 14:40〜 Track B レギュラートーク(15分)
monoqlo
September 01, 2018
More Decks by monoqlo
See All by monoqlo
入門 SwiftUI Alignment Guide / iOSDC2022
monoqlo
11
6.5k
Hey Siri!マルチプラットフォームでのSiriショートカットの地雷を教えて / iOSDC2021
monoqlo
0
910
あなたのアプリ、✨リブランディング✨できますか? / iosdc2020
monoqlo
9
1.7k
実践 CallKit/PushKit ときどき🐛退治 / iOSDC 2019
monoqlo
4
4.2k
WWDC2016のススメ
monoqlo
0
140
Other Decks in Programming
See All in Programming
AHC070解法紹介
eijirou
0
120
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
6
2.2k
マイコン向けの軽量Ruby「PicoRuby」で各種デバイスを制御するネイティブアプリの実現手法
bash0c7
0
390
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
150
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
210
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
0
280
Family mrubyの進捗
kishima
1
120
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
3
550
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
0
160
【高い買い物LT会】初任給で話題の国産フィジカルAIを買った話
akagami
PRO
0
160
Omarchy Tokyo やると聞いて UMPC 買ってセットアップしてきた
mtsmfm
0
140
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
4.5k
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
940
Ethics towards AI in product and experience design
skipperchong
2
370
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
670
Automating Front-end Workflow
addyosmani
1369
210k
Heart Work Chapter 1 - Part 1
lfama
PRO
10
36k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
How to Think Like a Performance Engineer
csswizardry
28
2.8k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
360
30k
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
500
Navigating Team Friction
lara
192
16k
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