Search code examples
androidkotlingoogle-mlkit

How to read CODE32 with Ml Kit in Android?


Is there a way to read Code32 (Italian Pharmacode) by using Ml Kit?

I was trying to convert the Code39 to Code32 but the reader returns completly different barcode from the read one, like by reading a Code32 like "A042028050" it returns a Code39 with value: "182M0L".

What i have tried is to transform the Code39 to Code32 but the transformation obviously fails:

 scanner.process(inputImage)
    .addOnSuccessListener { barcodes ->
        for (barcode in barcodes) {
            if (barcode.format == Barcode.FORMAT_CODE_39) {
                val code32Value = transformToCode32(barcode.rawValue)
                if (code32Value != null) {
                    Toast.makeText(
                        context,
                        "Italian Pharmaceutical Barcode (CODE 32): $code32Value",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
            
            // ...
        }

    fun transformToCode32(code39Value: String): String? {
        // Verify that the value is in the expected format for Italian pharmaceutical barcodes
        if (code39Value.length == 9 && code39Value[0] == 'A' && code39Value.substring(1).all { it.isDigit() }) {
            // Extract the 8 digits following the 'A' character
            val digits = code39Value.substring(1)
    
            // Calculate the check digit (if needed)
            // This will depend on the specific algorithm used for CODE 32
            // Here's an example algorithm that sums the digits and takes the remainder modulo 10
            val checkDigit = digits.map { it.toString().toInt() }.sum() % 10
    
            // Construct the CODE 32 value by combining the digits and check digit
            return digits + checkDigit.toString()
        }
    
        // Return null if the value does not match the expected format
        return null
    }

Solution

  • After looking around the web I've found the convertion table from Code39 to Code32 and I've built the following function that do the convertion:

    fun code39ToCode32(barcode: String): String {
        val code32set = "0123456789BCDFGHJKLMNPQRSTUWXY"
    
        if (barcode.any { it !in code32set }) {
            // it's not a code32 returning original barcode
            return barcode
        }
    
        var total = 0
    
        for (i in barcode.indices) {
            val char = barcode[i]
            val value = code32set.indexOf(char)
    
            total += value * (32.0.pow(5 - i)).toInt()
        }
    
        return "A" + String.format("%09d", total)
    }
    

    Source for the logic and conversion table.