png.c: Use palette for file size savings

This commit is contained in:
gitlost 2021-02-26 20:45:08 +00:00
parent 7f8c8114f3
commit ed3cc51a46
46 changed files with 185 additions and 63 deletions

View File

@ -2,7 +2,7 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2009-2017 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2009-2021 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -37,8 +37,6 @@
#include <io.h> #include <io.h>
#include <malloc.h> #include <malloc.h>
#endif #endif
#include <stdlib.h>
#include <string.h>
#include "common.h" #include "common.h"
#ifndef NO_PNG #ifndef NO_PNG
@ -72,37 +70,47 @@ static void writepng_error_handler(png_structp png_ptr, png_const_charp msg) {
longjmp(graphic->jmpbuf, 1); longjmp(graphic->jmpbuf, 1);
} }
/* Guestimate best compression strategy */
static int guess_compression_strategy(struct zint_symbol *symbol, unsigned char *pixelbuf) {
(void)pixelbuf;
/* TODO: Do properly */
/* It seems the best choice for typical barcode pngs is one of Z_DEFAULT_STRATEGY and Z_FILTERED */
/* Some guesses */
if (symbol->symbology == BARCODE_MAXICODE) {
return Z_DEFAULT_STRATEGY;
}
if (symbol->symbology == BARCODE_AZTEC && symbol->bitmap_width <= 30) {
return Z_DEFAULT_STRATEGY;
}
/* Z_FILTERED seems to work better for slightly more barcodes+data so default to that */
return Z_FILTERED;
}
INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) { INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) {
struct mainprog_info_type wpng_info; struct mainprog_info_type wpng_info;
struct mainprog_info_type *graphic; struct mainprog_info_type *graphic;
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
int i;
int row, column; int row, column;
unsigned char fg[4], bg[4]; png_color bg, fg;
unsigned char white[4] = { 0xff, 0xff, 0xff, 0xff }; unsigned char bg_alpha, fg_alpha;
unsigned char cyan[4] = { 0, 0xff, 0xff, 0xff }; unsigned char map[128];
unsigned char blue[4] = { 0, 0, 0xff, 0xff }; png_color palette[32];
unsigned char magenta[4] = { 0xff, 0, 0xff, 0xff }; int num_palette = 0;
unsigned char red[4] = { 0xff, 0, 0, 0xff }; unsigned char trans_alpha[32];
unsigned char yellow[4] = { 0xff, 0xff, 0, 0xff }; int num_trans = 0;
unsigned char green[4] = { 0, 0xff, 0, 0xff }; int bit_depth;
unsigned char black[4] = { 0, 0, 0, 0xff }; int compression_strategy;
unsigned char *map[91] = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x00-0F */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x10-1F */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0x20-2F */
bg, fg, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* 0-9 */
NULL, NULL, NULL, NULL, NULL, NULL, NULL, /* :;<=>?@ */
NULL, blue, cyan, NULL, NULL, NULL, green, NULL, NULL, NULL, black, NULL, magenta, /* A-M */
NULL, NULL, NULL, NULL, red, NULL, NULL, NULL, NULL, white, NULL, yellow, NULL /* N-Z */
};
int use_alpha, incr;
unsigned char *image_data;
#ifndef _MSC_VER #ifndef _MSC_VER
unsigned char outdata[symbol->bitmap_width * 4]; unsigned char outdata[symbol->bitmap_width];
#else #else
unsigned char* outdata = (unsigned char*) _alloca(symbol->bitmap_width * 4); unsigned char* outdata = (unsigned char*) _alloca(symbol->bitmap_width);
#endif #endif
graphic = &wpng_info; graphic = &wpng_info;
@ -110,28 +118,101 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
graphic->width = symbol->bitmap_width; graphic->width = symbol->bitmap_width;
graphic->height = symbol->bitmap_height; graphic->height = symbol->bitmap_height;
fg[0] = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]); fg.red = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
fg[1] = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]); fg.green = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
fg[2] = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]); fg.blue = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
bg[0] = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]); bg.red = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
bg[1] = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); bg.green = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
bg[2] = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); bg.blue = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
use_alpha = 0;
if (strlen(symbol->fgcolour) > 6) { if (strlen(symbol->fgcolour) > 6) {
fg[3] = (16 * ctoi(symbol->fgcolour[6])) + ctoi(symbol->fgcolour[7]); fg_alpha = (16 * ctoi(symbol->fgcolour[6])) + ctoi(symbol->fgcolour[7]);
white[3] = cyan[3] = blue[3] = magenta[3] = red[3] = yellow[3] = green[3] = black[3] = fg[3];
if (fg[3] != 0xff) use_alpha = 1;
} else { } else {
fg[3] = 0xff; fg_alpha = 0xff;
} }
if (strlen(symbol->bgcolour) > 6) { if (strlen(symbol->bgcolour) > 6) {
bg[3] = (16 * ctoi(symbol->bgcolour[6])) + ctoi(symbol->bgcolour[7]); bg_alpha = (16 * ctoi(symbol->bgcolour[6])) + ctoi(symbol->bgcolour[7]);
if (bg[3] != 0xff) use_alpha = 1;
} else { } else {
bg[3] = 0xff; bg_alpha = 0xff;
}
if (symbol->symbology == BARCODE_ULTRA) {
static const int ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' };
static png_color ultra_colours[8] = {
{ 0xff, 0xff, 0xff, }, /* White */
{ 0, 0xff, 0xff, }, /* Cyan */
{ 0, 0, 0xff, }, /* Blue */
{ 0xff, 0, 0xff, }, /* Magenta */
{ 0xff, 0, 0, }, /* Red */
{ 0xff, 0xff, 0, }, /* Yellow */
{ 0, 0xff, 0, }, /* Green */
{ 0, 0, 0, }, /* Black */
};
for (i = 0; i < 8; i++) {
map[ultra_chars[i]] = i;
palette[i] = ultra_colours[i];
if (fg_alpha != 0xff) {
trans_alpha[i] = fg_alpha;
}
}
num_palette = 8;
if (fg_alpha != 0xff) {
num_trans = 8;
}
/* For Ultracode, have background only if have whitespace/quiet zones */
if (pixelbuf[0] == '0' || pixelbuf[symbol->bitmap_width - 1] == '0'
|| pixelbuf[symbol->bitmap_height * (symbol->bitmap_width - 1)] == '0'
|| pixelbuf[symbol->bitmap_height * symbol->bitmap_width - 1] == '0') {
/* Check whether can re-use white */
if (bg.red == 0xff && bg.green == 0xff && bg.blue == 0xff && bg_alpha == fg_alpha) {
map['0'] = 0; /* Re-use white */
} else {
if (bg_alpha == 0xff || fg_alpha != 0xff) {
/* No alpha or have foreground alpha - add to end */
map['0'] = num_palette;
palette[num_palette++] = bg;
} else {
/* Alpha and no foreground alpha - add to front & move white to end */
map['0'] = 0;
palette[0] = bg;
map['W'] = num_palette;
palette[num_palette++] = ultra_colours[0];
}
if (bg_alpha != 0xff) {
trans_alpha[num_trans++] = bg_alpha;
}
}
}
} else {
int bg_idx = 0, fg_idx = 1;
/* Do alphas first so can swop indexes if background not alpha */
if (bg_alpha != 0xff) {
trans_alpha[num_trans++] = bg_alpha;
}
if (fg_alpha != 0xff) {
trans_alpha[num_trans++] = fg_alpha;
if (num_trans == 1) {
/* Only foreground has alpha so swop indexes - saves a byte! */
bg_idx = 1;
fg_idx = 0;
}
}
map['0'] = bg_idx;
palette[bg_idx] = bg;
map['1'] = fg_idx;
palette[fg_idx] = fg;
num_palette = 2;
}
if (num_palette <= 2) {
bit_depth = 1;
} else if (num_palette <= 16) {
bit_depth = 4;
} else {
bit_depth = 8;
} }
/* Open output file in binary mode */ /* Open output file in binary mode */
@ -177,32 +258,64 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
/* set compression */ /* set compression */
png_set_compression_level(png_ptr, 9); png_set_compression_level(png_ptr, 9);
/* Compression strategy can make a difference */
compression_strategy = guess_compression_strategy(symbol, pixelbuf);
if (compression_strategy != Z_DEFAULT_STRATEGY) {
png_set_compression_strategy(png_ptr, compression_strategy);
}
/* set Header block */ /* set Header block */
if (use_alpha) png_set_IHDR(png_ptr, info_ptr, graphic->width, graphic->height,
png_set_IHDR(png_ptr, info_ptr, graphic->width, graphic->height, bit_depth, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
8, PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
else png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
png_set_IHDR(png_ptr, info_ptr, graphic->width, graphic->height, if (num_trans) {
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, png_set_tRNS(png_ptr, info_ptr, trans_alpha, num_trans, NULL);
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); }
/* write all chunks up to (but not including) first IDAT */ /* write all chunks up to (but not including) first IDAT */
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
/* set up the transformations: for now, just pack low-bit-depth pixels
into bytes (one, two or four pixels per byte) */
png_set_packing(png_ptr);
/* Pixel Plotting */ /* Pixel Plotting */
incr = use_alpha ? 4 : 3; if (bit_depth == 1) {
for (row = 0; row < symbol->bitmap_height; row++) { for (row = 0; row < symbol->bitmap_height; row++) {
unsigned char *pb = pixelbuf + symbol->bitmap_width * row; unsigned char *pb = pixelbuf + symbol->bitmap_width * row;
image_data = outdata; unsigned char *image_data = outdata;
for (column = 0; column < symbol->bitmap_width; column++, pb++, image_data += incr) { for (column = 0; column < symbol->bitmap_width; column += 8, image_data++) {
memcpy(image_data, map[*pb], incr); unsigned char byte = 0;
for (i = 0; i < 8 && column + i < symbol->bitmap_width; i++, pb++) {
byte |= map[*pb] << (7 - i);
}
*image_data = byte;
}
/* write row contents to file */
png_write_row(png_ptr, outdata);
}
} else if (bit_depth == 4) {
for (row = 0; row < symbol->bitmap_height; row++) {
unsigned char *pb = pixelbuf + symbol->bitmap_width * row;
unsigned char *image_data = outdata;
for (column = 0; column < symbol->bitmap_width; column += 2, image_data++) {
unsigned char byte = 0;
for (i = 0; i < 2 && column + i < symbol->bitmap_width; i++, pb++) {
byte |= map[*pb] << (i * 4);
}
*image_data = byte;
}
/* write row contents to file */
png_write_row(png_ptr, outdata);
}
} else { /* Bit depth 8 */
for (row = 0; row < symbol->bitmap_height; row++) {
unsigned char *pb = pixelbuf + symbol->bitmap_width * row;
unsigned char *image_data = outdata;
for (column = 0; column < symbol->bitmap_width; column++, pb++, image_data++) {
*image_data = map[*pb];
}
/* write row contents to file */
png_write_row(png_ptr, outdata);
} }
/* write row contents to file */
png_write_row(png_ptr, outdata);
} }
/* End the file */ /* End the file */
@ -215,6 +328,7 @@ INTERNAL int png_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
} else { } else {
fclose(wpng_info.outfile); fclose(wpng_info.outfile);
} }
return 0; return 0;
} }
#endif /* NO_PNG */ #endif /* NO_PNG */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 365 B

After

Width:  |  Height:  |  Size: 178 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 520 B

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

After

Width:  |  Height:  |  Size: 235 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 366 B

After

Width:  |  Height:  |  Size: 151 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 901 B

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1002 B

After

Width:  |  Height:  |  Size: 488 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 545 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

After

Width:  |  Height:  |  Size: 236 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 299 B

After

Width:  |  Height:  |  Size: 155 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 454 B

After

Width:  |  Height:  |  Size: 219 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 745 B

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 865 B

After

Width:  |  Height:  |  Size: 392 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

After

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 470 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

After

Width:  |  Height:  |  Size: 193 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 395 B

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

After

Width:  |  Height:  |  Size: 150 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 223 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 941 B

After

Width:  |  Height:  |  Size: 442 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 910 B

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 904 B

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 424 B

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 515 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 581 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 657 B

After

Width:  |  Height:  |  Size: 239 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 B

After

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 828 B

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 882 B

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 481 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 596 B

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B

After

Width:  |  Height:  |  Size: 147 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 682 B

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

After

Width:  |  Height:  |  Size: 192 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 B

After

Width:  |  Height:  |  Size: 186 B

View File

@ -1,6 +1,6 @@
/* /*
libzint - the open source barcode library libzint - the open source barcode library
Copyright (C) 2020 Robin Stuart <rstuart114@gmail.com> Copyright (C) 2020 - 2021 Robin Stuart <rstuart114@gmail.com>
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
@ -164,7 +164,11 @@ static void test_print(int index, int generate, int debug) {
/* 29*/ { BARCODE_POSTNET, -1, -1, -1, -1, -1, -1, 0, 3.5, "", "", "12345", "", "../data/png/postnet_zip.png", "300 dpi, using 1/43in X, 300 / 43 / 2 = ~3.5 scale" }, /* 29*/ { BARCODE_POSTNET, -1, -1, -1, -1, -1, -1, 0, 3.5, "", "", "12345", "", "../data/png/postnet_zip.png", "300 dpi, using 1/43in X, 300 / 43 / 2 = ~3.5 scale" },
/* 30*/ { BARCODE_PDF417, -1, -1, -1, -1, -1, -1, 0, 0, "", "CFCECDCC", "12345", "", "../data/png/pdf417_bgalpha.png", "" }, /* 30*/ { BARCODE_PDF417, -1, -1, -1, -1, -1, -1, 0, 0, "", "CFCECDCC", "12345", "", "../data/png/pdf417_bgalpha.png", "" },
/* 31*/ { BARCODE_PDF417, -1, -1, -1, -1, -1, -1, 0, 0, "30313233", "", "12345", "", "../data/png/pdf417_fgalpha.png", "" }, /* 31*/ { BARCODE_PDF417, -1, -1, -1, -1, -1, -1, 0, 0, "30313233", "", "12345", "", "../data/png/pdf417_fgalpha.png", "" },
/* 32*/ { BARCODE_ULTRA, -1, -1, 2, -1, -1, -1, 0, 0, "0000007F", "FF000033", "12345", "", "../data/png/ultra_alpha.png", "" }, /* 32*/ { BARCODE_PDF417, -1, -1, -1, -1, -1, -1, 0, 0, "20212244", "CFCECDCC", "12345", "", "../data/png/pdf417_bgfgalpha.png", "" },
/* 33*/ { BARCODE_ULTRA, -1, -1, 2, -1, -1, -1, 0, 0, "0000007F", "FF000033", "12345", "", "../data/png/ultra_bgfgalpha.png", "" },
/* 34*/ { BARCODE_ULTRA, -1, -1, 2, -1, -1, -1, 0, 0, "", "FF000033", "12345", "", "../data/png/ultra_bgalpha.png", "" },
/* 35*/ { BARCODE_ULTRA, -1, -1, 2, -1, -1, -1, 0, 0, "0000007F", "FF0000", "12345", "", "../data/png/ultra_fgalpha.png", "" },
/* 36*/ { BARCODE_ULTRA, -1, -1, -1, -1, -1, -1, 0, 0, "0000007F", "", "12345", "", "../data/png/ultra_fgalpha_nobg.png", "" },
}; };
int data_size = ARRAY_SIZE(data); int data_size = ARRAY_SIZE(data);
@ -242,6 +246,8 @@ static void test_print(int index, int generate, int debug) {
ret = testUtilCmpPngs(symbol->outfile, data[i].expected_file); ret = testUtilCmpPngs(symbol->outfile, data[i].expected_file);
assert_zero(ret, "i:%d %s testUtilCmpPngs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, data[i].expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpPngs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, data[i].expected_file, ret);
ret = testUtilCmpBins(symbol->outfile, data[i].expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, data[i].expected_file, ret);
assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile);
} }

View File

@ -166,6 +166,8 @@ static void test_print(int index, int generate, int debug) {
} else if (strcmp(exts[j], "png") == 0) { } else if (strcmp(exts[j], "png") == 0) {
ret = testUtilCmpPngs(symbol->outfile, expected_file); ret = testUtilCmpPngs(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpPngs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpPngs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
ret = testUtilCmpBins(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpBins(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);
} else if (strcmp(exts[j], "svg") == 0) { } else if (strcmp(exts[j], "svg") == 0) {
ret = testUtilCmpSvgs(symbol->outfile, expected_file); ret = testUtilCmpSvgs(symbol->outfile, expected_file);
assert_zero(ret, "i:%d %s testUtilCmpSvgs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret); assert_zero(ret, "i:%d %s testUtilCmpSvgs(%s, %s) %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, expected_file, ret);