Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Question] Is it possible to create many QRCodes from complete text? #785

Closed
lexuanquynh opened this issue May 15, 2024 · 8 comments
Closed

Comments

@lexuanquynh
Copy link

I see that the application can read QRCode codes and combine them into complete text:

@property(nonatomic) NSInteger sequenceSize;
@property(nonatomic) NSInteger sequenceIndex;
@property(nonatomic, strong) NSString *sequenceId;

So is it possible to create many QRCodes from complete text?

@lexuanquynh
Copy link
Author

My codes:

extension ScanViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        guard self.zxingLock.wait(timeout: DispatchTime.now()) == .success else {
            // The previous image is still processed, drop the new one to prevent too much pressure
            return
        }
        let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)!
        if let result = try? reader.read(imageBuffer).first {
            //            debugPrint("Found barcode of format", result.format.rawValue, "with text", result.text)
            let codeFormat = CodeFormat(type: result.format.rawValue)
            debugPrint("codeFormat: \(codeFormat.title)")

            let sequenceId = result.sequenceId
            let sequenceIndex = result.sequenceIndex
            // check duplicate QR code
            if checkDuplicateQRCode(sequenceIndex) {
                self.zxingLock.signal()
                return
            }

            var sequenceSize = result.sequenceSize
            if !scanResultArr.isEmpty && (sequenceSize != scanResultArr[0].sequenceSize || sequenceId != scanResultArr[0].sequenceId) {
                // show alert and scan next QR code
                DispatchQueue.main.async { [weak self] in
                    self?.showNotSameQRCodeAlert()
                }

                if self.captureSession.isRunning {
                    self.captureSession.stopRunning()
                }
                self.zxingLock.signal()
                return
            }
            if sequenceSize < 0 {
                sequenceSize = 1
            }
            let text = result.text
            let scanResult = ScanResult(sequenceSize: sequenceSize, sequenceIndex: sequenceIndex, text: text, sequenceId: sequenceId)
            scanResultArr.append(scanResult)

            // set barcodeFormatLabel
            DispatchQueue.main.async { [weak self] in
                guard let self = self else { return }
                self.barcodeFormatLabel.text = "読み取り数 / 合計: \(self.scanResultArr.count) / \(sequenceSize)"
            }

            // check size of scanResultArr
            if checkSizeOfScanResultArr() {
                // show alert completion scan QR code
                // showCompletionScanQRCodeAlert()
                // run on main thread
                DispatchQueue.main.async { [weak self] in
                    self?.showCompletionScanQRCodeAlert()
                }
            } else {
                // show alert and scan next QR code
                DispatchQueue.main.async {[weak self] in
                    self?.showScanNextQRCodeAlert()
                }
            }

            self.zxingLock.signal()
            // stop camera
            self.captureSession.stopRunning()
            return
        }
        self.zxingLock.signal()
    }
}

@axxel
Copy link
Collaborator

axxel commented May 22, 2024

It will be possible in the future but currently it is not. This is related to #739 and #332.

@lexuanquynh
Copy link
Author

@axxel
This is because the technology to create multipart QR codes seems to be proprietary. I see companies that make it possible, but they keep their methods secret for business.

@axxel
Copy link
Collaborator

axxel commented May 24, 2024

This is because the technology to create multipart QR codes seems to be proprietary.

No, it is not possible within the zxing-cpp iOS wrapper (or in the base library for that matter) because no one as implemented it so far. I only recently started to put work in the encoder/writer part of the project with the addition of the zint backend, which is in experimental state right now. And I did not add this feature right away since it is pretty niche. The open source zint project can create QRCodes with structured append meta information since "forever".

@lexuanquynh
Copy link
Author

lexuanquynh commented May 24, 2024

@axxel
I spent a day reading the barcodeRawData and discovered that all the multipart information was in the first byte:
https://programresource.net/en/2013/05/04/2202.html?unapproved=77856&moderation-hash=da3973d4b1f0206e56c57b88995bc9b4#comment-77856
So I thought I could create a qr code and add metadata to it, but failed.
I think it has to do with adding attached data without changing the structure of the png image. However, learning how to add data without destroying the structure of the image would take a lot of time.

@lexuanquynh
Copy link
Author

Other way for reading the QRCode:

import Foundation
import AVFoundation

final class GCQRCodeManager {
    var isMultiQR = false
    var qrTotal: Int = 0
    var qrNumber: Int = 0
    var qrCodeID: String?

    /// init GCQRCodeManager
    /// - Parameter rawData: AVMetadataObject
    init(rawData: AVMetadataObject?) {
        guard let basicDescriptor = rawData?.value(forKeyPath: "_internal.basicDescriptor") as? NSDictionary, let barcodeRawData = basicDescriptor["BarcodeRawData"] as? NSData else { return }
        let listData = barcodeRawData.debugDescription.replacingOccurrences(of: "Optional(", with: "").replacingOccurrences(of: "<", with: "").replacingOccurrences(of: ">", with: "").split(separator: " ")

        if listData.count > 0, listData[0].count > 4 {
            let data = listData[0].description

            self.isMultiQR = self.isMultiQR(rawData: data)
            self.qrTotal = self.qrTotal(rawData: data)
            self.qrNumber = self.qrNumber(rawData: data)
            self.qrCodeID = String(data[data.index(data.startIndex, offsetBy: 3)..<data.index(data.startIndex, offsetBy: 5)])
        }
    }

    /// Check QRCode is multiple
    /// - Parameter rawData: Data Of Type String
    /// - Returns: Bool
    private func isMultiQR(rawData: String?) -> Bool {
        guard let rawData = rawData, !rawData.isEmpty else { return false }
        // If other than 3, single QR code
        return rawData.first == "3" ? true : false
    }

    /// Get QRCode Total
    /// - Parameter rawData: Data Of Type String
    /// - Returns: Int
    private func qrTotal(rawData: String?) -> Int {
        guard let rawData = rawData, rawData.count >= 3 else { return 0 }
        let endIndex = rawData.index(rawData.startIndex, offsetBy: 2)
        let total = Int(rawData[rawData.startIndex..<endIndex]) ?? 0

        return total >= 1 ? total + 1 : 0
    }

    /// Get QRCode Number
    /// - Parameter rawData: Data Of Type String
    /// - Returns: Int
    private func qrNumber(rawData: String?) -> Int {
        guard let rawData = rawData, rawData.count >= 3 else { return 0 }
        let endIndex = rawData.index(rawData.startIndex, offsetBy: 1)
        let number = Int(rawData[rawData.startIndex..<endIndex]) ?? 0
        return number + 1
    }
}

@lexuanquynh
Copy link
Author

@axxel
Anyway, thanks for answering the above questions. I am still working on how to create a multipart qrcode.
It involves splitting the data so that the qrcode image can be read more easily.

@lexuanquynh
Copy link
Author

I finally understand the principle of creating QR codes of this type.
It uses the QRcode_encodeStringStructured function.
I'm using C, then building for iOS and it works fine. If you need I will write a wrapper function for your library.
Reference:
fukuchi/libqrencode#222

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants