Add verification for North America VIN (Vehicle Identification Number)

This commit is contained in:
Robin Stuart 2018-02-03 18:44:01 +00:00
parent 38150ce931
commit e737f992b5
5 changed files with 146 additions and 38 deletions

View File

@ -39,6 +39,7 @@
#define SODIUM "0123456789-" #define SODIUM "0123456789-"
#define SILVER "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd" #define SILVER "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%abcd"
#define ARSENIC "0123456789ABCDEFGHJKLMNPRSTUVWXYZ"
static const char *C11Table[11] = { static const char *C11Table[11] = {
"111121", "211121", "121121", "221111", "112121", "212111", "122111", "111121", "211121", "121121", "221111", "112121", "212111", "122111",
@ -461,7 +462,7 @@ int c93(struct zint_symbol *symbol, unsigned char source[], int length) {
"It is the intent and understanding of AIM [t]hat the symbology presented in this "It is the intent and understanding of AIM [t]hat the symbology presented in this
specification is entirely in the public domain and free of all use restrictions, specification is entirely in the public domain and free of all use restrictions,
licenses and fees. AIM USA, its memer companies, or individual officers licenses and fees. AIM USA, its member companies, or individual officers
assume no liability for the use of this document." */ assume no liability for the use of this document." */
void CheckCharacter() { void CheckCharacter() {
@ -591,3 +592,98 @@ int channel_code(struct zint_symbol *symbol, unsigned char source[], int length)
} }
/* Vehicle Identification Number (VIN) */
int vin(struct zint_symbol *symbol, unsigned char source[], int length) {
/* This code verifies the check digit present in North American VIN codes */
int zeros;
char local_source[18];
char dest[200];
char input_check;
char output_check;
int value[17];
int weight[17] = {8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2};
int sum;
int i;
// Check length
if (length > 17) {
strcpy(symbol->errtxt, "336: Input too long");
return ZINT_ERROR_TOO_LONG;
}
// Check input characters, I, O and Q are not allowed
if (is_sane(ARSENIC, source, length) == ZINT_ERROR_INVALID_DATA) {
strcpy(symbol->errtxt, "337: Invalid characters in input data");
return ZINT_ERROR_INVALID_DATA;
}
// Pad with zeros
zeros = 17 - length;
for (i = 0; i < 17; i++) {
local_source[i] = '0';
}
local_source[17] = '\0';
for (i = 0; i < length; i++) {
local_source[zeros + i] = source[i];
}
input_check = local_source[8];
for (i = 0; i < 17; i++) {
if ((local_source[i] >= '0') && (local_source[i] <= '9')) {
value[i] = local_source[i] - '0';
}
if ((local_source[i] >= 'A') && (local_source[i] <= 'I')) {
value[i] = (local_source[i] - 'A') + 1;
}
if ((local_source[i] >= 'J') && (local_source[i] <= 'R')) {
value[i] = (local_source[i] - 'J') + 1;
}
if ((local_source[i] >= 'S') && (local_source[i] <= 'Z')) {
value[i] = (local_source[i] - 'S') + 2;
}
}
sum = 0;
for (i = 0; i < 17; i++) {
sum += value[i] * weight[i];
}
output_check = '0' + (sum % 11);
if (output_check == ':') {
// Check digit was 10
output_check = 'X';
}
if (symbol->debug) {
printf("Producing VIN code: %s\n", local_source);
printf("Input check was %c, calculated check is %c\n", input_check, output_check);
}
if (input_check != output_check) {
strcpy(symbol->errtxt, "338: Invalid check digit in input data");
return ZINT_ERROR_INVALID_DATA;
}
/* Start character */
strcpy(dest, "1211212111");
// Copy glyphs to symbol
for (i = 0; i < 17; i++) {
lookup(SILVER, C39Table, local_source[i], dest);
}
/* Stop character */
strcat(dest, "121121211");
ustrcpy(symbol->text, (unsigned char *) local_source);
expand(symbol, dest);
return 0;
}

View File

@ -171,8 +171,9 @@ extern int han_xin(struct zint_symbol * symbol, const unsigned char source[], si
extern int dotcode(struct zint_symbol * symbol, const unsigned char source[], int length); /* DotCode */ extern int dotcode(struct zint_symbol * symbol, const unsigned char source[], int length); /* DotCode */
extern int codablock(struct zint_symbol * symbol, const unsigned char source[], const size_t length); /* Codablock */ extern int codablock(struct zint_symbol * symbol, const unsigned char source[], const size_t length); /* Codablock */
extern int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* UPNQR */ extern int upnqr(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* UPNQR */
extern int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* Data Matrix (IEC16022) */ extern int qr_code(struct zint_symbol *symbol, const unsigned char source[], size_t length); /* QR Code */
extern int dmatrix(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* QR Code */ extern int dmatrix(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* Data Matrix (IEC16022) */
extern int vin(struct zint_symbol *symbol, const unsigned char source[], const size_t in_length); /* VIN Code (Vehicle Identification Number) */
extern int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */ extern int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type); /* Plot to PNG/BMP/PCX */
extern int render_plot(struct zint_symbol *symbol, float width, float height); /* Plot to gLabels */ extern int render_plot(struct zint_symbol *symbol, float width, float height); /* Plot to gLabels */
@ -554,6 +555,7 @@ int ZBarcode_ValidID(int symbol_id) {
case BARCODE_DOTCODE: case BARCODE_DOTCODE:
case BARCODE_CODABLOCKF: case BARCODE_CODABLOCKF:
case BARCODE_UPNQR: case BARCODE_UPNQR:
case BARCODE_VIN:
result = 1; result = 1;
break; break;
} }
@ -773,6 +775,8 @@ static int reduced_charset(struct zint_symbol *symbol, const unsigned char *sour
break; break;
case BARCODE_CODABLOCKF: error_number = codablock(symbol, preprocessed, in_length); case BARCODE_CODABLOCKF: error_number = codablock(symbol, preprocessed, in_length);
break; break;
case BARCODE_VIN: error_number = vin(symbol, preprocessed, in_length);
break;
} }
return error_number; return error_number;
@ -975,11 +979,6 @@ int ZBarcode_Encode(struct zint_symbol *symbol, const unsigned char *source, int
if ((symbol->symbology == 64) || (symbol->symbology == 65)) { if ((symbol->symbology == 64) || (symbol->symbology == 65)) {
symbol->symbology = BARCODE_AUSPOST; symbol->symbology = BARCODE_AUSPOST;
} }
if (symbol->symbology == 73) {
strcpy(symbol->errtxt, "211: Symbology out of range, using Code 128");
symbol->symbology = BARCODE_CODE128;
error_number = ZINT_WARN_INVALID_OPTION;
}
if (symbol->symbology == 78) { if (symbol->symbology == 78) {
symbol->symbology = BARCODE_RSS14; symbol->symbology = BARCODE_RSS14;
} }

View File

@ -151,6 +151,7 @@ extern "C" {
#define BARCODE_RM4SCC 70 #define BARCODE_RM4SCC 70
#define BARCODE_DATAMATRIX 71 #define BARCODE_DATAMATRIX 71
#define BARCODE_EAN14 72 #define BARCODE_EAN14 72
#define BARCODE_VIN 73
#define BARCODE_CODABLOCKF 74 #define BARCODE_CODABLOCKF 74
#define BARCODE_NVE18 75 #define BARCODE_NVE18 75
#define BARCODE_JAPANPOST 76 #define BARCODE_JAPANPOST 76

View File

@ -280,6 +280,7 @@ Numeric Value | Barcode Name
70 | Royal Mail 4 State (RM4SCC) 70 | Royal Mail 4 State (RM4SCC)
71 | Data Matrix (ECC200) 71 | Data Matrix (ECC200)
72 | EAN-14 72 | EAN-14
73 | Vehicle Identification Number (America)
74 | Codablock-F 74 | Codablock-F
75 | NVE-18 75 | NVE-18
76 | Japanese Postal Code 76 | Japanese Postal Code
@ -526,6 +527,7 @@ GIF | Graphics Interchange Format
PCX | ZSoft Paintbrush image PCX | ZSoft Paintbrush image
PNG | Portable Network Graphic PNG | Portable Network Graphic
SVG | Scalable Vector Graphic SVG | Scalable Vector Graphic
TIF | Tagged Image File Format
TXT | Text file (see 4.16) TXT | Text file (see 4.16)
-------------------------------------------------------------- --------------------------------------------------------------
@ -952,6 +954,7 @@ Value |
70 | BARCODE_RM4SCC | Royal Mail 4 State (RM4SCC) 70 | BARCODE_RM4SCC | Royal Mail 4 State (RM4SCC)
71 | BARCODE_DATAMATRIX | Data Matrix ECC200 71 | BARCODE_DATAMATRIX | Data Matrix ECC200
72 | BARCODE_EAN14 | EAN-14 72 | BARCODE_EAN14 | EAN-14
73 | BARCODE_VIN | Vehicle Identification Number (America)
74 | BARCODE_CODABLOCKF | Codablock-F 74 | BARCODE_CODABLOCKF | Codablock-F
75 | BARCODE_NVE18 | NVE-18 75 | BARCODE_NVE18 | NVE-18
76 | BARCODE_JAPANPOST | Japanese Postal Code 76 | BARCODE_JAPANPOST | Japanese Postal Code
@ -1309,6 +1312,12 @@ This option adds a leading '+' character and a trailing modulo-49 check digit
to a standard Code 39 symbol as required by the Health Industry Barcode to a standard Code 39 symbol as required by the Health Industry Barcode
standards. standards.
6.1.8.8 Vehicle Identification Number
-------------------------------------
This option includes a verification stage for vehicle identification numbers
used in North America which include a check digit. For European vehicle
identification numbers use Standard Code 39.
6.1.9 Codabar (EN 798) 6.1.9 Codabar (EN 798)
---------------------- ----------------------
Also known as NW-7, Monarch, ABC Codabar, USD-4, Ames Code and Code 27, this Also known as NW-7, Monarch, ABC Codabar, USD-4, Ames Code and Code 27, this
@ -2519,6 +2528,8 @@ v2.6.2 - Further bugfixes in Aztec and DotCode. Expand escape sequence support
to API and GUI. Handle UTF BOM. Bugfix raster images of Maxicode. to API and GUI. Handle UTF BOM. Bugfix raster images of Maxicode.
22/10/2017 22/10/2017
v2.6.3 - Includes VIN (US) verification. (Forthcoming)
7.4 Sources of Information 7.4 Sources of Information
-------------------------- --------------------------
Below is a list of some of the sources used in rough chronological order: Below is a list of some of the sources used in rough chronological order:

View File

@ -37,36 +37,37 @@
/* Print list of supported symbologies */ /* Print list of supported symbologies */
void types(void) { void types(void) {
printf( " 1: Code 11 50: Logmars 90: KIX Code\n" printf( " 1: Code 11 51: Pharma One-Track 92: Aztec Code\n"
" 2: Standard 2of5 51: Pharma One-Track 92: Aztec Code\n" " 2: Standard 2of5 52: PZN 93: DAFT Code\n"
" 3: Interleaved 2of5 52: PZN 93: DAFT Code\n" " 3: Interleaved 2of5 53: Pharma Two-Track 97: Micro QR Code\n"
" 4: IATA 2of5 53: Pharma Two-Track 97: Micro QR Code\n" " 4: IATA 2of5 55: PDF417 98: HIBC Code 128\n"
" 6: Data Logic 55: PDF417 98: HIBC Code 128\n" " 6: Data Logic 56: PDF417 Trunc 99: HIBC Code 39\n"
" 7: Industrial 2of5 56: PDF417 Trunc 99: HIBC Code 39\n" " 7: Industrial 2of5 57: Maxicode 102: HIBC Data Matrix\n"
" 8: Code 39 57: Maxicode 102: HIBC Data Matrix\n" " 8: Code 39 58: QR Code 104: HIBC QR Code\n"
" 9: Extended Code 39 58: QR Code 104: HIBC QR Code\n" " 9: Extended Code 39 60: Code 128-B 106: HIBC PDF417\n"
"13: EAN 60: Code 128-B 106: HIBC PDF417\n" "13: EAN 63: AP Standard Customer 108: HIBC MicroPDF417\n"
"14: EAN + Check 63: AP Standard Customer 108: HIBC MicroPDF417\n" "14: EAN + Check 66: AP Reply Paid 110: HIBC Codablock-F\n"
"16: GS1-128 66: AP Reply Paid 110: HIBC Codablock-F\n" "16: GS1-128 67: AP Routing 112: HIBC Aztec Code\n"
"18: Codabar 67: AP Routing 112: HIBC Aztec Code\n" "18: Codabar 68: AP Redirection 115: DotCode\n"
"20: Code 128 68: AP Redirection 115: DotCode\n" "20: Code 128 69: ISBN 116: Han Xin Code\n"
"21: Leitcode 69: ISBN 116: Han Xin Code\n" "21: Leitcode 70: RM4SCC 128: Aztec Runes\n"
"22: Identcode 70: RM4SCC 128: Aztec Runes\n" "22: Identcode 71: Data Matrix 129: Code 32\n"
"23: Code 16k 71: Data Matrix 129: Code 32\n" "23: Code 16k 72: EAN-14 130: Comp EAN\n"
"24: Code 49 72: EAN-14 130: Comp EAN\n" "24: Code 49 73: VIN (North America) 131: Comp GS1-128\n"
"25: Code 93 74: Codablock-F 131: Comp GS1-128\n" "25: Code 93 74: Codablock-F 132: Comp DataBar Omni\n"
"28: Flattermarken 75: NVE-18 132: Comp DataBar Omni\n" "28: Flattermarken 75: NVE-18 133: Comp DataBar Ltd\n"
"29: GS1 DataBar Omni 76: Japanese Post 133: Comp DataBar Ltd\n" "29: GS1 DataBar Omni 76: Japanese Post 134: Comp DataBar ExpOm\n"
"30: GS1 DataBar Ltd 77: Korea Post 134: Comp DataBar ExpOm\n" "30: GS1 DataBar Ltd 77: Korea Post 135: Comp UPC-A\n"
"31: GS1 DataBar ExpOm 79: GS1 DataBar Stack 135: Comp UPC-A\n" "31: GS1 DataBar ExpOm 79: GS1 DataBar Stack 136: Comp UPC-E\n"
"32: Telepen Alpha 80: GS1 DataBar Stack Omni 136: Comp UPC-E\n" "32: Telepen Alpha 80: GS1 DataBar Stack Omni 137: Comp DataBar Stack\n"
"34: UPC-A 81: GS1 DataBar ESO 137: Comp DataBar Stack\n" "34: UPC-A 81: GS1 DataBar ESO 138: Comp DataBar Stack Omni\n"
"35: UPC-A + Check 82: Planet 138: Comp DataBar Stack Omni\n" "35: UPC-A + Check 82: Planet 139: Comp DataBar ESO\n"
"37: UPC-E 84: MicroPDF 139: Comp DataBar ESO\n" "37: UPC-E 84: MicroPDF 140: Channel Code\n"
"38: UPC-E + Check 85: USPS OneCode 140: Channel Code\n" "38: UPC-E + Check 85: USPS OneCode 141: Code One\n"
"40: Postnet 86: UK Plessey 141: Code One\n" "40: Postnet 86: UK Plessey 142: Grid Matrix\n"
"47: MSI Plessey 87: Telepen Numeric 142: Grid Matrix\n" "47: MSI Plessey 87: Telepen Numeric 143: UPNQR\n"
"49: FIM 89: ITF-14 143: UPNQR\n" "49: FIM 89: ITF-14\n"
"50: Logmars 90: KIX Code\n"
); );
} }