From b5e27d3e0ba355cdc704589d86ea205c2157043a Mon Sep 17 00:00:00 2001 From: Robin Stuart Date: Wed, 12 Aug 2020 13:19:56 +0100 Subject: [PATCH] Better compression for Ultracode in BMP Also corrects colour shifting bug File size is still bigger than it needs to be for Ultracode, but now uses 4bpp --- backend/bmp.c | 74 +++++++++++++++++++----------------------------- backend/bmp.h | 4 +-- backend/common.c | 45 +++++++++++++++++++++++++++++ backend/common.h | 4 +++ backend/emf.c | 48 ------------------------------- 5 files changed, 80 insertions(+), 95 deletions(-) diff --git a/backend/bmp.c b/backend/bmp.c index 9c4bc294..07bc7e14 100644 --- a/backend/bmp.c +++ b/backend/bmp.c @@ -52,10 +52,11 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { bitmap_info_header_t info_header; color_ref_t bg_color_ref; color_ref_t fg_color_ref; + color_ref_t ultra_color_ref[8]; if (symbol->symbology == BARCODE_ULTRA) { - bits_per_pixel = 24; - colour_count = 0; + bits_per_pixel = 4; + colour_count = 9; } else { bits_per_pixel = 1; colour_count = 2; @@ -63,9 +64,7 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { row_size = 4 * ((bits_per_pixel * symbol->bitmap_width + 31) / 32); data_size = symbol->bitmap_height * row_size; data_offset = sizeof (bitmap_file_header_t) + sizeof (bitmap_info_header_t); - if (symbol->symbology != BARCODE_ULTRA) { - data_offset += (2 * (sizeof(color_ref_t))); - } + data_offset += (colour_count * (sizeof(color_ref_t))); file_size = data_offset + data_size; bitmap_file_start = (unsigned char *) malloc(file_size); @@ -85,64 +84,44 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { bg_color_ref.green = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); bg_color_ref.blue = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); bg_color_ref.reserved = 0x00; + + for (i = 0; i < 8; i++) { + ultra_color_ref[i].red = colour_to_red(i + 1); + ultra_color_ref[i].green = colour_to_green(i + 1); + ultra_color_ref[i].blue = colour_to_blue(i + 1); + ultra_color_ref[i].reserved = 0x00; + } /* Pixel Plotting */ if (symbol->symbology == BARCODE_ULTRA) { for (row = 0; row < symbol->bitmap_height; row++) { for (column = 0; column < symbol->bitmap_width; column++) { - i = (3 * column) + (row * row_size); + i = (column / 2) + (row * row_size); switch (*(pixelbuf + (symbol->bitmap_width * (symbol->bitmap_height - row - 1)) + column)) { - case 'W': // White - bitmap[i] = 255; - bitmap[i + 1] = 255; - bitmap[i + 2] = 255; - break; case 'C': // Cyan - bitmap[i] = 255; - bitmap[i + 1] = 255; - bitmap[i + 2] = 0; + bitmap[i] += 1 << (4 * (1 - (column % 2))); break; case 'B': // Blue - bitmap[i] = 255; - bitmap[i + 1] = 0; - bitmap[i + 2] = 0; + bitmap[i] += 2 << (4 * (1 - (column % 2))); break; case 'M': // Magenta - bitmap[i] = 255; - bitmap[i + 1] = 0; - bitmap[i + 2] = 255; + bitmap[i] += 3 << (4 * (1 - (column % 2))); break; case 'R': // Red - bitmap[i] = 0; - bitmap[i + 1] = 0; - bitmap[i + 2] = 255; + bitmap[i] += 4 << (4 * (1 - (column % 2))); break; case 'Y': // Yellow - bitmap[i] = 0; - bitmap[i + 1] = 255; - bitmap[i + 2] = 255; + bitmap[i] += 5 << (4 * (1 - (column % 2))); break; case 'G': // Green - bitmap[i] = 0; - bitmap[i + 1] = 255; - bitmap[i + 2] = 0; + bitmap[i] += 6 << (4 * (1 - (column % 2))); break; case 'K': // Black - bitmap[i] = 0; - bitmap[i + 1] = 0; - bitmap[i + 2] = 0; + bitmap[i] += 7 << (4 * (1 - (column % 2))); break; - case '1': - bitmap[i] = fg_color_ref.blue; - bitmap[i + 1] = fg_color_ref.green; - bitmap[i + 2] = fg_color_ref.red; + case 'W': // White + bitmap[i] += 8 << (4 * (1 - (column % 2))); break; - default: - bitmap[i] = bg_color_ref.blue; - bitmap[i + 1] = bg_color_ref.green; - bitmap[i + 2] = bg_color_ref.red; - break; - } } } @@ -181,9 +160,14 @@ INTERNAL int bmp_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { bmp_posn += sizeof (bitmap_file_header_t); memcpy(bmp_posn, &info_header, sizeof (bitmap_info_header_t)); - if (symbol->symbology != BARCODE_ULTRA) { - bmp_posn += sizeof(bitmap_info_header_t); - memcpy(bmp_posn, &bg_color_ref, sizeof(color_ref_t)); + bmp_posn += sizeof(bitmap_info_header_t); + memcpy(bmp_posn, &bg_color_ref, sizeof(color_ref_t)); + if (symbol->symbology == BARCODE_ULTRA) { + for (i = 0; i < 8; i++) { + bmp_posn += sizeof(color_ref_t); + memcpy(bmp_posn, &ultra_color_ref[i], sizeof(color_ref_t)); + } + } else { bmp_posn += sizeof(color_ref_t); memcpy(bmp_posn, &fg_color_ref, sizeof(color_ref_t)); } diff --git a/backend/bmp.h b/backend/bmp.h index 3f3b256e..cb71d56c 100644 --- a/backend/bmp.h +++ b/backend/bmp.h @@ -67,9 +67,9 @@ extern "C" { } bitmap_info_header_t; typedef struct color_ref { - uint8_t red; - uint8_t green; uint8_t blue; + uint8_t green; + uint8_t red; uint8_t reserved; } color_ref_t; diff --git a/backend/common.c b/backend/common.c index f9a36060..3690d83b 100644 --- a/backend/common.c +++ b/backend/common.c @@ -449,6 +449,51 @@ INTERNAL void pn_define_mode(char *mode, const unsigned int data[], const size_t } } +INTERNAL int colour_to_red(int colour) { + int return_val = 0; + + switch(colour) { + case 8: // White + case 3: // Magenta + case 4: // Red + case 5: // Yellow + return_val = 255; + break; + } + + return return_val; +} + +INTERNAL int colour_to_green(int colour) { + int return_val = 0; + + switch(colour) { + case 8: // White + case 1: // Cyan + case 5: // Yellow + case 6: // Green + return_val = 255; + break; + } + + return return_val; +} + +INTERNAL int colour_to_blue(int colour) { + int return_val = 0; + + switch(colour) { + case 8: // White + case 1: // Cyan + case 2: // Blue + case 3: // Magenta + return_val = 255; + break; + } + + return return_val; +} + #ifdef ZINT_TEST /* Dumps hex-formatted codewords in symbol->errtxt (for use in testing) */ void debug_test_codeword_dump(struct zint_symbol *symbol, unsigned char *codewords, int length) { diff --git a/backend/common.h b/backend/common.h index c2e348ec..2ad54d9e 100644 --- a/backend/common.h +++ b/backend/common.h @@ -100,6 +100,10 @@ extern "C" { INTERNAL void pn_define_mode(char *mode, const unsigned int data[], const size_t length, const int debug, unsigned int state[], const char mode_types[], const int num_modes, pn_head_costs head_costs, pn_switch_cost switch_cost, pn_eod_cost eod_cost, pn_cur_cost cur_cost); + + INTERNAL int colour_to_red(int colour); + INTERNAL int colour_to_green(int colour); + INTERNAL int colour_to_blue(int colour); #ifdef ZINT_TEST void debug_test_codeword_dump(struct zint_symbol *symbol, unsigned char *codewords, int length); diff --git a/backend/emf.c b/backend/emf.c index 0e971434..aba3ff2c 100644 --- a/backend/emf.c +++ b/backend/emf.c @@ -42,51 +42,6 @@ #include "common.h" #include "emf.h" -int colour_to_red(int colour) { - int return_val = 0; - - switch(colour) { - case 8: // White - case 3: // Magenta - case 4: // Red - case 5: // Yellow - return_val = 255; - break; - } - - return return_val; -} - -int colour_to_green(int colour) { - int return_val = 0; - - switch(colour) { - case 8: // White - case 1: // Cyan - case 5: // Yellow - case 6: // Green - return_val = 255; - break; - } - - return return_val; -} - -int colour_to_blue(int colour) { - int return_val = 0; - - switch(colour) { - case 8: // White - case 1: // Cyan - case 2: // Blue - case 3: // Magenta - return_val = 255; - break; - } - - return return_val; -} - static int count_rectangles(struct zint_symbol *symbol) { int rectangles = 0; struct zint_vector_rect *rect; @@ -617,18 +572,15 @@ INTERNAL int emf_plot(struct zint_symbol *symbol) { } if (symbol->symbology == BARCODE_ULTRA) { - printf("Using Ultra draw\n"); for(i = 0; i < 8; i++) { if (rectangle_count_bycolour[i]) { fwrite(&emr_selectobject_colour[i], sizeof (emr_selectobject_t), 1, emf_file); - printf("colour %d\n", i); rect = symbol->vector->rectangles; this_rectangle = 0; while (rect) { if (rect->colour == i) { fwrite(&rectangle[this_rectangle], sizeof (emr_rectangle_t), 1, emf_file); - printf("rect\n"); } this_rectangle++; rect = rect->next;