1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "./num.h"
#include "./tga.h"
#include "./upc.h"
#define UPC_A_WIDTH 113
#define UPC_A_HEIGHT 79
typedef struct {
int eflag;
int nflag;
char *ovalue;
} opts;
char *getInput( int index, char *argv[] );
opts parseOpts( int argc, char *argv[] );
void DrawBarcode( char *dst, const char *src );
void DrawNumbers( char *dst, const char *src );
int main(int argc, char *argv[]) {
// Parse CLI options
opts options = parseOpts( argc, argv );
// Parse CLI input
char *input = getInput( optind, argv );
// Set final element of input array to the appropriate check digit
input[11] = upc_a_calculate_check_digit( input );
// Create array of chars to represent 1D barcode
const char *barcode = create_upc_a( input );
// Allocate memory to hold image data
char *image = malloc( UPC_A_WIDTH * UPC_A_HEIGHT );
// Draw barcode to image data
DrawBarcode( image, barcode );
// Draw human-readable interpretation if '-e' is used
if( options.nflag ) {
DrawNumbers( image, input );
}
free( input );
// Create a .tga image file using image data
CreateTGA( options.ovalue, UPC_A_WIDTH, UPC_A_HEIGHT, image );
free( image );
return 0;
}
char *getInput( int index, char *argv[] ) {
char *result = malloc( 12 );
int k = 0;
for( int i = index; argv[i] != NULL; ++i ) {
for( int j = 0; j < strlen(argv[i]); ++j ) {
if( argv[i][j] < 58 && argv[i][j] > 47 ) {
result[k] = argv[i][j];
result[k] -= 48;
++k;
}
}
}
if( k != 11 ) {
printf( "Inappropriate input detected!\nPlease provide an 11-digit number.\n" );
}
return result;
}
opts parseOpts( int argc, char *argv[] ) {
opts options = { 0, 0, NULL };
int c;
while( ( c = getopt(argc, argv, "eno:")) != -1 ) {
switch( c ) {
case 'e':
options.eflag = 1;
break;
case 'n':
options.nflag = 1;
break;
case 'o':
options.ovalue = optarg;
break;
}
}
return options;
}
void DrawBarcode( char *dst, const char *src ) {
const char UPC_A_QUIET_ZONE[9] = {0};
for(int i = 0; i < UPC_A_HEIGHT; ++i) {
memcpy( dst + (i * UPC_A_WIDTH), &UPC_A_QUIET_ZONE, sizeof(UPC_A_QUIET_ZONE) );
memcpy( dst + 9 + (i * UPC_A_WIDTH), src, 95 );
memcpy( dst + 104 + (i * UPC_A_WIDTH), &UPC_A_QUIET_ZONE, sizeof(UPC_A_QUIET_ZONE) );
}
}
void DrawNumbers( char *dst, const char *src ) {
const int POSITION_0 = UPC_A_WIDTH * (UPC_A_HEIGHT - 16) + 1;
const int POSITION_1 = UPC_A_WIDTH * (UPC_A_HEIGHT - 16) + 14;
const int POSITION_2 = UPC_A_WIDTH * (UPC_A_HEIGHT - 16) + 59;
const int POSITION_3 = UPC_A_WIDTH * (UPC_A_HEIGHT - 16) + 104;
for(int i = 0; i < 16; ++i) {
memcpy( dst + POSITION_0 + (i * UPC_A_WIDTH), NUMBER[src[0]][i], sizeof(NUMBER[0][i]) );
}
for( int i = 0; i < 5; ++i ) {
for(int j = 0; j < 16; ++j) {
memcpy( dst + POSITION_1 + (j * UPC_A_WIDTH) + (i * 8), NUMBER[src[i + 1]][j], sizeof(NUMBER[0][j]) );
}
}
for( int i = 0; i < 5; ++i ) {
for(int j = 0; j < 16; ++j) {
memcpy( dst + POSITION_2 + (j * UPC_A_WIDTH) + (i * 8), NUMBER[src[i + 6]][j], sizeof(NUMBER[0][j]) );
}
}
for(int i = 0; i < 16; ++i) {
memcpy( dst + POSITION_3 + (i * UPC_A_WIDTH), NUMBER[src[11]][i], sizeof(NUMBER[0][i]) );
}
}
|