Skip to content

Instantly share code, notes, and snippets.

@pmogollons
Last active June 7, 2024 21:58
Show Gist options
  • Save pmogollons/52d76cc219ae74baacc19b3f7c46e882 to your computer and use it in GitHub Desktop.
Save pmogollons/52d76cc219ae74baacc19b3f7c46e882 to your computer and use it in GitHub Desktop.
Función para extraer los datos del codigo de barras PDF417 de una cedula colombiana usando React Native Camera en Javascript
import moment from 'moment';
export function extractColDocumentData(data) {
let dataString = data.barcodes[0]?.data.replaceAll('�', ' ');
if (!dataString.includes('PubDSK_1')) {
throw new Error('Invalid barcode data, only PubSub_1 is supported');
}
dataString = dataString.replace('PubDSK_1', '0');
const sI = dataString.match('[a-zA-Z]').index;
dataString = dataString.substring(sI - 10);
const btIndex = dataString.match('[+]|-').index;
let usableData = dataString.substring(0, btIndex + 1);
usableData = usableData.replace(/ +/g, ' ');
const dataArray = usableData.split(' ');
const firstAlpha = dataArray[0].match('[a-zA-Z]').index;
const idNumber = Number(dataArray[0].substring(0, firstAlpha)).toString();
const lastName1 = capitalize(dataArray[0].substring(firstAlpha, dataArray[0].length));
const lastName2 = dataArray.length > 3 ? capitalize(dataArray[1]) : undefined;
const firstName1 = dataArray.length > 3 ? capitalize(dataArray[2]) : capitalize(dataArray[1]);
const middleName = dataArray.length > 4 ? capitalize(dataArray[3]) : undefined;
const extraData = dataArray.length > 4 ? dataArray[4] : dataArray.length > 3 ? dataArray[3] : dataArray[2];
const genderIndex = extraData.match(/M|F/).index;
const gender = extraData.substring(genderIndex, genderIndex + 1) === 'M' ? 'MALE' : 'FEMALE';
const birthDate = moment(`${extraData.substring(genderIndex + 1, genderIndex + 9)}`, 'YYYYMMDD').toDate();
const bloodType = extraData.substring(genderIndex + 15, genderIndex + 17);
const municipalityCode = extraData.substring(genderIndex + 10, genderIndex + 12);
const departmentCode = extraData.substring(genderIndex + 12, genderIndex + 15);
return {
idNumber,
lastName1,
lastName2,
firstName1,
middleName,
gender,
birthDate: birthDate,
bloodType,
fullName: `${firstName1}${middleName ? ` ${middleName}` : ''} ${lastName1} ${lastName2 || ''}`.trim(),
municipalityCode,
departmentCode,
};
}
function capitalize(string) {
return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
}
@rodaheva
Copy link

rodaheva commented Feb 19, 2024

He estado probando y continúa generando errores al acceder a los índices. Es posible que haya habido cambios en los datos o en la estructura que estás tratando de procesar. He creado una versión en Java y la he integrado en una extensión para App Inventor, pero aún así persisten los errores.

public class ActivityCapture extends AndroidNonvisibleComponent {

// Activity and Context
private Context context;
private Activity activity;

public ActivityCapture(ComponentContainer container){
    super(container.$form());
    this.activity = container.$context();
    this.context = container.$context();
}

@SimpleFunction(description = "Extract Colombian Document Data")
public void ExtractColDocumentData(String data) {
    String dataString = data.replace("PubDSK", "0");
    Pattern pattern = Pattern.compile("[a-zA-Z]");
    Matcher matcher = pattern.matcher(dataString);
    int sI = 0;
    while (matcher.find()) {
        sI = matcher.start();
        break;
    }
    dataString = dataString.substring(sI - 10);
    String idNumber = dataString.substring(0, 10).replaceFirst("^0+(?!$)", "");
    String lastName1 = capitalize(dataString.substring(10, 30).replaceAll("�", ""));
    String lastName2 = capitalize(dataString.substring(30, 70).replaceAll("�", ""));
    String firstName1 = capitalize(dataString.substring(70, 110).replaceAll("�", ""));
    String middleName = capitalize(dataString.substring(110, 150).replaceAll("�", ""));

    int edI = dataString.indexOf("�0");
    dataString = dataString.substring(edI);

    String dateString = dataString.substring(3, 11);
    SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
    Date birthDate = null;
    try {
        birthDate = format.parse(dateString);
    } catch (Exception e) {
        e.printStackTrace();
    }

    String gender = dataString.substring(2, 3).contains("M") ? "MALE" : "FEMALE";
    String bloodType = dataString.substring(17, 19);
    String fullName = firstName1 + (middleName != null ? " " + middleName : "") + " " + lastName1 + " " + (lastName2 != null ? lastName2 : "");
    String municipalityCode = dataString.substring(11, 13);
    String departmentCode = dataString.substring(13, 16);

    // Dispatch event with extracted data
    ExtractedDataEvent(idNumber, lastName1, lastName2, firstName1, middleName, gender, dateString, bloodType, fullName, municipalityCode, departmentCode);
}

@SimpleEvent(description = "Event triggered after extracting Colombian Document Data")
public void ExtractedDataEvent(String idNumber, String lastName1, String lastName2, String firstName1, String middleName, String gender, String birthDate, String bloodType, String fullName, String municipalityCode, String departmentCode) {
    EventDispatcher.dispatchEvent(this, "ExtractedDataEvent", idNumber, lastName1, lastName2, firstName1, middleName, gender, birthDate, bloodType, fullName, municipalityCode, departmentCode);
}

private String capitalize(String string) {
    return string.charAt(0) + string.substring(1).toLowerCase();
}

}

@pmogollons
Copy link
Author

Realice unos ajustes para mejorar el soporte para diferentes cedulas. Ahora se pueden leer cedulas con solo un nombre y un apellido, asi como 2 nombres y dos apellidos. El nuevo código es mas facil de entender y es mas estable.

Si no les funciona es muy posible que sea por que las cedulas que estan leyendo tengan un caracter de relleno o padding diferente al que tenian con las que yo probe. Pueden dejar aca el código en buena resolución o los datos crudos y yo ajusto el código.

@SkiAndory
Copy link

Hola!

Has pensado en hacerlo funcional para códigos QR de las nuevas cédulas?

@pmogollons
Copy link
Author

No he encontrado la forma de leer el QR, en el caso de las nuevas es mas facil leer el codigo que tiene en la parte posterior con OCR y extraer la info.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment