diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt index af3f3115..7638ee2e 100644 --- a/backend/tests/CMakeLists.txt +++ b/backend/tests/CMakeLists.txt @@ -83,6 +83,7 @@ zint_add_test(rss, test_rss) zint_add_test(sjis, test_sjis) zint_add_test(svg, test_svg) zint_add_test(telepen, test_telepen) +zint_add_test(tif, test_tif) zint_add_test(ultra, test_ultra) zint_add_test(upcean, test_upcean) zint_add_test(vector, test_vector) diff --git a/backend/tests/data/print/tif/dotcode_aim_fig7.tif b/backend/tests/data/print/tif/dotcode_aim_fig7.tif index 680d1bda..83b548fd 100644 Binary files a/backend/tests/data/print/tif/dotcode_aim_fig7.tif and b/backend/tests/data/print/tif/dotcode_aim_fig7.tif differ diff --git a/backend/tests/data/print/tif/qr_v1_m.tif b/backend/tests/data/print/tif/qr_v1_m.tif index 1c54d936..a03f5162 100644 Binary files a/backend/tests/data/print/tif/qr_v1_m.tif and b/backend/tests/data/print/tif/qr_v1_m.tif differ diff --git a/backend/tests/data/print/tif/ultracode_a.tif b/backend/tests/data/print/tif/ultracode_a.tif index e943b09e..c9449936 100644 Binary files a/backend/tests/data/print/tif/ultracode_a.tif and b/backend/tests/data/print/tif/ultracode_a.tif differ diff --git a/backend/tests/test_gif.c b/backend/tests/test_gif.c index e310be41..6a9bc3ae 100644 --- a/backend/tests/test_gif.c +++ b/backend/tests/test_gif.c @@ -81,6 +81,7 @@ static void test_pixel_plot(int index, int debug) { symbol->bitmap_width = data[i].width; symbol->bitmap_height = data[i].height; + symbol->debug |= debug; 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)); diff --git a/backend/tests/test_png.c b/backend/tests/test_png.c index d4fd75e9..d54fcf8a 100644 --- a/backend/tests/test_png.c +++ b/backend/tests/test_png.c @@ -79,6 +79,7 @@ static void test_pixel_plot(int index, int debug) { symbol->bitmap_width = data[i].width; symbol->bitmap_height = data[i].height; + symbol->debug |= debug; int size = data[i].width * data[i].height; 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)); diff --git a/backend/tests/test_tif.c b/backend/tests/test_tif.c new file mode 100644 index 00000000..ad535b13 --- /dev/null +++ b/backend/tests/test_tif.c @@ -0,0 +1,146 @@ +/* + 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 tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf); + +// For overview when debugging: ./test_tiff -f pixel_plot -d 5 +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*/ { 1, 2, "11", 0 }, + /* 3*/ { 2, 2, "10", 1 }, + /* 4*/ { 3, 1, "101", 0 }, + /* 5*/ { 1, 3, "101", 0 }, + /* 6*/ { 4, 1, "1010", 0 }, + /* 7*/ { 1, 4, "1010", 0 }, + /* 8*/ { 5, 1, "10101", 0 }, + /* 9*/ { 1, 5, "10101", 0 }, + /* 10*/ { 3, 2, "101", 1 }, + /* 11*/ { 100, 2, "10", 1 }, + /* 12*/ { 2, 100, "10", 1 }, + /* 13*/ { 3, 3, "101010101", 0 }, + /* 14*/ { 4, 3, "10", 1 }, + /* 15*/ { 3, 4, "10", 1 }, + /* 16*/ { 52, 51, "10", 1 }, // Strip Count 1, Rows Per Strip 51 (52 * 51 * 3 == 7956) + /* 17*/ { 52, 52, "10", 1 }, // Strip Count 1, Rows Per Strip 52 (52 * 52 * 3 == 8112) + /* 18*/ { 53, 52, "10", 1 }, // Strip Count 2, Rows Per Strip 51 (53 * 51 * 3 == 8109) + /* 19*/ { 53, 53, "10", 1 }, // Strip Count 2, Rows Per Strip 51 + /* 20*/ { 2730, 1, "10", 1 }, // Strip Count 1, Rows Per Strip 1 (2730 * 1 * 3 == 8190) + /* 21*/ { 1, 2730, "10", 1 }, // Strip Count 1, Rows Per Strip 2730 + /* 22*/ { 2730, 2, "10", 1 }, // Strip Count 2, Rows Per Strip 1 + /* 23*/ { 2, 2730, "10", 1 }, // Strip Count 2, Rows Per Strip 1365 (2 * 1365 * 3 == 8190) + /* 24*/ { 2730, 3, "10", 1 }, // Strip Count 3, Rows Per Strip 1 + /* 25*/ { 3, 2730, "10", 1 }, // Strip Count 3, Rows Per Strip 910 (3 * 910 * 3 == 8190) + /* 26*/ { 2731, 4, "10", 1 }, // Strip Count 4, Rows Per Strip 1 (2731 * 1 * 3 == 8193) - large rows in 1 strip, even if > 8192 + /* 27*/ { 4, 2731, "10", 1 }, // Strip Count 5, Rows Per Strip 682 (4 * 682 * 3 == 8184) + }; + int data_size = ARRAY_SIZE(data); + + char *tif = "out.tif"; + char escaped[1024]; + int escaped_size = 1024; + + char data_buf[2731 * 4 + 1]; + + 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, tif); + + symbol->bitmap_width = data[i].width; + symbol->bitmap_height = data[i].height; + symbol->debug |= debug; + + int size = data[i].width * data[i].height; + assert_nonzero(size < (int) sizeof(data_buf), "i:%d tif_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 tif_pixel_plot size %d != strlen(data_buf) %d\n", i, size, (int) strlen(data_buf)); + + symbol->bitmap = data_buf; + + ret = tif_pixel_plot(symbol, data_buf); + assert_zero(ret, "i:%d tif_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); + + if (!(debug & 8)) { + 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/tif.c b/backend/tif.c index 30caf4d8..b884cc40 100644 --- a/backend/tif.c +++ b/backend/tif.c @@ -1,4 +1,5 @@ /* tif.c - Aldus Tagged Image File Format support */ +/* TIFF Revision 6.0 https://www.adobe.io/content/dam/udp/en/open/standards/tiff/TIFF6.pdf */ /* libzint - the open source barcode library @@ -67,6 +68,9 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]); bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]); + /* TIFF Rev 6 Section 7 p.27 "Set RowsPerStrip such that the size of each strip is about 8K bytes... + * Note that extremely wide high resolution images may have rows larger than 8K bytes; in this case, + * RowsPerStrip should be 1, and the strip will be larger than 8K." */ rows_per_strip = 8192 / (symbol->bitmap_width * 3); if (rows_per_strip == 0) { rows_per_strip = 1; @@ -81,13 +85,12 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { rows_per_strip = symbol->bitmap_height; } - if (strip_count == 1) { - rows_per_strip = (rows_per_strip / 2) + 1; - strip_count++; + if (symbol->debug & ZINT_DEBUG_PRINT) { + printf("TIFF (%dx%d) Strip Count %d, Rows Per Strip %d\n", symbol->bitmap_width, symbol->bitmap_height, strip_count, rows_per_strip); } #ifndef _MSC_VER - uint32_t strip_offset[strip_count]; + uint32_t strip_offset[strip_count]; // NOLINT(clang-analyzer-core.VLASize) strip_count >= 1 uint32_t strip_bytes[strip_count]; #else strip_offset = (uint32_t*) _alloca(strip_count * sizeof(uint32_t)); @@ -201,7 +204,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { bytes_put += 3; } - if ((bytes_put + 3) >= strip_bytes[strip]) { + if (strip < strip_count && (bytes_put + 3) >= strip_bytes[strip]) { // End of strip, pad if strip length is odd if (strip_bytes[strip] % 2 == 1) { putc(0, tif_file); @@ -249,8 +252,12 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { ifd.strip_offsets.tag = 0x0111; ifd.strip_offsets.type = 4; // LONG ifd.strip_offsets.count = strip_count; - ifd.strip_offsets.offset = free_memory; - free_memory += strip_count * 4; + if (strip_count == 1) { + ifd.strip_offsets.offset = strip_offset[0]; + } else { + ifd.strip_offsets.offset = free_memory; + free_memory += strip_count * 4; + } ifd.samples_per_pixel.tag = 0x0115; ifd.samples_per_pixel.type = 3; @@ -265,8 +272,12 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { ifd.strip_byte_counts.tag = 0x0117; ifd.strip_byte_counts.type = 4; ifd.strip_byte_counts.count = strip_count; - ifd.strip_byte_counts.offset = free_memory; - free_memory += strip_count * 4; + if (strip_count == 1) { + ifd.strip_byte_counts.offset = strip_bytes[0]; + } else { + ifd.strip_byte_counts.offset = free_memory; + free_memory += strip_count * 4; + } ifd.x_resolution.tag = 0x011a; ifd.x_resolution.type = 5; @@ -298,14 +309,16 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, char *pixelbuf) { fwrite(&temp, 2, 1, tif_file); // Green Bytes fwrite(&temp, 2, 1, tif_file); // Blue Bytes - /* Strip offsets */ - for(i = 0; i < strip_count; i++) { - fwrite(&strip_offset[i], 4, 1, tif_file); - } + if (strip_count != 1) { + /* Strip offsets */ + for (i = 0; i < strip_count; i++) { + fwrite(&strip_offset[i], 4, 1, tif_file); + } - /* Strip byte lengths */ - for(i = 0; i < strip_count; i++) { - fwrite(&strip_bytes[i], 4, 1, tif_file); + /* Strip byte lengths */ + for (i = 0; i < strip_count; i++) { + fwrite(&strip_bytes[i], 4, 1, tif_file); + } } /* X Resolution */