summaryrefslogtreecommitdiff
path: root/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.c')
-rw-r--r--src/main.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..b5e115e
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,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]) );
+ }
+}