diff --git a/backend/gif.c b/backend/gif.c index 6237c86a..238eb1b7 100644 --- a/backend/gif.c +++ b/backend/gif.c @@ -2,7 +2,7 @@ /* libzint - the open source barcode library - Copyright (C) 2009-2017 Robin Stuart + Copyright (C) 2009 - 2020 Robin Stuart Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions @@ -32,7 +32,6 @@ /* vim: set ts=4 sw=4 et : */ #include -#include #include #include "common.h" #include @@ -49,8 +48,6 @@ */ #define TRANSPARENT_INDEX (-1) -#include - typedef struct s_statestruct { unsigned char * pOut; unsigned char *pIn; @@ -67,6 +64,7 @@ typedef struct s_statestruct { unsigned char NodePix[4096]; unsigned char colourCode[10]; unsigned char colourPaletteIndex[10]; + int colourCount; } statestruct; /* Transform a Pixel to a lzw colourmap index and move to next pixel. @@ -79,11 +77,12 @@ static unsigned char NextPaletteIndex(statestruct *pState) pixelColour = *(pState->pIn); (pState->pIn)++; (pState->InLen)--; - for (colourIndex = 0;; colourIndex++) { + for (colourIndex = 0; colourIndex < pState->colourCount; colourIndex++) { if (pixelColour == pState->colourCode[colourIndex]) return pState->colourPaletteIndex[colourIndex]; } + return 0; /* Not reached */ } @@ -301,14 +300,16 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { unsigned char pixelColour; + /* Allow for overhead of 4 == code size + byte count + overflow byte + zero terminator */ + unsigned int lzoutbufSize = symbol->bitmap_height * symbol->bitmap_width + 4; #ifdef _MSC_VER char * lzwoutbuf; #endif #ifndef _MSC_VER - char lzwoutbuf[symbol->bitmap_height * symbol->bitmap_width]; + char lzwoutbuf[lzoutbufSize]; #else - lzwoutbuf = (char *) _alloca((symbol->bitmap_height * symbol->bitmap_width) * sizeof (char)); + lzwoutbuf = _alloca(lzoutbufSize); #endif /* _MSC_VER */ /* Open output file in binary mode */ @@ -444,6 +445,8 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { (State.colourPaletteIndex)[colourCount] = paletteIndex; colourCount++; } + State.colourCount = colourCount; + /* find palette bit size from palette size*/ /* 1,2 -> 1, 3,4 ->2, 5,6,7,8->3 */ @@ -563,7 +566,7 @@ INTERNAL int gif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { State.pIn = (unsigned char *) pixelbuf; State.InLen = symbol->bitmap_height * symbol->bitmap_width; State.pOut = (unsigned char *) lzwoutbuf; - State.OutLength = symbol->bitmap_height * symbol->bitmap_width; + State.OutLength = lzoutbufSize; /* call lzw encoding */ byte_out = gif_lzw(&State, paletteBitSize); diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt index bbe1d3ee..af3f3115 100644 --- a/backend/tests/CMakeLists.txt +++ b/backend/tests/CMakeLists.txt @@ -64,6 +64,7 @@ zint_add_test(eci, test_eci) zint_add_test(emf, test_emf) zint_add_test(gb18030, test_gb18030) zint_add_test(gb2312, test_gb2312) +zint_add_test(gif, test_gif) zint_add_test(gridmtx, test_gridmtx) zint_add_test(gs1, test_gs1) zint_add_test(hanxin, test_hanxin) diff --git a/backend/tests/test_gif.c b/backend/tests/test_gif.c new file mode 100644 index 00000000..e310be41 --- /dev/null +++ b/backend/tests/test_gif.c @@ -0,0 +1,124 @@ +/* + libzint - the open source barcode library + Copyright (C) 2020 Robin Stuart + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the project nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + */ +/* vim: set ts=4 sw=4 et : */ + +#include "testcommon.h" + +extern int gif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf); + +static void test_pixel_plot(int index, int debug) { + + testStart(""); + + if (!testUtilHaveIdentify()) { + testSkip("ImageMagick identify not available"); + return; + } + + int ret; + struct item { + int width; + int height; + unsigned char *pattern; + int repeat; + }; + // s/\/\*[ 0-9]*\*\//\=printf("\/*%3d*\/", line(".") - line("'<")) + struct item data[] = { + /* 0*/ { 1, 1, "1", 0 }, + /* 1*/ { 2, 1, "11", 0 }, + /* 2*/ { 3, 1, "101", 0 }, + /* 3*/ { 4, 1, "1010", 0 }, + /* 4*/ { 5, 1, "10101", 0 }, + /* 5*/ { 3, 2, "101010", 0 }, + /* 6*/ { 3, 3, "101010101", 0 }, + /* 7*/ { 8, 2, "CBMWKRYGGYRKWMBC", 0 }, + /* 8*/ { 20, 30, "WWCWBWMWRWYWGWKCCWCMCRCYCGCKBWBCBBMBRBYBGBKMWMCMBMMRMYMGMKRWRCRBRMRRYRGRKYWYCYBYMYRYYGYKGWGCGBGMGRGYGGKKWKCKBKMKRKYKGKK", 1 }, // Single LZW block, size 255 + /* 9*/ { 19, 32, "WWCWBWMWRWYWGWKCCWCMCRCYCGCKBWBCBBMBRBYBGBKMWMCMBMMRMYMGMKRWRCRBRMRRYRGRKYWYCYBYMYRYYGYKGWGCGBGMGRGYGGKKWK", 1 }, // Two LZW blocks, last size 1 + }; + int data_size = ARRAY_SIZE(data); + + char *gif = "out.gif"; + char escaped[1024]; + int escaped_size = 1024; + + char data_buf[19 * 32 + 1]; // 19 * 32 == 608 + + for (int i = 0; i < data_size; i++) { + + if (index != -1 && i != index) continue; + + struct zint_symbol *symbol = ZBarcode_Create(); + assert_nonnull(symbol, "Symbol not created\n"); + + strcpy(symbol->outfile, gif); + + symbol->bitmap_width = data[i].width; + symbol->bitmap_height = data[i].height; + + int size = data[i].width * data[i].height; + assert_nonzero(size < (int) sizeof(data_buf), "i:%d gif_pixel_plot size %d < sizeof(data_buf) %d\n", i, size, (int) sizeof(data_buf)); + + if (data[i].repeat) { + testUtilStrCpyRepeat(data_buf, data[i].pattern, size); + } else { + strcpy(data_buf, data[i].pattern); + } + assert_equal(size, (int) strlen(data_buf), "i:%d gif_pixel_plot size %d != strlen(data_buf) %d\n", i, size, (int) strlen(data_buf)); + + symbol->bitmap = data_buf; + + ret = gif_pixel_plot(symbol, data_buf); + assert_zero(ret, "i:%d gif_pixel_plot ret %d != 0 (%s)\n", i, ret, symbol->errtxt); + + ret = testUtilVerifyIdentify(symbol->outfile, debug); + assert_zero(ret, "i:%d identify %s ret %d != 0\n", i, symbol->outfile, ret); + + assert_zero(remove(symbol->outfile), "i:%d remove(%s) != 0\n", i, symbol->outfile); + + symbol->bitmap = NULL; + + ZBarcode_Delete(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 }, + }; + + testRun(argc, argv, funcs, ARRAY_SIZE(funcs)); + + testReport(); + + return 0; +} diff --git a/backend/tests/test_png.c b/backend/tests/test_png.c index dbda734f..d4fd75e9 100644 --- a/backend/tests/test_png.c +++ b/backend/tests/test_png.c @@ -66,7 +66,7 @@ static void test_pixel_plot(int index, int debug) { char escaped[1024]; int escaped_size = 1024; - char data_buf[2731 * 5 + 1]; + char data_buf[8 * 2 + 1]; for (int i = 0; i < data_size; i++) { @@ -84,14 +84,7 @@ static void test_pixel_plot(int index, int debug) { assert_nonzero(size < (int) sizeof(data_buf), "i:%d png_pixel_plot size %d < sizeof(data_buf) %d\n", i, size, (int) sizeof(data_buf)); if (data[i].repeat) { - int len = strlen(data[i].pattern); - for (int j = 0; j < size; j += len) { - memcpy(data_buf + j, data[i].pattern, len); - } - if (size % len) { - memcpy(data_buf + size - size % len, data[i].pattern, size % len); - } - data_buf[size] = '\0'; + testUtilStrCpyRepeat(data_buf, data[i].pattern, size); } else { strcpy(data_buf, data[i].pattern); } diff --git a/backend/tests/testcommon.c b/backend/tests/testcommon.c index 7f94cb1a..4b92dbc3 100644 --- a/backend/tests/testcommon.c +++ b/backend/tests/testcommon.c @@ -545,6 +545,17 @@ char *testUtilReadCSVField(char *buffer, char *field, int field_size) { return b; } +void testUtilStrCpyRepeat(char *buffer, char *repeat, int size) { + int i; + int len = strlen(repeat); + int max = size - len; + for (i = 0; i < max; i += len) { + memcpy(buffer + i, repeat, len); + } + memcpy(buffer + i, repeat, size - i); + buffer[size] = '\0'; +} + int testUtilSymbolCmp(const struct zint_symbol *a, const struct zint_symbol *b) { if (a->symbology != b->symbology) { return 1; diff --git a/backend/tests/testcommon.h b/backend/tests/testcommon.h index 7efee824..9243ef70 100644 --- a/backend/tests/testcommon.h +++ b/backend/tests/testcommon.h @@ -79,6 +79,7 @@ char *testUtilOption3Name(int option_3); int testUtilDAFTConvert(const struct zint_symbol *symbol, char *buffer, int buffer_size); char *testUtilEscape(char *buffer, int length, char *escaped, int escaped_size); char *testUtilReadCSVField(char *buffer, char *field, int field_size); +void testUtilStrCpyRepeat(char *buffer, char *repeat, int size); int testUtilSymbolCmp(const struct zint_symbol *a, const struct zint_symbol *b); struct zint_vector *testUtilVectorCpy(const struct zint_vector *in); int testUtilVectorCmp(const struct zint_vector *a, const struct zint_vector *b);