1 /* bmp.c - Handles output to Windows Bitmap file */
2 
3 /*
4     libzint - the open source barcode library
5     Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com>
6 
7     Redistribution and use in source and binary forms, with or without
8     modification, are permitted provided that the following conditions
9     are met:
10 
11     1. Redistributions of source code must retain the above copyright
12        notice, this list of conditions and the following disclaimer.
13     2. Redistributions in binary form must reproduce the above copyright
14        notice, this list of conditions and the following disclaimer in the
15        documentation and/or other materials provided with the distribution.
16     3. Neither the name of the project nor the names of its contributors
17        may be used to endorse or promote products derived from this software
18        without specific prior written permission.
19 
20     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21     ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23     ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26     OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29     OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30     SUCH DAMAGE.
31  */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include "common.h"
37 #include "bmp.h"        /* Bitmap header structure */
38 #include <math.h>
39 #ifdef _MSC_VER
40 #include <io.h>
41 #include <fcntl.h>
42 #endif
43 
44 #define SSET	"0123456789ABCDEF"
45 
bmp_pixel_plot(struct zint_symbol * symbol,char * pixelbuf)46 int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) {
47     int i, row, column;
48     int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
49     int row_size;
50     unsigned int data_size;
51     unsigned char *bitmap_file_start, *bmp_posn;
52     char *bitmap;
53     FILE *bmp_file;
54     bitmap_file_header_t file_header;
55     bitmap_info_header_t info_header;
56 
57     if (symbol->bitmap != NULL)
58         free(symbol->bitmap);
59 
60     row_size = 4 * floor((24.0 * symbol->bitmap_width + 31) / 32);
61     bitmap = (char *) malloc(row_size * symbol->bitmap_height);
62 
63     fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
64     fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
65     fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
66     bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
67     bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
68     bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
69 
70     /* Pixel Plotting */
71     i = 0;
72     for (row = 0; row < symbol->bitmap_height; row++) {
73         for (column = 0; column < symbol->bitmap_width; column++) {
74             i = (3 * column) + (row * row_size);
75             switch (*(pixelbuf + (symbol->bitmap_width * (symbol->bitmap_height - row - 1)) + column)) {
76                 case '1':
77                     bitmap[i] = fgblu;
78                     bitmap[i + 1] = fggrn;
79                     bitmap[i + 2] = fgred;
80                     break;
81                 default:
82                     bitmap[i] = bgblu;
83                     bitmap[i + 1] = bggrn;
84                     bitmap[i + 2] = bgred;
85                     break;
86 
87             }
88         }
89     }
90 
91     data_size = symbol->bitmap_height * row_size;
92     symbol->bitmap_byte_length = data_size;
93 
94     file_header.header_field = 0x4d42; // "BM"
95     file_header.file_size = sizeof (bitmap_file_header_t) + sizeof (bitmap_info_header_t) + data_size;
96     file_header.reserved = 0;
97     file_header.data_offset = sizeof (bitmap_file_header_t) + sizeof (bitmap_info_header_t);
98 
99     info_header.header_size = sizeof (bitmap_info_header_t);
100     info_header.width = symbol->bitmap_width;
101     info_header.height = symbol->bitmap_height;
102     info_header.colour_planes = 1;
103     info_header.bits_per_pixel = 24;
104     info_header.compression_method = 0; // BI_RGB
105     info_header.image_size = 0;
106     info_header.horiz_res = 0;
107     info_header.vert_res = 0;
108     info_header.colours = 0;
109     info_header.important_colours = 0;
110 
111     bitmap_file_start = (unsigned char*) malloc(file_header.file_size);
112     memset(bitmap_file_start, 0xff, file_header.file_size);
113 
114     bmp_posn = bitmap_file_start;
115     memcpy(bitmap_file_start, &file_header, sizeof (bitmap_file_header_t));
116     bmp_posn += sizeof (bitmap_file_header_t);
117     memcpy(bmp_posn, &info_header, sizeof (bitmap_info_header_t));
118     bmp_posn += sizeof (bitmap_info_header_t);
119     memcpy(bmp_posn, bitmap, data_size);
120 
121     /* Open output file in binary mode */
122     if ((symbol->output_options & BARCODE_STDOUT) != 0) {
123 #ifdef _MSC_VER
124         if (-1 == _setmode(_fileno(stdout), _O_BINARY)) {
125             strcpy(symbol->errtxt, "600: Can't open output file");
126             free(bitmap_file_start);
127             free(bitmap);
128             return ZINT_ERROR_FILE_ACCESS;
129         }
130 #endif
131         bmp_file = stdout;
132     } else {
133         if (!(bmp_file = fopen(symbol->outfile, "wb"))) {
134             free(bitmap_file_start);
135             free(bitmap);
136             strcpy(symbol->errtxt, "601: Can't open output file");
137             return ZINT_ERROR_FILE_ACCESS;
138         }
139     }
140 
141     fwrite(bitmap_file_start, file_header.file_size, 1, bmp_file);
142     fclose(bmp_file);
143 
144     free(bitmap_file_start);
145     free(bitmap);
146     return 0;
147 }
148