Add dot (circle) plotting for raster (PNG/GIF/PCX/BMP) images

This commit is contained in:
Robin Stuart 2016-08-08 23:18:55 +01:00
parent 30b8bebf82
commit 498fd4151d

View File

@ -43,66 +43,38 @@
#include <malloc.h> #include <malloc.h>
#endif /* _MSC_VER */ #endif /* _MSC_VER */
#include "maxihex.h" /* Maxicode shapes */ #include "maxihex.h" /* Maxicode shapes */
#include "font.h" /* Font for human readable text */ #include "font.h" /* Font for human readable text */
#ifndef NO_PNG #ifndef NO_PNG
extern int png_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle); extern int png_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle);
#endif /* NO_PNG */ #endif /* NO_PNG */
extern int bmp_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle); extern int bmp_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle);
extern int pcx_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle); extern int pcx_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle);
extern int gif_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle); extern int gif_pixel_plot(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle);
int save_raster_image_to_file(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle, int image_type) { int save_raster_image_to_file(struct zint_symbol *symbol, int image_height, int image_width, char *pixelbuf, int rotate_angle, int image_type) {
int error_number; int error_number;
float scaler = symbol->scale;
char *scaled_pixelbuf;
int horiz, vert, i;
int scale_width, scale_height;
if (scaler == 0) { switch (image_type) {
scaler = 0.5;
}
scale_width = image_width * scaler;
scale_height = image_height * scaler;
/* Apply scale options by creating another pixel buffer */
if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) {
printf("Insufficient memory for pixel buffer");
return ZINT_ERROR_ENCODING_PROBLEM;
} else {
for (i = 0; i < (scale_width * scale_height); i++) {
*(scaled_pixelbuf + i) = '0';
}
}
for (vert = 0; vert < scale_height; vert++) {
for (horiz = 0; horiz < scale_width; horiz++) {
*(scaled_pixelbuf + (vert * scale_width) + horiz) = *(pixelbuf + ((int) (vert / scaler) * image_width) + (int) (horiz / scaler));
}
}
switch(image_type) {
case OUT_PNG_FILE: case OUT_PNG_FILE:
#ifndef NO_PNG #ifndef NO_PNG
error_number = png_pixel_plot(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle); error_number = png_pixel_plot(symbol, image_height, image_width, pixelbuf, rotate_angle);
#else #else
return ZINT_ERROR_INVALID_OPTION; return ZINT_ERROR_INVALID_OPTION;
#endif #endif
break; break;
case OUT_PCX_FILE: case OUT_PCX_FILE:
error_number = pcx_pixel_plot(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle); error_number = pcx_pixel_plot(symbol, image_height, image_width, pixelbuf, rotate_angle);
break;
case OUT_GIF_FILE:
error_number = gif_pixel_plot(symbol, image_height, image_width, pixelbuf, rotate_angle);
break; break;
case OUT_GIF_FILE:
error_number = gif_pixel_plot(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle);
break;
default: default:
error_number = bmp_pixel_plot(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle); error_number = bmp_pixel_plot(symbol, image_height, image_width, pixelbuf, rotate_angle);
break; break;
} }
free(scaled_pixelbuf);
return error_number; return error_number;
} }
@ -186,92 +158,92 @@ void draw_letter(char *pixelbuf, unsigned char letter, int xposn, int yposn, int
} else { } else {
glyph_no = letter - 33; glyph_no = letter - 33;
} }
switch (textflags) { switch (textflags) {
case 1: // small font 5x9 case 1: // small font 5x9
max_x = 5; max_x = 5;
max_y = 9; max_y = 9;
if (xposn + max_x >= image_width) { if (xposn + max_x >= image_width) {
max_x = image_width - xposn - 1; max_x = image_width - xposn - 1;
} }
if (yposn + max_y >= image_height) { if (yposn + max_y >= image_height) {
max_y = image_height - yposn - 1; max_y = image_height - yposn - 1;
} }
for (y = 0; y < max_y; y++) { for (y = 0; y < max_y; y++) {
for (x = 0; x < max_x; x++) { for (x = 0; x < max_x; x++) {
if (small_font[(glyph_no * 9) + y] & (0x10 >> x)) { if (small_font[(glyph_no * 9) + y] & (0x10 >> x)) {
*(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1'; *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1';
} }
} }
} }
break; break;
case 2: // bold font -> twice the regular font case 2: // bold font -> twice the regular font
{ {
char * linePtr; char * linePtr;
max_x = 7; max_x = 7;
max_y = 14; max_y = 14;
if (xposn + max_x + 1 >= image_width) { if (xposn + max_x + 1 >= image_width) {
max_x = image_width - xposn - 2; max_x = image_width - xposn - 2;
} }
if (yposn + max_y >= image_height) { if (yposn + max_y >= image_height) {
max_y = image_height - yposn - 1; max_y = image_height - yposn - 1;
} }
linePtr = pixelbuf + (yposn * image_width) + xposn + 1; linePtr = pixelbuf + (yposn * image_width) + xposn + 1;
for (y = 0; y < max_y; y++) { for (y = 0; y < max_y; y++) {
char * pixelPtr = linePtr; char * pixelPtr = linePtr;
int extra_dot = 0; int extra_dot = 0;
for (x = 0; x < 7; x++) { for (x = 0; x < 7; x++) {
if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) { if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) {
*pixelPtr = '1'; *pixelPtr = '1';
extra_dot = 1; extra_dot = 1;
} else { } else {
if (extra_dot) { if (extra_dot) {
*pixelPtr = '1'; *pixelPtr = '1';
} }
extra_dot = 0; extra_dot = 0;
} }
++pixelPtr; ++pixelPtr;
} }
if (extra_dot) { if (extra_dot) {
*pixelPtr = '1'; *pixelPtr = '1';
} }
linePtr += image_width; linePtr += image_width;
} }
} }
break; break;
default: // regular font 7x15 default: // regular font 7x15
max_x = 7; max_x = 7;
max_y = 14; max_y = 14;
if (xposn + max_x >= image_width) { if (xposn + max_x >= image_width) {
max_x = image_width - xposn - 1; max_x = image_width - xposn - 1;
} }
if (yposn + max_y >= image_height) { if (yposn + max_y >= image_height) {
max_y = image_height - yposn - 1; max_y = image_height - yposn - 1;
} }
for (y = 0; y < max_y; y++) { for (y = 0; y < max_y; y++) {
for (x = 0; x < 7; x++) { for (x = 0; x < 7; x++) {
if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) { if (ascii_font[(glyph_no * 14) + y] & (0x40 >> x)) {
*(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1'; *(pixelbuf + (y * image_width) + (yposn * image_width) + xposn + x) = '1';
} }
} }
} }
break; break;
} }
} }
} }
@ -281,19 +253,19 @@ void draw_string(char *pixbuf, char input_string[], int xposn, int yposn, int te
int i, string_length, string_left_hand, letter_width = 7; int i, string_length, string_left_hand, letter_width = 7;
switch (textflags) { switch (textflags) {
case 1: // small font 5x9 case 1: // small font 5x9
letter_width = 5; letter_width = 5;
break; break;
case 2: // bold font -> width of the regular font + 1 extra dot + 1 extra space case 2: // bold font -> width of the regular font + 1 extra dot + 1 extra space
letter_width = 9; letter_width = 9;
break; break;
default: // regular font 7x15 default: // regular font 7x15
letter_width = 7; letter_width = 7;
break; break;
} }
string_length = strlen(input_string); string_length = strlen(input_string);
string_left_hand = xposn - ((letter_width * string_length) / 2); string_left_hand = xposn - ((letter_width * string_length) / 2);
@ -309,6 +281,10 @@ int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, int data_
char *pixelbuf; char *pixelbuf;
int error_number; int error_number;
int xoffset, yoffset; int xoffset, yoffset;
float scaler = symbol->scale;
char *scaled_pixelbuf;
int horiz, vert;
int scale_width, scale_height;
xoffset = symbol->border_width + symbol->whitespace_width; xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width; yoffset = symbol->border_width;
@ -355,7 +331,31 @@ int plot_raster_maxicode(struct zint_symbol *symbol, int rotate_angle, int data_
draw_bar(pixelbuf, 300 + ((symbol->border_width + symbol->whitespace_width + symbol->whitespace_width) * 2), symbol->border_width * 2, 0, image_height, image_width, image_height); draw_bar(pixelbuf, 300 + ((symbol->border_width + symbol->whitespace_width + symbol->whitespace_width) * 2), symbol->border_width * 2, 0, image_height, image_width, image_height);
} }
error_number = save_raster_image_to_file(symbol, image_height, image_width, pixelbuf, rotate_angle, data_type);
if (scaler == 0) {
scaler = 0.5;
}
scale_width = image_width * scaler;
scale_height = image_height * scaler;
/* Apply scale options by creating another pixel buffer */
if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) {
printf("Insufficient memory for pixel buffer");
return ZINT_ERROR_ENCODING_PROBLEM;
} else {
for (i = 0; i < (scale_width * scale_height); i++) {
*(scaled_pixelbuf + i) = '0';
}
}
for (vert = 0; vert < scale_height; vert++) {
for (horiz = 0; horiz < scale_width; horiz++) {
*(scaled_pixelbuf + (vert * scale_width) + horiz) = *(pixelbuf + ((int) (vert / scaler) * image_width) + (int) (horiz / scaler));
}
}
error_number = save_raster_image_to_file(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle, data_type);
free(scaled_pixelbuf);
free(pixelbuf); free(pixelbuf);
return error_number; return error_number;
} }
@ -399,6 +399,70 @@ void to_latin1(unsigned char source[], unsigned char preprocessed[]) {
return; return;
} }
void draw_circle(char *pixelbuf, int image_width, int image_height, int x0, int y0, int radius) {
int x, y;
for (y = -radius; y <= radius; y++) {
for (x = -radius; x <= radius; x++) {
if ((x * x) + (y * y) <= (radius * radius)) {
if ((y + y0 >= 0) && (y + y0 < image_height)
&& (x + x0 >= 0) && (x + x0 < image_width)) {
*(pixelbuf + ((y + y0) * image_width) + (x + x0)) = '1';
}
}
}
}
}
int plot_raster_dotty(struct zint_symbol *symbol, int rotate_angle, int data_type) {
float scaler = 2 * symbol->scale;
char *scaled_pixelbuf;
int r, i;
int scale_width, scale_height;
int error_number = 0;
int xoffset, yoffset, image_width, image_height;
symbol->height = symbol->rows; // This is true because only 2d matrix symbols are processed here
xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width;
image_width = symbol->width + xoffset + xoffset;
image_height = symbol->height + yoffset + yoffset;
if (scaler < 2.0) {
scaler = 2.0;
}
scale_width = (image_width * scaler) + 1;
scale_height = (image_height * scaler) + 1;
/* Apply scale options by creating another pixel buffer */
if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) {
printf("Insufficient memory for pixel buffer");
return ZINT_ERROR_ENCODING_PROBLEM;
} else {
for (i = 0; i < (scale_width * scale_height); i++) {
*(scaled_pixelbuf + i) = '0';
}
}
/* Plot the body of the symbol to the pixel buffer */
for (r = 0; r < symbol->rows; r++) {
for (i = 0; i < symbol->width; i++) {
if (module_is_set(symbol, r, i)) {
draw_circle(scaled_pixelbuf, scale_width, scale_height,
(int) ((i + xoffset) * scaler) + (scaler / 2.0),
(int) ((r + yoffset) * scaler) + (scaler / 2.0),
(int) (scaler / 2.0));
}
}
}
error_number = save_raster_image_to_file(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle, data_type);
free(scaled_pixelbuf);
return error_number;
}
int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_type) { int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_type) {
int textdone, main_width, comp_offset, large_bar_count; int textdone, main_width, comp_offset, large_bar_count;
char textpart[10], addon[6]; char textpart[10], addon[6];
@ -411,6 +475,10 @@ int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_t
int error_number; int error_number;
int default_text_posn; int default_text_posn;
int next_yposn; int next_yposn;
float scaler = symbol->scale;
char *scaled_pixelbuf;
int horiz, vert;
int scale_width, scale_height;
#ifndef _MSC_VER #ifndef _MSC_VER
unsigned char local_text[ustrlen(symbol->text) + 1]; unsigned char local_text[ustrlen(symbol->text) + 1];
#else #else
@ -456,8 +524,7 @@ int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_t
row_height = 0; row_height = 0;
if (symbol->output_options & SMALL_TEXT) { if (symbol->output_options & SMALL_TEXT) {
textflags = 1; textflags = 1;
} } else if (symbol->output_options & BOLD_TEXT) {
else if (symbol->output_options & BOLD_TEXT) {
textflags = 2; textflags = 2;
} }
@ -537,7 +604,7 @@ int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_t
} else { } else {
textoffset = 0; textoffset = 0;
} }
xoffset = symbol->border_width + symbol->whitespace_width; xoffset = symbol->border_width + symbol->whitespace_width;
yoffset = symbol->border_width; yoffset = symbol->border_width;
image_width = 2 * (symbol->width + xoffset + xoffset); image_width = 2 * (symbol->width + xoffset + xoffset);
@ -826,7 +893,31 @@ int plot_raster_default(struct zint_symbol *symbol, int rotate_angle, int data_t
draw_string(pixelbuf, (char*) local_text, textpos, default_text_posn, textflags, image_width, image_height); draw_string(pixelbuf, (char*) local_text, textpos, default_text_posn, textflags, image_width, image_height);
} }
error_number = save_raster_image_to_file(symbol, image_height, image_width, pixelbuf, rotate_angle, data_type);
if (scaler == 0) {
scaler = 0.5;
}
scale_width = image_width * scaler;
scale_height = image_height * scaler;
/* Apply scale options by creating another pixel buffer */
if (!(scaled_pixelbuf = (char *) malloc(scale_width * scale_height))) {
printf("Insufficient memory for pixel buffer");
return ZINT_ERROR_ENCODING_PROBLEM;
} else {
for (i = 0; i < (scale_width * scale_height); i++) {
*(scaled_pixelbuf + i) = '0';
}
}
for (vert = 0; vert < scale_height; vert++) {
for (horiz = 0; horiz < scale_width; horiz++) {
*(scaled_pixelbuf + (vert * scale_width) + horiz) = *(pixelbuf + ((int) (vert / scaler) * image_width) + (int) (horiz / scaler));
}
}
error_number = save_raster_image_to_file(symbol, scale_height, scale_width, scaled_pixelbuf, rotate_angle, data_type);
free(scaled_pixelbuf);
free(pixelbuf); free(pixelbuf);
return error_number; return error_number;
} }
@ -840,11 +931,15 @@ int plot_raster(struct zint_symbol *symbol, int rotate_angle, int file_type) {
return ZINT_ERROR_INVALID_OPTION; return ZINT_ERROR_INVALID_OPTION;
} }
#endif /* NO_PNG */ #endif /* NO_PNG */
if (symbol->symbology == BARCODE_MAXICODE) { if (symbol->output_options &= BARCODE_DOTTY_MODE) {
error = plot_raster_maxicode(symbol, rotate_angle, file_type); error = plot_raster_dotty(symbol, rotate_angle, file_type);
} else { } else {
error = plot_raster_default(symbol, rotate_angle, file_type); if (symbol->symbology == BARCODE_MAXICODE) {
error = plot_raster_maxicode(symbol, rotate_angle, file_type);
} else {
error = plot_raster_default(symbol, rotate_angle, file_type);
}
} }
return error; return error;