Пример #1
0
/*!
 *  barcodeDecode39()
 *
 *      Input:  barstr (of widths, in set {1, 2})
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref:  http://en.wikipedia.org/wiki/Code39
 *                http://morovia.com/education/symbology/code39.asp
 *      (2) Each symbol has 5 black and 4 white bars.
 *          The start and stop codes are 121121211 (the asterisk)
 *      (3) This decoder was contributed by Roger Hyde.
 */
static char *
barcodeDecode39(char    *barstr,
                l_int32  debugflag)
{
char     *data, *vbarstr;
char      code[10];
l_int32   valid, reverse, i, j, len, error, nsymb, start, found;

    PROCNAME("barcodeDecode39");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format; reverse if necessary */
    barcodeVerifyFormat(barstr, L_BF_CODE39, &valid, &reverse);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in code39 format", procName, NULL);
    if (reverse)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Verify size */
    len = strlen(vbarstr);
    if ((len + 1) % 10 != 0)
        return (char *)ERROR_PTR("size+1 not divisible by 10: invalid code 39",
                                 procName, NULL);

        /* Decode the symbols */
    nsymb = (len - 19) / 10;
    data = (char *)LEPT_CALLOC(nsymb + 1, sizeof(char));
    memset(code, 0, 10);
    error = FALSE;
    for (i = 0; i < nsymb; i++) {
        start = 10 + 10 * i;
        for (j = 0; j < 9; j++)
            code[j] = vbarstr[start + j];

        if (debugflag)
            fprintf(stderr, "code: %s\n", code);

        found = FALSE;
        for (j = 0; j < C39_START; j++) {
            if (!strcmp(code, Code39[j])) {
                data[i] = Code39Val[j];
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
    }
    LEPT_FREE(vbarstr);

    if (error) {
        LEPT_FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

    return data;
}
Пример #2
0
/*!
 *  barcodeDecode2of5()
 *
 *      Input:  barstr (of widths, in set {1, 2})
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref: http://en.wikipedia.org/wiki/Two-out-of-five_code (Note:
 *                 the codes given here are wrong!)
 *               http://morovia.com/education/symbology/code25.asp
 *      (2) This is a very low density encoding for the 10 digits.
 *          Each digit is encoded with 5 black bars, of which 2 are wide
 *          and 3 are narrow.  No information is carried in the spaces
 *          between the bars, which are all equal in width, represented by
 *          a "1" in our encoding.
 *      (3) The mapping from the sequence of five bar widths to the
 *          digit is identical to the mapping used by the interleaved
 *          2 of 5 code.  The start code is 21211, representing two
 *          wide bars and a narrow bar, and the interleaved "1" spaces
 *          are explicit.  The stop code is 21112.  For all codes
 *          (including start and stop), the trailing space "1" is
 *          implicit -- there is no reason to represent it in the
 *          Code2of5[] array.
 */
static char *
barcodeDecode2of5(char    *barstr,
                  l_int32  debugflag)
{
char    *data, *vbarstr;
char     code[10];
l_int32  valid, reverse, i, j, len, error, ndigits, start, found;

    PROCNAME("barcodeDecodeI2of5");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format; reverse if necessary */
    barcodeVerifyFormat(barstr, L_BF_CODE2OF5, &valid, &reverse);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in 2of5 format", procName, NULL);
    if (reverse)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Verify size */
    len = strlen(vbarstr);
    if ((len - 11) % 10 != 0)
        return (char *)ERROR_PTR("size not divisible by 10: invalid 2of5 code",
                                 procName, NULL);

    error = FALSE;
    ndigits = (len - 11) / 10;
    data = (char *)LEPT_CALLOC(ndigits + 1, sizeof(char));
    memset(code, 0, 10);
    for (i = 0; i < ndigits; i++) {
        start = 6 + 10 * i;
        for (j = 0; j < 9; j++)
            code[j] = vbarstr[start + j];

        if (debugflag)
            fprintf(stderr, "code: %s\n", code);

        found = FALSE;
        for (j = 0; j < 10; j++) {
            if (!strcmp(code, Code2of5[j])) {
                data[i] = 0x30 + j;
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
    }
    LEPT_FREE(vbarstr);

    if (error) {
        LEPT_FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

    return data;
}
Пример #3
0
/*!
 *  barcodeFindFormat()
 *
 *      Input:  barstr (of barcode widths, in set {1,2,3,4})
 *      Return: format (for barcode), or L_BF_UNKNOWN if not recognized
 */
static l_int32
barcodeFindFormat(char    *barstr)
{
l_int32  i, format, valid;

   PROCNAME("barcodeFindFormat");

   if (!barstr)
       return ERROR_INT("barstr not defined", procName, L_BF_UNKNOWN);

   for (i = 0; i < NumSupportedBarcodeFormats; i++) {
       format = SupportedBarcodeFormat[i];
       barcodeVerifyFormat(barstr, format, &valid, NULL);
       if (valid) {
           L_INFO("Barcode format: %s\n", procName,
                   SupportedBarcodeFormatName[i]);
           return format;
       }
   }
   return L_BF_UNKNOWN;
}
Пример #4
0
/*!
 *  barcodeDecodeEan13()
 *
 *      Input:  barstr (of widths, in set {1, 2, 3, 4})
 *              first (first digit: 0 - 9)
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref:  http://en.wikipedia.org/wiki/UniversalProductCode
 *                http://morovia.com/education/symbology/ean-13.asp
 *      (2) The encoding is essentially the same as UPC-A, except
 *          there are 13 digits in total, of which 12 are encoded
 *          by bars (as with UPC-A) and the 13th is a leading digit
 *          that determines the encoding of the next 6 digits,
 *          selecting each digit from one of two tables.
 *          encoded in the bars (as with UPC-A).  If the first digit
 *          is 0, the encoding is identical to UPC-A.
 *      (3) As with UPC-A, the last digit is a check digit.
 *      (4) For now, we assume the first digit is input to this function.
 *          Eventually, we will read it by pattern matching.
 *
 *    TODO: fix this for multiple tables, depending on the value of @first
 */
static char *
barcodeDecodeEan13(char    *barstr,
                   l_int32  first,
                   l_int32  debugflag)
{
char     *data, *vbarstr;
char      code[5];
l_int32   valid, i, j, len, error, start, found, sum, checkdigit;

    PROCNAME("barcodeDecodeEan13");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format.  You can't tell the orientation by the start
         * and stop codes, but you can by the location of the digits.
         * Use the UPCA verifier for EAN 13 -- it is identical. */
    barcodeVerifyFormat(barstr, L_BF_UPCA, &valid, NULL);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in EAN 13 format", procName, NULL);

        /* Verify size */
    len = strlen(barstr);
    if (len != 59)
        return (char *)ERROR_PTR("size not 59; invalid EAN 13 barcode",
                                 procName, NULL);

        /* Check the first digit.  If invalid, reverse the string. */
    memset(code, 0, 5);
    for (i = 0; i < 4; i++)
        code[i] = barstr[i + 3];
    found = FALSE;
    for (i = 0; i < 10; i++) {
        if (!strcmp(code, Upca[i])) {
            found = TRUE;
            break;
        }
    }
    if (found == FALSE)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Decode the 12 symbols */
    data = (char *)LEPT_CALLOC(13, sizeof(char));
    memset(code, 0, 5);
    error = FALSE;
    for (i = 0; i < 12; i++) {
        if (i < 6)
            start = 3 + 4 * i;
        else
            start = 32 + 4 * (i - 6);
        for (j = 0; j < 4; j++)
            code[j] = vbarstr[start + j];

        if (debugflag)
            fprintf(stderr, "code: %s\n", code);

        found = FALSE;
        for (j = 0; j < 10; j++) {
            if (!strcmp(code, Upca[j])) {
                data[i] = 0x30 + j;
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
    }
    LEPT_FREE(vbarstr);

    if (error) {
        LEPT_FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

        /* Calculate the check digit (data[11]). */
    sum = 0;
    for (i = 0; i < 12; i += 2)  /* "even" digits */
        sum += 3 * (data[i] - 0x30);
    for (i = 1; i < 12; i += 2)  /* "odd" digits */
        sum += (data[i] - 0x30);
    checkdigit = sum % 10;
    if (checkdigit)  /* not 0 */
        checkdigit = 10 - checkdigit;
    if (checkdigit + 0x30 != data[11])
        L_WARNING("Error for EAN-13 check character\n", procName);

    return data;
}
Пример #5
0
/*!
 *  barcodeDecode93()
 *
 *      Input:  barstr (of widths, in set {1, 2, 3, 4})
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref:  http://en.wikipedia.org/wiki/Code93
 *                http://morovia.com/education/symbology/code93.asp
 *      (2) Each symbol has 3 black and 3 white bars.
 *          The start and stop codes are 111141; the stop code then is
 *          terminated with a final (1) bar.
 *      (3) The last two codes are check codes.  We are checking them
 *          for correctness, and issuing a warning on failure.  Should
 *          probably not return any data on failure.
 */
static char *
barcodeDecode93(char    *barstr,
                l_int32  debugflag)
{
const char  *checkc, *checkk;
char        *data, *vbarstr;
char         code[7];
l_int32      valid, reverse, i, j, len, error, nsymb, start, found, sum;
l_int32     *index;

    PROCNAME("barcodeDecode93");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format; reverse if necessary */
    barcodeVerifyFormat(barstr, L_BF_CODE93, &valid, &reverse);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in code93 format", procName, NULL);
    if (reverse)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Verify size; skip the first 6 and last 7 bars. */
    len = strlen(vbarstr);
    if ((len - 13) % 6 != 0)
        return (char *)ERROR_PTR("size not divisible by 6: invalid code 93",
                                 procName, NULL);

        /* Decode the symbols */
    nsymb = (len - 13) / 6;
    data = (char *)LEPT_CALLOC(nsymb + 1, sizeof(char));
    index = (l_int32 *)LEPT_CALLOC(nsymb, sizeof(l_int32));
    memset(code, 0, 7);
    error = FALSE;
    for (i = 0; i < nsymb; i++) {
        start = 6 + 6 * i;
        for (j = 0; j < 6; j++)
            code[j] = vbarstr[start + j];

        if (debugflag)
            fprintf(stderr, "code: %s\n", code);

        found = FALSE;
        for (j = 0; j < C93_START; j++) {
            if (!strcmp(code, Code93[j])) {
                data[i] = Code93Val[j];
                index[i] = j;
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
    }
    LEPT_FREE(vbarstr);

    if (error) {
        LEPT_FREE(index);
        LEPT_FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

        /* Do check sums.  For character "C", use only the
         * actual data in computing the sum.  For character "K",
         * use the actual data plus the check character "C". */
    sum = 0;
    for (i = 0; i < nsymb - 2; i++)  /* skip the "C" and "K" */
        sum += ((i % 20) + 1) * index[nsymb - 3 - i];
    if (data[nsymb - 2] != Code93Val[sum % 47])
        L_WARNING("Error for check C\n", procName);

    if (debugflag) {
        checkc = Code93[sum % 47];
        fprintf(stderr, "checkc = %s\n", checkc);
    }

    sum = 0;
    for (i = 0; i < nsymb - 1; i++)  /* skip the "K" */
        sum += ((i % 15) + 1) * index[nsymb - 2 - i];
    if (data[nsymb - 1] != Code93Val[sum % 47])
        L_WARNING("Error for check K\n", procName);

    if (debugflag) {
        checkk = Code93[sum % 47];
        fprintf(stderr, "checkk = %s\n", checkk);
    }

        /* Remove the two check codes from the output */
    data[nsymb - 2] = '\0';

    LEPT_FREE(index);
    return data;
}
Пример #6
0
/*!
 *  barcodeDecodeI2of5()
 *
 *      Input:  barstr (of widths, in set {1, 2})
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref: http://en.wikipedia.org/wiki/Interleaved_2_of_5
 *      (2) This always encodes an even number of digits.
 *          The start code is 1111; the stop code is 211.
 */
static char *
barcodeDecodeI2of5(char    *barstr,
                   l_int32  debugflag)
{
char    *data, *vbarstr;
char     code1[6], code2[6];
l_int32  valid, reverse, i, j, len, error, npairs, start, found;

    PROCNAME("barcodeDecodeI2of5");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format; reverse if necessary */
    barcodeVerifyFormat(barstr, L_BF_CODEI2OF5, &valid, &reverse);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in i2of5 format", procName, NULL);
    if (reverse)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Verify size */
    len = strlen(vbarstr);
    if ((len - 7) % 10 != 0)
        return (char *)ERROR_PTR("size not divisible by 10: invalid I2of5 code",
                                 procName, NULL);

    error = FALSE;
    npairs = (len - 7) / 10;
    data = (char *)LEPT_CALLOC(2 * npairs + 1, sizeof(char));
    memset(code1, 0, 6);
    memset(code2, 0, 6);
    for (i = 0; i < npairs; i++) {
        start = 4 + 10 * i;
        for (j = 0; j < 5; j++) {
            code1[j] = vbarstr[start + 2 * j];
            code2[j] = vbarstr[start + 2 * j + 1];
        }

        if (debugflag)
            fprintf(stderr, "code1: %s, code2: %s\n", code1, code2);

        found = FALSE;
        for (j = 0; j < 10; j++) {
            if (!strcmp(code1, CodeI2of5[j])) {
                data[2 * i] = 0x30 + j;
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
        found = FALSE;
        for (j = 0; j < 10; j++) {
            if (!strcmp(code2, CodeI2of5[j])) {
                data[2 * i + 1] = 0x30 + j;
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
    }
    LEPT_FREE(vbarstr);

    if (error) {
        LEPT_FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

    return data;
}
Пример #7
0
/*!
 *  barcodeDecodeUpca()
 *
 *      Input:  barstr (of widths, in set {1, 2, 3, 4})
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref:  http://en.wikipedia.org/wiki/UniversalProductCode
 *                http://morovia.com/education/symbology/upc-a.asp
 *      (2) Each symbol has 2 black and 2 white bars, and encodes a digit.
 *          The start and stop codes are 111 and 111.  There are a total of
 *          30 black bars, encoding 12 digits in two sets of 6, with
 *          2 black bars separating the sets.
 *      (3) The last digit is a check digit.  We check for correctness, and
 *          issue a warning on failure.  Should probably not return any
 *          data on failure.
 */
static char *
barcodeDecodeUpca(char    *barstr,
                  l_int32  debugflag)
{
char     *data, *vbarstr;
char      code[5];
l_int32   valid, i, j, len, error, start, found, sum, checkdigit;

    PROCNAME("barcodeDecodeUpca");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format; reverse has no meaning here -- we must test both */
    barcodeVerifyFormat(barstr, L_BF_UPCA, &valid, NULL);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in UPC-A format", procName, NULL);

        /* Verify size */
    len = strlen(barstr);
    if (len != 59)
        return (char *)ERROR_PTR("size not 59; invalid UPC-A barcode",
                                 procName, NULL);

        /* Check the first digit.  If invalid, reverse the string. */
    memset(code, 0, 5);
    for (i = 0; i < 4; i++)
        code[i] = barstr[i + 3];
    found = FALSE;
    for (i = 0; i < 10; i++) {
        if (!strcmp(code, Upca[i])) {
            found = TRUE;
            break;
        }
    }
    if (found == FALSE)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Decode the 12 symbols */
    data = (char *)CALLOC(13, sizeof(char));
    memset(code, 0, 5);
    error = FALSE;
    for (i = 0; i < 12; i++) {
        if (i < 6)
            start = 3 + 4 * i;
        else
            start = 32 + 4 * (i - 6);
        for (j = 0; j < 4; j++)
            code[j] = vbarstr[start + j];

        if (debugflag)
            fprintf(stderr, "code: %s\n", code);

        found = FALSE;
        for (j = 0; j < 10; j++) {
            if (!strcmp(code, Upca[j])) {
                data[i] = 0x30 + j;
		found = TRUE;
                break;
            }
        }
	if (!found) error = TRUE;
    }
    FREE(vbarstr);

    if (error) {
        FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

        /* Calculate the check digit (data[11]). */
    sum = 0;
    for (i = 0; i < 12; i += 2)  /* "even" digits */
        sum += 3 * (data[i] - 0x30);
    for (i = 1; i < 11; i += 2)  /* "odd" digits */
        sum += (data[i] - 0x30);
    checkdigit = sum % 10;
    if (checkdigit)  /* not 0 */
        checkdigit = 10 - checkdigit;
    if (checkdigit + 0x30 != data[11])
        L_WARNING("Error for UPC-A check character", procName);

    return data;
}
Пример #8
0
/*!
 *  barcodeDecodeCodabar()
 *
 *      Input:  barstr (of widths, in set {1, 2})
 *              debugflag
 *      Return: data (string of digits), or null if none found or on error
 *
 *  Notes:
 *      (1) Ref:  http://en.wikipedia.org/wiki/Codabar
 *                http://morovia.com/education/symbology/codabar.asp
 *      (2) Each symbol has 4 black and 3 white bars.  They represent the
 *          10 digits, and optionally 6 other characters.  The start and
 *          stop codes can be any of four (typically denoted A,B,C,D).
 */
static char *
barcodeDecodeCodabar(char    *barstr,
                     l_int32  debugflag)
{
char     *data, *vbarstr;
char      code[8];
l_int32   valid, reverse, i, j, len, error, nsymb, start, found;

    PROCNAME("barcodeDecodeCodabar");

    if (!barstr)
        return (char *)ERROR_PTR("barstr not defined", procName, NULL);

        /* Verify format; reverse if necessary */
    barcodeVerifyFormat(barstr, L_BF_CODABAR, &valid, &reverse);
    if (!valid)
        return (char *)ERROR_PTR("barstr not in codabar format",
                                 procName, NULL);
    if (reverse)
        vbarstr = stringReverse(barstr);
    else
        vbarstr = stringNew(barstr);

        /* Verify size */
    len = strlen(vbarstr);
    if ((len + 1) % 8 != 0)
        return (char *)ERROR_PTR("size+1 not divisible by 8: invalid codabar",
                                 procName, NULL);

        /* Decode the symbols */
    nsymb = (len - 15) / 8;
    data = (char *)CALLOC(nsymb + 1, sizeof(char));
    memset(code, 0, 8);
    error = FALSE;
    for (i = 0; i < nsymb; i++) {
        start = 8 + 8 * i;
        for (j = 0; j < 7; j++)
            code[j] = vbarstr[start + j];

        if (debugflag)
            fprintf(stderr, "code: %s\n", code);

        found = FALSE;
        for (j = 0; j < 16; j++) {
            if (!strcmp(code, Codabar[j])) {
                data[i] = CodabarVal[j];
                found = TRUE;
                break;
            }
        }
        if (!found) error = TRUE;
    }
    FREE(vbarstr);

    if (error) {
        FREE(data);
        return (char *)ERROR_PTR("error in decoding", procName, NULL);
    }

    return data;
}