Upgrade to Pro — share decks privately, control downloads, hide ads and more …

QRコードの仕様ってn種類あんねん

Avatar for Ryomm Ryomm
September 20, 2025

 QRコードの仕様ってn種類あんねん

2025.09.20 iOSDC Japan 2025

Avatar for Ryomm

Ryomm

September 20, 2025
Tweet

More Decks by Ryomm

Other Decks in Programming

Transcript

  1. 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
  2. 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ίʔυʹؚΊΔσʔλ ޡΓగਖ਼Ϩϕϧ
  3. 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
  4. όʔδϣϯ όʔδϣϯ1 2121 M14byte όʔδϣϯ10 5757 M213byte όʔδϣϯ40 177177 M2,331byte

    όʔδϣϯ5 3737 M84byte ࢀߟ: https://www.qrcode.com/about/version.html
  5. 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) }
  6. 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) } όʔδϣϯࢦఆ Ͱ͖ͳ͘Ͷ…ʁ ʁ ͳΜ͔উखʹ ৭ΜͳόʔδϣϯͰ ੜ੒͞ΕͯΔ͠…
  7. 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) }
  8. 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) }
  9. 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ຒΊͰ௕͞ௐ੔
  10. 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) }
  11. ޡΓగਖ਼Ϩϕϧ ϨϕϧL Low ໿7% ϨϕϧM Medium ໿15% ϨϕϧQ Quality) ໿25%

    ϨϕϧH High ໿30% ࢀߟ: https://www.qrcode.com/about/error_correction.html
  12. ޡΓగਖ਼ σʔλίʔυϫʔυ: 10 / గਖ਼ର৅: 5 ޡΓగਖ਼ίʔυϫʔυ: 52  10

    గਖ਼͢Δίʔυϫʔυͷ2ഒ గਖ਼཰: 5 / 20  25% (ϨϕϧQ σʔλίʔυϫʔυ ޡΓగਖ਼ίʔυϫʔυ શίʔυϫʔυ
  13. 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/
  14. 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/
  15. 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/
  16. 0 0 1 1 ෼ׂ23ίʔυ ϔομʔ ύσΟϯά σʔλ Ϟʔυࢦࣔࢠ ;ͭ͏ͷQRίʔυ

    3 ෼ׂQRίʔυ ෼ׂQRίʔυ ͜ΕԿ൪໨ʁ શ෦ͰԿݸʁ ϖʔδ൪߸ ࠷େϖʔδ൪߸ ࿈݁༻IDతͳѻ͍Λ͞Ε͕ͪ ࢀߟ: https://programresource.net/2013/05/04/2193.html ύϦςΟ(্Ґ) ύϦςΟ(ԼҐ)
  17.          

      σʔλͷେ͖͞     ϔομʔ 1101110 1111001 1100001 1101110 4byte σʔλ͸4byte෼ೖͬͯΔͷͶʂ σʔλίʔυϫʔυ 8bit
  18. ऴ୺ύλʔϯύσΟϯάύλʔϯ         

       ϔομʔ 1101110 1111001 1100001 1101110 σʔλίʔυϫʔυ
  19. ϚεΫύλʔϯ 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
  20. ϚεΫύλʔϯ 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
  21. ϑΥʔϚοτ৘ใ ޡΓగਖ਼Ϩϕϧ ϚεΫύλʔϯ      2bit 3bit

    ޡΓగਖ਼ූ߸ʢBCHූ߸ʣ bchCode(formatInfo, poly: 0x537)
  22. ϚεΫύλʔϯ 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
  23. ϚεΫύλʔϯ 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