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
6
0
Share
QRコードの仕様ってn種類あんねん
2025.09.20 iOSDC Japan 2025
Ryomm
September 20, 2025
More Decks by Ryomm
See All by Ryomm
Bring your app’s core features to users with App Intents とか App Intents 関連の要約
ryomm
1
680
クソアプリハッカソン
ryomm
0
150
万年筆のスゝメ
ryomm
0
150
Other Decks in Programming
See All in Programming
The Monolith Strikes Back: Why AI Agents ❤️ Rails Monoliths
serradura
0
350
t *testing.T は どこからやってくるの?
otakakot
1
730
Claude CodeでETLジョブ実行テストを自動化してみた
yoshikikasama
0
880
〜バイブコーディングを超えて〜 チームで実験し続けたAI駆動開発
tigertora7571
0
170
検索設計から 推論設計への重心移動と Recall-First Retrieval
po3rin
4
1.2k
tRPCの概要と少しだけパフォーマンス
misoton665
2
240
HTML-Aware ERB: The Path to Reactive Rendering @ RubyKaigi 2026, Hakodate, Japan
marcoroth
0
290
AIを導入する前にやるべきこと
negima
2
260
[RubyKaigi 2026] Require Hooks
palkan
1
240
The Less-Told Story of Socket Timeouts
coe401_
3
650
GitHubCopilotCLIをはじめよう.pdf
htkym
0
280
Server-Side Kotlin LT大会 vol.18 [Kotlin-lspの最新情報と Neovimのlsp設定例]
yasunori0418
1
190
Featured
See All Featured
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
320
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
280
Optimizing for Happiness
mojombo
378
71k
Into the Great Unknown - MozCon
thekraken
41
2.4k
Evolving SEO for Evolving Search Engines
ryanjones
0
180
Neural Spatial Audio Processing for Sound Field Analysis and Control
skoyamalab
0
270
Designing for Timeless Needs
cassininazir
0
210
AI: The stuff that nobody shows you
jnunemaker
PRO
6
600
Testing 201, or: Great Expectations
jmmastey
46
8.1k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
520
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
230
Darren the Foodie - Storyboard
khoart
PRO
3
3.3k
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ͷಉ৭ϒϩοΫʹͳ͍ͬͯΔ͔ ϑΝΠϯμʔύλʔϯʹࣅ͍ͯΔ ໌҉Ϟδϡʔϧͷൺ
͜ΕͲ͏ͬͯ ը૾ʹ͢Δ…ʁ