summaryrefslogtreecommitdiff
path: root/src/main.c
blob: b5e115e09b15405f88db52f3bdeb4c93a0f8767b (plain)
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]) );
    }
}