mirror of
https://github.com/zint/zint
synced 2024-11-16 20:57:25 +13:00
gif.c: use malloc instead of alloca for LZW buffer as fails for large scale
This commit is contained in:
parent
537990e32e
commit
5766b39845
@ -41,7 +41,8 @@
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#define SSET "0123456789ABCDEF"
|
||||
/* Limit initial ZLW buffer size to this in expectation that compressed data will fit for typical scalings */
|
||||
#define GIF_ZLW_PAGE_SIZE 0x100000 /* Megabyte */
|
||||
|
||||
typedef struct s_statestruct {
|
||||
unsigned char *pOut;
|
||||
@ -95,8 +96,15 @@ static int BufferNextByte(statestruct *pState) {
|
||||
pState->OutByteCountPos = pState->OutPosCur;
|
||||
(pState->OutPosCur)++;
|
||||
}
|
||||
if (pState->OutPosCur >= pState->OutLength)
|
||||
if (pState->OutPosCur >= pState->OutLength) {
|
||||
unsigned char *pOut;
|
||||
pState->OutLength += GIF_ZLW_PAGE_SIZE;
|
||||
/* Note pState->pOut not free()d by realloc() on failure */
|
||||
if (!(pOut = (unsigned char *) realloc(pState->pOut, pState->OutLength))) {
|
||||
return 1;
|
||||
}
|
||||
pState->pOut = pOut;
|
||||
}
|
||||
|
||||
(pState->pOut)[pState->OutPosCur] = 0x00;
|
||||
return 0;
|
||||
@ -301,15 +309,9 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
|
||||
/* Allow for overhead of 4 == code size + byte count + overflow byte + zero terminator */
|
||||
unsigned int lzoutbufSize = bitmapSize + 4;
|
||||
#ifdef _MSC_VER
|
||||
char *lzwoutbuf;
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_VER
|
||||
char lzwoutbuf[lzoutbufSize];
|
||||
#else
|
||||
lzwoutbuf = (char *) _alloca(lzoutbufSize);
|
||||
#endif /* _MSC_VER */
|
||||
if (lzoutbufSize > GIF_ZLW_PAGE_SIZE) {
|
||||
lzoutbufSize = GIF_ZLW_PAGE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Build a table of the used palette items.
|
||||
@ -582,19 +584,27 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
/* prepare state array */
|
||||
State.pIn = pixelbuf;
|
||||
State.InLen = bitmapSize;
|
||||
State.pOut = (unsigned char *) lzwoutbuf;
|
||||
if (!(State.pOut = (unsigned char *) malloc(lzoutbufSize))) {
|
||||
if (!output_to_stdout) {
|
||||
fclose(gif_file);
|
||||
}
|
||||
strcpy(symbol->errtxt, "614: Insufficient memory for LZW buffer");
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
State.OutLength = lzoutbufSize;
|
||||
|
||||
/* call lzw encoding */
|
||||
byte_out = gif_lzw(&State, paletteBitSize);
|
||||
if (byte_out <= 0) {
|
||||
free(State.pOut);
|
||||
if (!output_to_stdout) {
|
||||
fclose(gif_file);
|
||||
}
|
||||
strcpy(symbol->errtxt, "613: Insufficient memory for LZW buffer");
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
fwrite(lzwoutbuf, byte_out, 1, gif_file);
|
||||
fwrite((const char *) State.pOut, byte_out, 1, gif_file);
|
||||
free(State.pOut);
|
||||
|
||||
/* GIF terminator */
|
||||
fputc('\x3b', gif_file);
|
||||
|
BIN
backend/tests/data/gif/itf14_height61.8_bind4_wsp24_3.gif
Normal file
BIN
backend/tests/data/gif/itf14_height61.8_bind4_wsp24_3.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
@ -129,37 +129,40 @@ static void test_print(int index, int generate, int debug) {
|
||||
int whitespace_height;
|
||||
int option_1;
|
||||
int option_2;
|
||||
float height;
|
||||
float scale;
|
||||
float dot_size;
|
||||
char *fgcolour;
|
||||
char *bgcolour;
|
||||
char *data;
|
||||
char *expected_file;
|
||||
char *comment;
|
||||
};
|
||||
struct item data[] = {
|
||||
/* 0*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, "", "", "12", "dotcode_1.0.gif" },
|
||||
/* 1*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0.1, "", "", "12", "dotcode_1.0_ds0.1.gif" },
|
||||
/* 2*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 1.1, "", "", "12", "dotcode_1.0_ds1.1.gif" },
|
||||
/* 3*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 1.5, 0, "", "", "12", "dotcode_1.5.gif" },
|
||||
/* 4*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 1.5, 0.4, "", "", "12", "dotcode_1.5_ds0.4.gif" },
|
||||
/* 5*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 1.5, 1.1, "", "", "12", "dotcode_1.5_ds1.1.gif" },
|
||||
/* 6*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 1.5, 2.1, "", "", "12", "dotcode_1.5_ds2.1.gif" },
|
||||
/* 7*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 2, 0, "", "", "12", "dotcode_2.0.gif" },
|
||||
/* 8*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 2, 0.9, "", "", "12", "dotcode_2.0_ds0.9.gif" },
|
||||
/* 9*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 2, 1.1, "", "", "12", "dotcode_2.0_ds1.1.gif" },
|
||||
/* 10*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 3, 0, "", "", "12", "dotcode_3.0.gif" },
|
||||
/* 11*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 3, 0.4, "", "", "12", "dotcode_3.0_ds0.4.gif" },
|
||||
/* 12*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 3, 1.1, "", "", "12", "dotcode_3.0_ds1.1.gif" },
|
||||
/* 13*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 3.5, 0, "", "", "12", "dotcode_3.5.gif" },
|
||||
/* 14*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 3.5, 0.4, "", "", "12", "dotcode_3.5_ds0.4.gif" },
|
||||
/* 15*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 3.5, 1.1, "", "", "12", "dotcode_3.5_ds1.1.gif" },
|
||||
/* 16*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 5, 0, "", "", "12", "dotcode_5.0.gif" },
|
||||
/* 17*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 5, 0.2, "", "", "12", "dotcode_5.0_ds0.2.gif" },
|
||||
/* 18*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 5, 1.1, "", "", "12", "dotcode_5.0_ds1.1.gif" },
|
||||
/* 19*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 5, 1.7, "", "", "12", "dotcode_5.0_ds1.7.gif" },
|
||||
/* 20*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, "2674C344", "FDFFC2CC", "12", "dotcode_bgfgalpha.gif" },
|
||||
/* 21*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, "00000000", "FFFFFF00", "12", "dotcode_bgfgtrans.gif" },
|
||||
/* 22*/ { BARCODE_ULTRA, 1, BARCODE_BOX, 1, 1, -1, -1, 0, 0, "0000FF", "FF0000", "12", "ultra_fgbg_hvwsp1_box1.gif" },
|
||||
/* 0*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, 0, "", "", "12", "dotcode_1.0.gif", "" },
|
||||
/* 1*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, 0.1, "", "", "12", "dotcode_1.0_ds0.1.gif", "" },
|
||||
/* 2*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, 1.1, "", "", "12", "dotcode_1.0_ds1.1.gif", "" },
|
||||
/* 3*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 1.5, 0, "", "", "12", "dotcode_1.5.gif", "" },
|
||||
/* 4*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 1.5, 0.4, "", "", "12", "dotcode_1.5_ds0.4.gif", "" },
|
||||
/* 5*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 1.5, 1.1, "", "", "12", "dotcode_1.5_ds1.1.gif", "" },
|
||||
/* 6*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 1.5, 2.1, "", "", "12", "dotcode_1.5_ds2.1.gif", "" },
|
||||
/* 7*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 2, 0, "", "", "12", "dotcode_2.0.gif", "" },
|
||||
/* 8*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 2, 0.9, "", "", "12", "dotcode_2.0_ds0.9.gif", "" },
|
||||
/* 9*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 2, 1.1, "", "", "12", "dotcode_2.0_ds1.1.gif", "" },
|
||||
/* 10*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 3, 0, "", "", "12", "dotcode_3.0.gif", "" },
|
||||
/* 11*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 3, 0.4, "", "", "12", "dotcode_3.0_ds0.4.gif", "" },
|
||||
/* 12*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 3, 1.1, "", "", "12", "dotcode_3.0_ds1.1.gif", "" },
|
||||
/* 13*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 3.5, 0, "", "", "12", "dotcode_3.5.gif", "" },
|
||||
/* 14*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 3.5, 0.4, "", "", "12", "dotcode_3.5_ds0.4.gif", "" },
|
||||
/* 15*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 3.5, 1.1, "", "", "12", "dotcode_3.5_ds1.1.gif", "" },
|
||||
/* 16*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 5, 0, "", "", "12", "dotcode_5.0.gif", "" },
|
||||
/* 17*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 5, 0.2, "", "", "12", "dotcode_5.0_ds0.2.gif", "" },
|
||||
/* 18*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 5, 1.1, "", "", "12", "dotcode_5.0_ds1.1.gif", "" },
|
||||
/* 19*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 5, 1.7, "", "", "12", "dotcode_5.0_ds1.7.gif", "" },
|
||||
/* 20*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, 0, "2674C344", "FDFFC2CC", "12", "dotcode_bgfgalpha.gif", "" },
|
||||
/* 21*/ { BARCODE_DOTCODE, -1, -1, -1, -1, -1, -1, 0, 0, 0, "00000000", "FFFFFF00", "12", "dotcode_bgfgtrans.gif", "" },
|
||||
/* 22*/ { BARCODE_ULTRA, 1, BARCODE_BOX, 1, 1, -1, -1, 0, 0, 0, "0000FF", "FF0000", "12", "ultra_fgbg_hvwsp1_box1.gif", "" },
|
||||
/* 23*/ { BARCODE_ITF14, 4, BARCODE_BIND, 24, -1, -1, -1, 61.8, 3, 0, "", "", "0501054800395", "itf14_height61.8_bind4_wsp24_3.gif", "#204 ARM-Cortex crash" },
|
||||
};
|
||||
int data_size = ARRAY_SIZE(data);
|
||||
int i, length, ret;
|
||||
@ -201,6 +204,9 @@ static void test_print(int index, int generate, int debug) {
|
||||
if (data[i].whitespace_height != -1) {
|
||||
symbol->whitespace_height = data[i].whitespace_height;
|
||||
}
|
||||
if (data[i].height) {
|
||||
symbol->height = data[i].height;
|
||||
}
|
||||
if (data[i].scale) {
|
||||
symbol->scale = data[i].scale;
|
||||
}
|
||||
@ -224,11 +230,11 @@ static void test_print(int index, int generate, int debug) {
|
||||
assert_nonzero(testUtilDataPath(expected_file, sizeof(expected_file), data_dir, data[i].expected_file), "i:%d testUtilDataPath == 0\n", i);
|
||||
|
||||
if (generate) {
|
||||
printf(" /*%3d*/ { %s, %d, %s, %d, %d, %d, %d, %.5g, %.5g, \"%s\", \"%s\", \"%s\", \"%s\" },\n",
|
||||
printf(" /*%3d*/ { %s, %d, %s, %d, %d, %d, %d, %.5g, %.5g, %.5g, \"%s\", \"%s\", \"%s\", \"%s\", \"%s\" },\n",
|
||||
i, testUtilBarcodeName(data[i].symbology), data[i].border_width, testUtilOutputOptionsName(data[i].output_options),
|
||||
data[i].whitespace_width, data[i].whitespace_height,
|
||||
data[i].option_1, data[i].option_2, data[i].scale, data[i].dot_size, data[i].fgcolour, data[i].bgcolour,
|
||||
testUtilEscape(data[i].data, length, escaped, escaped_size), data[i].expected_file);
|
||||
data[i].option_1, data[i].option_2, data[i].height, data[i].scale, data[i].dot_size, data[i].fgcolour, data[i].bgcolour,
|
||||
testUtilEscape(data[i].data, length, escaped, escaped_size), data[i].expected_file, data[i].comment);
|
||||
ret = testUtilRename(symbol->outfile, expected_file);
|
||||
assert_zero(ret, "i:%d testUtilRename(%s, %s) ret %d != 0\n", i, symbol->outfile, expected_file, ret);
|
||||
if (have_identify) {
|
||||
@ -275,12 +281,43 @@ static void test_outfile(void) {
|
||||
testFinish();
|
||||
}
|
||||
|
||||
static void test_large_scale(int debug) {
|
||||
int length, ret;
|
||||
struct zint_symbol symbol = {0};
|
||||
char data[] = "1";
|
||||
|
||||
testStart("test_large_scale");
|
||||
|
||||
length = (int) strlen(data);
|
||||
|
||||
symbol.symbology = BARCODE_ITF14;
|
||||
strcpy(symbol.fgcolour, "000000");
|
||||
strcpy(symbol.bgcolour, "ffffff");
|
||||
strcpy(symbol.outfile, "out.gif");
|
||||
// X-dimension 0.27mm * 95 = 25.65 ~ 25 pixels so 12.5 gives 95 dpmm (2400 dpi)
|
||||
symbol.scale = 12.5f; // 70.0f would cause re-alloc as LZW > 1MB but very slow
|
||||
symbol.dot_size = 4.0f / 5.0f;
|
||||
|
||||
ret = ZBarcode_Encode_and_Print(&symbol, (unsigned char *) data, length, 0 /*rotate_angle*/);
|
||||
assert_zero(ret, "%s ZBarcode_Encode_and_Print ret %d != 0 %s\n", testUtilBarcodeName(symbol.symbology), ret, symbol.errtxt);
|
||||
|
||||
if (!(debug & ZINT_DEBUG_TEST_KEEP_OUTFILE)) { /* -d 64 */
|
||||
// 129.1 kB file manually inspected and checked (1.1 MB file for scale 70.0f also checked)
|
||||
assert_zero(remove(symbol.outfile), "remove(%s) != 0\n", symbol.outfile);
|
||||
}
|
||||
|
||||
ZBarcode_Clear(&symbol);
|
||||
|
||||
testFinish();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
testFunction funcs[] = { /* name, func, has_index, has_generate, has_debug */
|
||||
{ "test_pixel_plot", test_pixel_plot, 1, 0, 1 },
|
||||
{ "test_print", test_print, 1, 1, 1 },
|
||||
{ "test_outfile", test_outfile, 0, 0, 0 },
|
||||
{ "test_large_scale", test_large_scale, 0, 0, 1 },
|
||||
};
|
||||
|
||||
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
|
||||
|
Loading…
Reference in New Issue
Block a user