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
This commit is contained in:
Robin Stuart 2020-08-12 13:19:56 +01:00
parent 20f767c4b6
commit b5e27d3e0b
5 changed files with 80 additions and 95 deletions

View File

@ -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));
}

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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;