「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」 / iOSDC 2018

13d64bff196e33cc6b352f226137d16e?s=47 monoqlo
September 01, 2018

「QRコード読み取り?楽勝ですよ😙」=>「AVFoundationを信じたおれがバカだった😇」 / iOSDC 2018

iOSDC 2018 2018/09/01 14:40〜 Track B レギュラートーク(15分)

13d64bff196e33cc6b352f226137d16e?s=128

monoqlo

September 01, 2018
Tweet

Transcript

  1. @monoqlo QRίʔυಡΈऔΓʁ ָউͰ͢Α AVFoundationΛ৴ͨ͡ ͓Ε͕όΧͩͬͨ

  2. None
  3. ḪΔ͜ͱ ಥવͰ͕͢

  4. ໿ 1೥൒

  5. 2017 ೥ 3 ݄ ๭೔

  6. ָউͰ͢Α✌✌ QRίʔυಡΈऔΔ ΞϓϦͭ͘ΕΔʁ

  7. ͜ͷ࣌ߟ͍͑ͯͨ͜ͱ

  8. AVFoundation Ͱ༨༟Ͱ͠ΐ • AVCaptureSession • AVCaptureMetadataOutput • AVMetadataMachineReadableCodeObject • etc…

  9. QRίʔυ ౉͞Εͨ

  10. https://www.55truck.com/shaken.html

  11. https://www.55truck.com/shaken.html

  12. None
  13. "8/-/1/-/- /- /999999/02” "2/- //160114/1001/BKG-NKR85” "AN/0168/- /- /0381/13/09” "2/඼઒ɹɹ̔̌̌ͤ̒̐̎” “̒/1/NKR85-7011300/4JJ1/1"

  14. http://mangalifewin.takeshobo.co.jp/rensai/popute3/

  15. "8/-/1/-/- /- /999999/02” "2/- //160114/1001/BKG-NKR85” "AN/0168/- /- /0381/13/09” "2/඼઒ɹɹ̔̌̌ͤ̒̐̎” “̒/1/NKR85-7011300/4JJ1/1"

  16. "2/- //160114/1001/BKG-NKR85AN/0168/- /- /0381/13/098/-/1/-/- /- /999999/02” "2/඼઒ɹɹ̔̌̌ͤ̒̐̎̒/1/NKR85-7011300/4JJ1/1”

  17. φχϞϊ ͜Ε͸…

  18. None
  19. http://www.qrcode.com

  20. None
  21. ΋ͬͱ QRίʔυ Λ஌Ζ͏

  22. ৘ใٕज़ʵࣗಈೝࣝٴͼσʔλऔಘٕज़ʵ ̧̦ίʔυόʔίʔυγϯϘϧମܥ࢓༷ JIS ن֨ X0510

  23. http://www.jisc.go.jp/

  24. શ 115 ϖʔδ…

  25. QRίʔυͷ࢓૊Έ ௒μΠδΣετ൛

  26. ࠇനϞδϡʔϧͷೝࣝ START ܕࣜ৘ใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ

  27. ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ

  28. “Ϟʔυ” ղऍ ෮߸͢ΔͨΊʹॏཁͳͷ͕

  29. “Ϟʔυ” ͱ͸

  30. • ECI • ߏ଄త࿈઀ • FNC1 • (ऴ୺ύλʔϯ) • ਺ࣈ

    • ӳ਺ࣈ • 8ϏοτόΠτ • ׽ࣈ Ϟʔυ = σʔλΛ֨ೲ͢Δܗࣜ • ѹॖޮ཰޲্Λ໨తͱ͠ɺଟ਺ͷϞʔυ͕ఆٛ͞Ε͍ͯΔ • QRίʔυੜ੒࣌ɺσʔλʹ߹Θͤͯ࠷దͳ΋ͷΛબ୒͢Δ • ϔομʔͱͯ͠จࣈ਺ࢦࣔࢠͱͱ΋ʹσʔλʹ෇Ճ͢Δ • ૊Έ߹Θͤͯ࢖༻Մʢex. ӳ਺ࣈ + ׽ࣈʣ ߏ଄త࿈઀
  31. • ਺ࣈ • ӳ਺ࣈ • 8ϏοτόΠτ • ׽ࣈ • ECI

    • ߏ଄త࿈઀ • FNC1 • (ऴ୺ύλʔϯ) Ϟʔυ = σʔλΛ֨ೲ͢Δܗࣜ • ѹॖޮ཰޲্Λ໨తͱ͠ɺଟ਺ͷϞʔυ͕ఆٛ͞Ε͍ͯΔ • QRίʔυੜ੒࣌ɺσʔλʹ߹Θͤͯ࠷దͳ΋ͷΛબ୒͢Δ • ϔομʔͱͯ͠จࣈ਺ࢦࣔࢠͱͱ΋ʹσʔλʹ෇Ճ͢Δ • ૊Έ߹Θͤͯ࢖༻Մʢex. ӳ਺ࣈ + ׽ࣈʣ ߏ଄త࿈઀
  32. ߏ଄త࿈઀ Ϟʔυ

  33. ϔομʔ࢓༷ 1. Ϟʔυࢦࣔࢠʢ0011ʣɿ4bit 2. γϯϘϧྻࢦࣔࢠɿ8bit 1. γϯϘϧҐஔɿ4bit 2. ࿈݁͞ΕΔγϯϘϧͷ߹ܭ਺ɿ4bit 3.

    ύϦςΟɿ8bit ෼ׂલͷσʔλΛόΠτ͝ͱʹXORԋࢉͨ͠஋
  34. None
  35. ϓϩύςΟ var corners: [CGPoint] A Swift array of corner points.

    var stringValue: String? Returns the error corrected data decoded into a human- readable string.
  36. ͦΜͳ΋ͷͳ͍ AVMetadataMachineReadableCodeObject ʹ

  37. ࠇനϞδϡʔϧͷೝࣝ START ܕࣜ৘ใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ

  38. ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ AVMetadataMachine ReadableCodeObject ͷ

    stringValue ͸ ෳ߹ޙͷίϨ
  39. ϥΠϒϥϦΛ୳͢ ߏ଄త࿈઀Λ͏·͘ѻ͑Δ

  40. None Swift ੡ͷϥΠϒϥϦ

  41. None
  42. ZXingObjC ٹੈओ TheLevelUp/ZXingObjC: An Objective-C Port of ZXing

  43. γϯϘϧҐஔ/߹ܭ਺ͱύϦςΟ͕औΕΔ @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
  44. γϯϘϧҐஔ/߹ܭ਺ͱύϦςΟ͕औΕΔ @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 }
  45. γϯϘϧҐஔ/߹ܭ਺ͱύϦςΟ͕औΕΔ @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)! … }
  46. γϯϘϧҐஔ/߹ܭ਺ͱύϦςΟ͕औΕΔ @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 }
  47. ղܾ ΍ͬͨʔʂʂ

  48. ຊ౰ʹʁ

  49. ZXingObjC ͷऑ఺ • ಡΈऔΓਫ਼౓͕͋·Γߴ͘ͳ͍ • AVFoundation ΍σϯιʔެࣜΞϓϦʹൺ΂Δͱ݁ߏ ͕͔͔࣌ؒΔ͜ͱ͕͋Δ • ։ൃ͕࣮࣭ࢭ·͍ͬͯΔ

    • Swift ʹஔ͖׵͍͑ͨͱ͔ॻ͔ΕͯΔ͚Ͳ͍ͭʹͳΔ ͔·ͬͨ͘Θ͔Βͳ͍
  50. ઈ๬ ະདྷ͕ͳ͍

  51. ઈ๬ ະདྷ͕ͳ͍ ʁ

  52. ઈ๬ ະདྷ͕ͳ͍ ʁ 2017 ೥ ൒͹ ·Ͱͷ͓࿩

  53. ࣌͸ྲྀΕ… 2018 ೥ 9 ݄ 1 ೔

  54. iOS ͷόʔδϣϯγΣΞભҠ      ೥݄ ݄ ݄

    ݄ ݄ ೥݄ ݄ ݄ ݄ iOS 11 iOS 10 iOS 9 or Earlier ※ 2018೥9݄͸༧ଌ
  55. iOS 10 ͷαϙʔτ ͦΖͦΖ੾Ε·͢ΑͶʁ ࠓ݄͸ iOS 12 ͕ϦϦʔε͞Ε·͢

  56. CIQRCodeDescriptor ਅͷٹੈओ in AVMetadataMachineReadableCodeObject

  57. ϓϩύςΟ 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.
  58. CIQRCodeDescriptor ͱ͸

  59. CIQRCodeDescriptor ͱ͸ • iOS 11 Ͱ௥Ճ͞ΕͨڧྗͳΫϥε • ந৅Ϋϥε CIBarcodeDescriptor ͷαϒΫϥε

    • QRίʔυΛੜ੒͢ΔͨΊʹඞཁे෼ͳσʔλΛ࣋ͭ • CIFilter Ͱ QRίʔυը૾Λੜ੒͢Δ͜ͱ΋Ͱ͖Δ
  60. 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) }
  61. େࣄͳͷ͸͜ͷ 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.
  62. ࠇനϞδϡʔϧͷೝࣝ START ܕࣜ৘ใͷ෮߸ ܕ൪ͷܾఆ ϚεΫॲཧͷղআ σʔλ & ޡΓగਖ਼ίʔυޠͷ෮ݩ

  63. ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ AVMetadataMachine ReadableCodeObject ͷ

    stringValue ͸ ෳ߹ޙͷίϨ
  64. ޡΓగਖ਼ ޡΓݕग़ σʔλΛ෮߸ σʔλೖख END ޡΓφγ ޡΓΞϦ errorCorrectedPayload ͸ ίίͷσʔλʂ

  65. େࣄͳͷ͸͜ͷ 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.
  66. େࣄͳͷ͸͜ͷ 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.
  67. จࣈ਺ࢦࣔࢠͷϏοτ਺ ܕ൪ TZNCPM7FSTJPO ਺ࣈ Ϟʔυ ӳ਺ࣈ Ϟʔυ ϏοτόΠτ Ϟʔυ ׽ࣈ

    Ϟʔυ ʙ     ʙ     ʙ    
  68. symbolVersion + errorCorrectedPayload σίʔυͰ͖Δ

  69. ͱ͍͏͜ͱ͸…ʁ

  70. iOS 11 Ҏ߱ͷੈքͰ͸ 1. AVCaptureSession ͰಡΈऔΔ ߴਫ਼౓Ͱ଎͍

  71. iOS 11 Ҏ߱ͷੈքͰ͸ AVMetadata Machine ReadableCode Object 2. CIQRCodeDescriptor #errorCorrectedPayload

    ΛऔΓग़͢ 1. AVCaptureSession ͰಡΈऔΔ
  72. iOS 11 Ҏ߱ͷੈքͰ͸ AVMetadata Machine ReadableCode Object 2. CIQRCodeDescriptor #errorCorrectedPayload

    ΛऔΓग़͢ σίʔυ͢Δ 1. AVFoundation ͰಡΈऔΔ ͕Μ͹ͬͯ 3.
  73. ղܾ ΍ͬͨʔʂʂࠓ౓ͦ͜

  74. σίʔυ͢Δ ͕Μ͹ͬͯ 3. ͕Μ͹ͬͯ

  75. ͕Μ͹Δ = ࣗલͰσίʔυॲཧΛॻ͘

  76. ࣗલσίʔυͷํ਑ • શϞʔυʹରԠ͠Α͏ͱࢥͬͨΒʢͨͿΜʣ݁ߏେม… • ͱ͍͏͔σϯιʔެࣜΞϓϦ΋ରԠͯ͠ͳ͍ • ࠷௿ݶಡΈऔΓ͍ͨQRίʔυͷσίʔυॲཧͰଥڠ • ಠࣗΤϯίʔυ͞ΕͨQRίʔυ΋σίʔυͰ͖Δ͠ɺ ෯͕޿͕Δʢͱ͔ॻ͍ͯΔ͏ͪʹσϯιʔ͕Ԍ্͠·ͨ͠ʣ

    => https://srad.jp/submission/78134/
  77. σίʔυͷҰྫ https://github.com/ monoqlo/QRCodeReader

  78. ࣌ؒ͋Ε͹ গ͚ͩ͠ DEMO

  79. ·ͱΊ

  80. 0. iOS 10 ͷαϙʔτΛ੾ΔʢҰ൪େࣄʣ

  81. ·ͱΊʢiOS 11 Ҏ߱ͷੈքʣ 1. AVCaptureSession ͰಡΈऔΔ AVMetadata Machine ReadableCode Object

    2. CIQRCodeDescriptor #errorCorrectedPayload ΛऔΓग़͢ ͕Μ͹ͬͯσίʔυ͢Δ 3.
  82. Appendix • Speaker Info @monoqlo • This Slide URL https://speakerdeck.com/monoqlo/iosdc-2018