@@ -10,7 +10,7 @@ struct LiveMRZScannerView: View {
1010 @State private var lastMRZDetection : Date = Date ( )
1111 @State private var parsedMRZ : QKMRZResult ? = nil
1212 @State private var scanComplete : Bool = false
13- @State private var overrideDocumentNumber : String ? = nil // for Belgian ID overflow format
13+ @State private var overrideDocumentNumber : String ? = nil // for TD1 overflow format (ID cards)
1414 var onScanComplete : ( ( QKMRZResult ) -> Void ) ? = nil
1515 var onScanResultAsDict : ( ( [ String : Any ] ) -> Void ) ? = nil
1616
@@ -61,8 +61,8 @@ struct LiveMRZScannerView: View {
6161 }
6262
6363 private func mapVisionResultToDictionary( _ result: QKMRZResult ) -> [ String : Any ] {
64-
65- // using manually validated document number for Belgian IDs ( overflow format)
64+
65+ // using manually validated document number for TD1 documents with overflow format
6666 // this is necessary for NFC chip authentication which requires the full document number
6767 let documentNumber = overrideDocumentNumber ?? result. documentNumber
6868
@@ -111,12 +111,13 @@ struct LiveMRZScannerView: View {
111111 return sum % 10
112112 }
113113
114- /// Extracts and validates the Belgian document number from MRZ line 1, handling both standard and overflow formats.
115- /// Belgian TD1 format uses an overflow mechanism when document numbers exceed 9 digits.
114+ /// Extracts and validates the document number from TD1 MRZ line 1, handling both standard and overflow formats.
115+ /// TD1 format uses an overflow mechanism when document numbers exceed 9 digits.
116116 /// Example overflow format: IDBEL595392450<8039<<<<<<<<<< where positions 6-14 contain the principal part (595392450),
117117 /// position 15 contains the overflow indicator (<), positions 16-18 contain overflow digits (803), and position 19 contains the check digit (9).
118118 /// The full document number becomes: 595392450803.
119- private func extractAndValidateBelgianDocumentNumber( line1: String ) -> ( documentNumber: String , isValid: Bool ) ? {
119+ /// This overflow format can occur for any country using TD1 MRZ (ID cards).
120+ private func extractAndValidateTD1DocumentNumber( line1: String ) -> ( documentNumber: String , isValid: Bool ) ? {
120121 guard line1. count == 30 else { return nil }
121122
122123 // extracting positions 6-14 (9 characters - principal part)
@@ -133,7 +134,7 @@ struct LiveMRZScannerView: View {
133134 let checkDigit = Int ( String ( pos15) ) ?? - 1
134135 let calculatedCheck = calculateMRZCheckDigit ( principalPart)
135136 let isValid = ( checkDigit == calculatedCheck)
136- print ( " [extractAndValidateBelgianDocumentNumber ] Standard format: \( principalPart) , check= \( checkDigit) , calculated= \( calculatedCheck) , valid= \( isValid) " )
137+ print ( " [extractAndValidateTD1DocumentNumber ] Standard format: \( principalPart) , check= \( checkDigit) , calculated= \( calculatedCheck) , valid= \( isValid) " )
137138 return ( principalPart, isValid)
138139 }
139140
@@ -153,7 +154,7 @@ struct LiveMRZScannerView: View {
153154 }
154155
155156 guard overflowDigits. count > 0 else {
156- print ( " [extractAndValidateBelgianDocumentNumber ] ERROR: No overflow digits found " )
157+ print ( " [extractAndValidateTD1DocumentNumber ] ERROR: No overflow digits found " )
157158 return nil
158159 }
159160
@@ -167,14 +168,14 @@ struct LiveMRZScannerView: View {
167168 // validating check digit against full document number
168169 guard let checkDigitChar = checkDigitChar,
169170 let checkDigit = Int ( String ( checkDigitChar) ) else {
170- print ( " [extractAndValidateBelgianDocumentNumber ] ERROR: Invalid check digit " )
171+ print ( " [extractAndValidateTD1DocumentNumber ] ERROR: Invalid check digit " )
171172 return nil
172173 }
173174 let calculatedCheck = calculateMRZCheckDigit ( fullDocumentNumber)
174175 let isValid = ( checkDigit == calculatedCheck)
175176
176177 #if DEBUG
177- print ( " [extractAndValidateBelgianDocumentNumber ] Overflow format: " )
178+ print ( " [extractAndValidateTD1DocumentNumber ] Overflow format: " )
178179 print ( " Principal part (6-14): \( principalPart) " )
179180 print ( " Overflow with check: \( overflowDigits) " )
180181 print ( " Overflow without check: \( overflowWithoutCheck) " )
@@ -198,11 +199,11 @@ struct LiveMRZScannerView: View {
198199 onScanResultAsDict ? ( mapVisionResultToDictionary ( result) )
199200 }
200201
201- /// Processes Belgian ID documents by manually extracting and validating the document number using the overflow format handler,
202+ /// Processes TD1 documents ( ID cards) by manually extracting and validating the document number using the overflow format handler,
202203 /// then parses the remaining MRZ fields (name, dates, etc.) using QKMRZParser. This bypasses QKMRZParser's validation for the
203- /// document number field since it doesn't handle Belgian overflow format correctly.
204- private func processBelgiumDocument ( result: String , parser: QKMRZParser ) -> QKMRZResult ? {
205- print ( " [LiveMRZScannerView] Processing Belgium document with manual validation " )
204+ /// document number field since it doesn't handle TD1 overflow format correctly.
205+ private func processTD1DocumentWithOverflow ( result: String , parser: QKMRZParser ) -> QKMRZResult ? {
206+ print ( " [LiveMRZScannerView] Processing TD1 document with manual overflow validation " )
206207
207208 let lines = result. components ( separatedBy: " \n " )
208209 guard lines. count >= 3 else {
@@ -214,17 +215,17 @@ struct LiveMRZScannerView: View {
214215 print ( " [LiveMRZScannerView] Line 1: \( line1) " )
215216
216217 // extracting and validating document number manually using overflow format handler
217- guard let ( documentNumber, isDocNumberValid) = extractAndValidateBelgianDocumentNumber ( line1: line1) else {
218- print ( " [LiveMRZScannerView] Failed to extract Belgian document number " )
218+ guard let ( documentNumber, isDocNumberValid) = extractAndValidateTD1DocumentNumber ( line1: line1) else {
219+ print ( " [LiveMRZScannerView] Failed to extract TD1 document number " )
219220 return nil
220221 }
221222
222223 if !isDocNumberValid {
223- print ( " [LiveMRZScannerView] Belgian document number check digit is INVALID " )
224+ print ( " [LiveMRZScannerView] TD1 document number check digit is INVALID " )
224225 return nil
225226 }
226227
227- print ( " [LiveMRZScannerView] Belgian document number validated: \( documentNumber) ✓ " )
228+ print ( " [LiveMRZScannerView] TD1 document number validated: \( documentNumber) ✓ " )
228229
229230 // parsing the original MRZ to get all other fields (name, birthdate, etc.)
230231 // using QKMRZParser for non-documentNumber fields
@@ -233,9 +234,9 @@ struct LiveMRZScannerView: View {
233234 return nil
234235 }
235236
236- // validating that other fields are also correct (consistency with non-Belgium documents)
237+ // validating that other fields are also correct
237238 if !mrzResult. isBirthdateValid || !mrzResult. isExpiryDateValid {
238- print ( " [LiveMRZScannerView] Belgium document has invalid birthdate or expiry date " )
239+ print ( " [LiveMRZScannerView] TD1 document has invalid birthdate or expiry date " )
239240 return nil
240241 }
241242
@@ -285,10 +286,13 @@ struct LiveMRZScannerView: View {
285286 return
286287 }
287288
288- // Handle Belgium documents (only if not already valid)
289- if doc. countryCode == " BEL " {
290- if let belgiumResult = processBelgiumDocument ( result: result, parser: parser) {
291- handleValidMRZResult ( belgiumResult)
289+ // handling TD1 documents with potential overflow format (only if not already valid)
290+ // TD1 format has 3 lines of 30 characters each
291+ let lines = result. components ( separatedBy: " \n " )
292+ if lines. count >= 3 && lines [ 0 ] . count == 30 {
293+ // trying overflow validation
294+ if let td1Result = processTD1DocumentWithOverflow ( result: result, parser: parser) {
295+ handleValidMRZResult ( td1Result)
292296 }
293297 return
294298 }
0 commit comments