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コードの仕様ってn種類あんねん
Search
Ryomm
September 20, 2025
Programming
0
4
QRコードの仕様ってn種類あんねん
2025.09.20 iOSDC Japan 2025
Ryomm
September 20, 2025
Tweet
Share
More Decks by Ryomm
See All by Ryomm
Bring your app’s core features to users with App Intents とか App Intents 関連の要約
ryomm
1
670
クソアプリハッカソン
ryomm
0
150
万年筆のスゝメ
ryomm
0
140
Other Decks in Programming
See All in Programming
Windows on Ryzen and I
seosoft
0
290
Cyrius ーLinux非依存にコンテナをネイティブ実行する専用OSー
n4mlz
0
150
Unity6.3 AudioUpdate
cova8bitdots
0
130
Ruby x Terminal
a_matsuda
7
600
Go 1.26でのsliceのメモリアロケーション最適化 / Go 1.26 リリースパーティ #go126party
mazrean
1
400
「抽象に依存せよ」が分からなかった新卒1年目の私が Goのインターフェースと和解するまで
kurogenki
0
120
Vuetify 3 → 4 何が変わった?差分と移行ポイント10分まとめ
koukimiura
0
140
CDIの誤解しがちな仕様とその対処TIPS
futokiyo
0
220
Claude Code Skill入門
mayahoney
0
390
go directiveを最新にしすぎないで欲しい話──あるいは、Go 1.26からgo mod initで作られるgo directiveの値が変わる話 / Go 1.26 リリースパーティ
arthur1
2
550
AI 開発合宿を通して得た学び
niftycorp
PRO
0
120
AWS Infrastructure as Code の新機能 2025 総まとめ 〜SA 4人による怒涛のデモ祭り〜
konokenj
10
3.4k
Featured
See All Featured
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
240
The SEO Collaboration Effect
kristinabergwall1
0
390
Art, The Web, and Tiny UX
lynnandtonic
304
21k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
9.9k
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Marketing to machines
jonoalderson
1
5k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.6k
Mind Mapping
helmedeiros
PRO
1
120
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
140
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
310
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Groundhog Day: Seeking Process in Gaming for Health
codingconduct
0
120
Transcript
QRίʔυͷ༷ͬͯnछྨ͋ΜͶΜ 2025.09.20 iOSDC Japan 2025 Ryomm / Ryoko Matsusaka
Ryomm / Ryoko Matsusaka ͦͷଞ: Ryomm : @__ryomm iOSΞϓϦΤϯδχϟ
QRίʔυ(ג)σϯιʔΣʔϒͷొඪͰ͢ QRίʔυΛੜ͍ͨ͠
func qrCode(data: Data?) -" UIImage? { let transform = CGAffineTransform(scaleX:
10, y: 10) guard let data, let filter = CIFilter(name: “CIQRCodeGenerator”, parameters: ["inputMessage": data, "inputCorrectionLevel": "Q"]), let ciImage = filter.outputImage?.transformed(by: transform) let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) } https://developer.apple.com/documentation/coreimage/cifilter https://developer.apple.com/documentation/coreimage/ciqrcodegenerator
func qrCode(data: Data?) -" UIImage? { let transform = CGAffineTransform(scaleX:
10, y: 10) guard let data, let filter = CIFilter(name: “CIQRCodeGenerator”, parameters: ["inputMessage": data, "inputCorrectionLevel": "Q"]), let ciImage = filter.outputImage?.transformed(by: transform) let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) } https://developer.apple.com/documentation/coreimage/cifilter https://developer.apple.com/documentation/coreimage/ciqrcodegenerator QRίʔυʹؚΊΔσʔλ ޡΓగਖ਼Ϩϕϧ
func qrCode(data: Data?) -" UIImage? { let transform = CGAffineTransform(scaleX:
10, y: 10) guard let data, let filter = CIFilter(name: “CIQRCodeGenerator”, parameters: ["inputMessage": data, "inputCorrectionLevel": "Q"]), let ciImage = filter.outputImage?.transformed(by: transform) let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) } https://developer.apple.com/documentation/coreimage/cifilter https://developer.apple.com/documentation/coreimage/ciqrcodegenerator
QRίʔυͷ༷ͬͯnछྨ͋ΜͶΜ
࠷ۙͷMaaSք۾
࠷ۙͷMaaSք۾
όʔδϣϯ
όʔδϣϯ όʔδϣϯ1 2121 M14byte όʔδϣϯ10 5757 M213byte όʔδϣϯ40 177177 M2,331byte
όʔδϣϯ5 3737 M84byte ࢀߟ: https://www.qrcode.com/about/version.html
func qrCode(data: Data?) -" UIImage? { let transform = CGAffineTransform(scaleX:
10, y: 10) guard let data, let filter = CIFilter(name: “CIQRCodeGenerator”, parameters: ["inputMessage": data, "inputCorrectionLevel": "Q"]), let ciImage = filter.outputImage?.transformed(by: transform) let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
func qrCode(data: Data?) -" UIImage? { let transform = CGAffineTransform(scaleX:
10, y: 10) guard let data, let filter = CIFilter(name: “CIQRCodeGenerator”, parameters: ["inputMessage": data, "inputCorrectionLevel": "Q"]), let ciImage = filter.outputImage?.transformed(by: transform) let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) } όʔδϣϯࢦఆ Ͱ͖ͳ͘Ͷ…ʁ ʁ ͳΜ͔উखʹ ৭ΜͳόʔδϣϯͰ ੜ͞ΕͯΔ͠…
ͳΜ͔উखʹ ৭ΜͳόʔδϣϯͰ ੜ͞ΕͯΔ͠…
ͳΜ͔উखʹ ৭ΜͳόʔδϣϯͰ ੜ͞ΕͯΔ͠… ʂ
Data 1234123412 Data 123…………..234 ʂ
func qrCodeVersion5(of binary: String) -" UIImage? { guard let bint
= BInt(binary, radix: 16) else { return nil } let bytes: [UInt8] = bint.getBytes() let maxBinaryLength = 84 let shortage = maxBinaryLength - bytes.count if shortage > 0 { bytes.insert(contentsOf: Array(repeating: 0, count: shortage), at: 0) } let data: Data = Data(bytes) guard let QRFilter = CIFilter(name: ”CIQRCodeGenerator”, parameters: ["inputMessage": data]), let ciImage = QRFilter.outputImage?.transformed(by: transform), let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
func qrCodeVersion5(of binary: String) -" UIImage? { guard let bint
= BInt(binary, radix: 16) else { return nil } let bytes: [UInt8] = bint.getBytes() let maxBinaryLength = 84 let shortage = maxBinaryLength - bytes.count if shortage > 0 { bytes.insert(contentsOf: Array(repeating: 0, count: shortage), at: 0) } let data: Data = Data(bytes) guard let QRFilter = CIFilter(name: ”CIQRCodeGenerator”, parameters: ["inputMessage": data]), let ciImage = QRFilter.outputImage?.transformed(by: transform), let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
func qrCodeVersion5(of binary: String) -" UIImage? { guard let bint
= BInt(binary, radix: 16) else { return nil } let bytes: [UInt8] = bint.getBytes() let maxBinaryLength = 84 let shortage = maxBinaryLength - bytes.count if shortage > 0 { bytes.insert(contentsOf: Array(repeating: 0, count: shortage), at: 0) } let data: Data = Data(bytes) guard let QRFilter = CIFilter(name: ”CIQRCodeGenerator”, parameters: ["inputMessage": data]), let ciImage = QRFilter.outputImage?.transformed(by: transform), let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) } 0 0 0 0 0ຒΊͰ͞ௐ
func qrCodeVersion5(of binary: String) -" UIImage? { guard let bint
= BInt(binary, radix: 16) else { return nil } let bytes: [UInt8] = bint.getBytes() let maxBinaryLength = 84 let shortage = maxBinaryLength - bytes.count if shortage > 0 { bytes.insert(contentsOf: Array(repeating: 0, count: shortage), at: 0) } let data: Data = Data(bytes) guard let QRFilter = CIFilter(name: ”CIQRCodeGenerator”, parameters: ["inputMessage": data]), let ciImage = QRFilter.outputImage?.transformed(by: transform), let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } return UIImage(cgImage: cgImage) }
ଞʹԿ͔ΕΔ ؾ͕͖ͯͨ͠ ʢ͔͜͜Βझຯʣ
ٖࣅϑϨʔϜ23
ޡΓగਖ਼Ϩϕϧ ϨϕϧL Low 7% ϨϕϧM Medium 15% ϨϕϧQ Quality) 25%
ϨϕϧH High 30% ࢀߟ: https://www.qrcode.com/about/error_correction.html
ޡΓగਖ਼ ϔομʔ ύσΟϯά 1ίʔυϫʔυ8bit σʔλίʔυϫʔυ ޡΓగਖ਼ίʔυϫʔυ શίʔυϫʔυ
ޡΓగਖ਼ σʔλίʔυϫʔυ: 10 / గਖ਼ର: 5 ޡΓగਖ਼ίʔυϫʔυ: 52 10
గਖ਼͢Δίʔυϫʔυͷ2ഒ గਖ਼: 5 / 20 25% (ϨϕϧQ σʔλίʔυϫʔυ ޡΓగਖ਼ίʔυϫʔυ શίʔυϫʔυ
ޡΓగਖ਼ గਖ਼: గਖ਼Մೳ / શίʔυϫʔυ RSϒϩοΫ గਖ਼: 2 / 8
25% గਖ਼: 4 / 16 25%
ޡΓగਖ਼Ϩϕϧ ϨϕϧM ϨϕϧQ ϨϕϧL ϨϕϧH ࣮ࡍ ͜ͷ͘Β͍͍͚Δ
func frameQRCode(data: Data?, image: UIImage) -" UIImage? { let transform
= CGAffineTransform(scaleX: 10, y: 10) guard let data, let filter = CIFilter(name: “CIQRCodeGenerator”, parameters: ["inputMessage": data, "inputCorrectionLevel": "H"]), let ciImage = filter.outputImage?.transformed(by: transform) let cgImage = CIContext().createCGImage(ciImage, from: ciImage.extent) else { return nil } let qrImage = UIImage(cgImage: cgImage) return UIGraphicsImageRenderer(size: qrImage.size).image { context in let qrWidth = context.format.bounds.width let qrHeight = context.format.bounds.height let imageWidth = qrWidth / (dimension + 2) * imageDimension let imageHeight = qrHeight / (dimension + 2) * imageDimension ࢀߟ: https://dev.classmethod.jp/articles/swift-generate-qr-code/
let qrImage = UIImage(cgImage: cgImage) return UIGraphicsImageRenderer(size: qrImage.size).image { context
in let qrWidth = context.format.bounds.width let qrHeight = context.format.bounds.height let imageWidth = qrWidth / (dimension + 2) * imageDimension let imageHeight = qrHeight / (dimension + 2) * imageDimension qrImage.draw(in: CGRect(origin: .zero, size: context.format.bounds.size)) let imageRect = CGRect(x: (qrWidth - imageWidth) / 2, y: (qrHeight - imageHeight) / 2, width: imageWidth, height: imageHeight) image.draw(in: imageRect) } } ࢀߟ: https://dev.classmethod.jp/articles/swift-generate-qr-code/
let qrImage = UIImage(cgImage: cgImage) return UIGraphicsImageRenderer(size: qrImage.size).image { context
in let qrWidth = context.format.bounds.width let qrHeight = context.format.bounds.height let imageWidth = qrWidth / (dimension + 2) * imageDimension let imageHeight = qrHeight / (dimension + 2) * imageDimension qrImage.draw(in: CGRect(origin: .zero, size: context.format.bounds.size)) let imageRect = CGRect(x: (qrWidth - imageWidth) / 2, y: (qrHeight - imageHeight) / 2, width: imageWidth, height: imageHeight) image.draw(in: imageRect) } } ࢀߟ: https://dev.classmethod.jp/articles/swift-generate-qr-code/
͜ΕͲ͜·Ͱ ΕΔΜͩʙʂʁ
0 0 1 1 ׂ23ίʔυ ϔομʔ ύσΟϯά σʔλ Ϟʔυࢦࣔࢠ ;ͭ͏ͷQRίʔυ
3 ׂQRίʔυ ׂQRίʔυ ͜ΕԿ൪ʁ શ෦ͰԿݸʁ ϖʔδ൪߸ ࠷େϖʔδ൪߸ ࿈݁༻IDతͳѻ͍Λ͞Ε͕ͪ ࢀߟ: https://programresource.net/2013/05/04/2193.html ύϦςΟ(্Ґ) ύϦςΟ(ԼҐ)
͋ʙͳΜ͔͜Ε… Ͱ͖ͳ͘ͳͦ͞͏…
͋ʙͳΜ͔͜Ε… Ͱ͖ͳ͘ͳͦ͞͏… CIQRCodeGeneratorͰ Ͳ͏ͬͯϔομʔใ ͍͡ΔΜͩ…ʁ
Ͱ͖·ͤΜʂ
ࢀߟ: https://github.com/zxing-cpp/zxing-cpp
Ϟʔυࢦࣔࢠ ࣈ ӳه߸ 8bit ࣈ
Ϟʔυࢦࣔࢠ ࣈ ӳه߸ 8bit ࣈ “nyan".data(using: .utf8) 1101110 1111001 1100001
1101110
Ϟʔυࢦࣔࢠ ࣈ ӳه߸ 8bit ࣈ “nyan".data(using: .utf8) 1101110 1111001 1100001
1101110 0001 0010 0100 1000 ϔομʔ
όʔδϣϯ 1101110 1111001 1100001 1101110 4byte ޡΓగਖ਼Ϩϕϧ: Q ΄ͳɺόʔδϣϯ1͔ʙ 2121ͷۭͷϚτϦοΫε
ϔομʔ σʔλίʔυϫʔυ
σʔλͷେ͖͞ ϔομʔ 1101110 1111001 1100001 1101110 4byte σʔλ4byteೖͬͯΔͷͶʂ σʔλίʔυϫʔυ 8bit
ऴύλʔϯύσΟϯάύλʔϯ ޡΓగਖ਼Ϩϕϧ: Q όʔδϣϯ: 1ɹ 13byteೖΓ·͢ͳʙ ϔομʔใؚΜͩ༰ྔ
ϔομʔ 1101110 1111001 1100001 1101110 σʔλίʔυϫʔυ
ऴύλʔϯύσΟϯάύλʔϯ
ϔομʔ 1101110 1111001 1100001 1101110 σʔλίʔυϫʔυ
ऴύλʔϯύσΟϯάύλʔϯ ϔομʔ σʔλίʔυϫʔυ 13byte 12bit 4byte σʔλ෦֨ೲՄೳ༰ྔ ऴύλʔϯ 0000 ͪΐ͏Ͳ8bitʹͳΔΑ͏0ຒΊ
ύσΟϯάύλʔϯ 0xEC 0x11 0xEC 0x11 …
ޡΓగਖ਼ ϔομʔ σʔλίʔυϫʔυ ޡΓగਖ਼ίʔυϫʔυ
ϚεΫύλʔϯ 000 (x+y)%2='0 001 y%2='0 010 x%3='0 011 (x+y)%3='0 100
((y/2)+(x/3)%2='0 101 (x*y)%6='0 110 (x*y)%6<3 111 (y+x+((y*x)%3))%2='0
ϚεΫύλʔϯ 000 (x+y)%2='0 001 y%2='0 010 x%3='0 011 (x+y)%3='0 100
((y/2)+(x/3)%2='0 101 (x*y)%6='0 110 (x*y)%6<3 111 (y+x+((y*x)%3))%2='0
ϑΝΠϯμύλʔϯηύϨʔλ ϑΝΠϯμύλʔϯ ҐஔճసΛݕग़ ηύϨʔλ
ΞϥΠϝϯτύλʔϯ ΞϥΠϝϯτύλʔϯ ΈʹΑΔҐஔͣΕΛิਖ਼
λΠϛϯάύλʔϯ λΠϛϯάύλʔϯ Ϟδϡʔϧ࠲ඪΛݕग़
ϑΥʔϚοτใ ޡΓగਖ਼Ϩϕϧ ϚεΫύλʔϯ 2bit 3bit
ޡΓగਖ਼ූ߸ʢBCHූ߸ʣ bchCode(formatInfo, poly: 0x537)
ϑΥʔϚοτใ ޡΓగਖ਼Ϩϕϧ ϚεΫύλʔϯ 2bit 3bit
10bit ޡΓగਖ਼ූ߸ formatBits ^ 0x5412
ϑΥʔϚοτใ
σʔλใ
ϚεΫύλʔϯ 000 (x+y)%2='0 001 y%2='0 010 x%3='0 011 (x+y)%3='0 100
((y/2)+(x/3)%2='0 101 (x*y)%6='0 110 (x*y)%6<3 111 (y+x+((y*x)%3))%2='0
ϚεΫύλʔϯ 000 (x+y)%2='0 001 y%2='0 010 x%3='0 011 (x+y)%3='0 100
((y/2)+(x/3)%2='0 101 (x*y)%6='0 110 (x*y)%6<3 111 (y+x+((y*x)%3))%2='0
ϚεΫύλʔϯ ಉ͡৭ͷϞδϡʔϧ͕࿈ଓ͢Δ͔5ݸҎ্) 22ͷಉ৭ϒϩοΫʹͳ͍ͬͯΔ͔ ϑΝΠϯμʔύλʔϯʹࣅ͍ͯΔ ໌҉Ϟδϡʔϧͷൺ
͜ΕͲ͏ͬͯ ը૾ʹ͢Δ…ʁ