mirror of
https://github.com/zint/zint
synced 2024-11-16 20:57:25 +13:00
tif.c: Use palette/bilevel/LZW to reduce file size, alpha/CMYK support
This commit is contained in:
parent
badd9e59ad
commit
2c053c325a
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
backend/tests/data/tif/aztec_v32_fg.tif
Normal file
BIN
backend/tests/data/tif/aztec_v32_fg.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/code128_bgalpha.tif
Normal file
BIN
backend/tests/data/tif/code128_bgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/code128_cmyk.tif
Normal file
BIN
backend/tests/data/tif/code128_cmyk.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/code128_cmyk_fgbgalpha.tif
Normal file
BIN
backend/tests/data/tif/code128_cmyk_fgbgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/code128_fgalpha.tif
Normal file
BIN
backend/tests/data/tif/code128_fgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/code128_fgbg.tif
Normal file
BIN
backend/tests/data/tif/code128_fgbg.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/code128_fgbgalpha.tif
Normal file
BIN
backend/tests/data/tif/code128_fgbgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/daft_scale0.5.tif
Normal file
BIN
backend/tests/data/tif/daft_scale0.5.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/hanxin_v84_l4_scale2.tif
Normal file
BIN
backend/tests/data/tif/hanxin_v84_l4_scale2.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/ultra_bgalpha.tif
Normal file
BIN
backend/tests/data/tif/ultra_bgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/ultra_bgalpha_nofg.tif
Normal file
BIN
backend/tests/data/tif/ultra_bgalpha_nofg.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/ultra_fgalpha.tif
Normal file
BIN
backend/tests/data/tif/ultra_fgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/ultra_fgalpha_nobg.tif
Normal file
BIN
backend/tests/data/tif/ultra_fgalpha_nobg.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/ultra_fgbgalpha.tif
Normal file
BIN
backend/tests/data/tif/ultra_fgbgalpha.tif
Normal file
Binary file not shown.
BIN
backend/tests/data/tif/ultra_odd.tif
Normal file
BIN
backend/tests/data/tif/ultra_odd.tif
Normal file
Binary file not shown.
@ -30,6 +30,7 @@
|
||||
/* vim: set ts=4 sw=4 et : */
|
||||
|
||||
#include "testcommon.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf);
|
||||
|
||||
@ -68,24 +69,24 @@ static void test_pixel_plot(int index, int debug) {
|
||||
/* 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)
|
||||
/* 16*/ { 45, 44, "10", 1 }, // Strip Count 1, Rows Per Strip 44 (45 * 44 * 4 == 7920)
|
||||
/* 17*/ { 45, 45, "10", 1 }, // Strip Count 1, Rows Per Strip 45 (45 * 45 * 4 == 8100)
|
||||
/* 18*/ { 46, 45, "10", 1 }, // Strip Count 2, Rows Per Strip 44 (46 * 45 * 4 == 8280)
|
||||
/* 19*/ { 46, 46, "10", 1 }, // Strip Count 2, Rows Per Strip 44
|
||||
/* 20*/ { 2048, 1, "10", 1 }, // Strip Count 1, Rows Per Strip 1 (2048 * 4 == 8192)
|
||||
/* 21*/ { 1, 2048, "10", 1 }, // Strip Count 1, Rows Per Strip 2048
|
||||
/* 22*/ { 2048, 2, "10", 1 }, // Strip Count 2, Rows Per Strip 1
|
||||
/* 23*/ { 2, 2048, "10", 1 }, // Strip Count 2, Rows Per Strip 1024 (2 * 1024 * 4 == 8192)
|
||||
/* 24*/ { 2048, 3, "10", 1 }, // Strip Count 3, Rows Per Strip 1
|
||||
/* 25*/ { 3, 2048, "10", 1 }, // Strip Count 4, Rows Per Strip 682 ((3 * 682 + 2) * 4 == 8192)
|
||||
/* 26*/ { 2049, 4, "10", 1 }, // Strip Count 4, Rows Per Strip 1 (2049 * 1 * 4 == 8196) - large rows in 1 strip, even if > 8192
|
||||
/* 27*/ { 4, 2049, "10", 1 }, // Strip Count 5, Rows Per Strip 512 ((4 * 512 + 1) * 4 == 8196)
|
||||
};
|
||||
int data_size = ARRAY_SIZE(data);
|
||||
|
||||
char *tif = "out.tif";
|
||||
|
||||
char data_buf[2731 * 4 + 1];
|
||||
char data_buf[65536];
|
||||
|
||||
for (int i = 0; i < data_size; i++) {
|
||||
|
||||
@ -98,10 +99,11 @@ static void test_pixel_plot(int index, int debug) {
|
||||
|
||||
symbol->bitmap_width = data[i].width;
|
||||
symbol->bitmap_height = data[i].height;
|
||||
strcpy(symbol->bgcolour, "FFFFFFEE"); // Use alpha background to force RGB
|
||||
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));
|
||||
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);
|
||||
@ -130,10 +132,138 @@ static void test_pixel_plot(int index, int debug) {
|
||||
testFinish();
|
||||
}
|
||||
|
||||
static void test_print(int index, int generate, int debug) {
|
||||
|
||||
testStart("");
|
||||
|
||||
int have_identify = testUtilHaveIdentify();
|
||||
|
||||
int ret;
|
||||
struct item {
|
||||
int symbology;
|
||||
int input_mode;
|
||||
int border_width;
|
||||
int output_options;
|
||||
int whitespace_width;
|
||||
int show_hrt;
|
||||
int option_1;
|
||||
int option_2;
|
||||
int height;
|
||||
float scale;
|
||||
char *fgcolour;
|
||||
char *bgcolour;
|
||||
char *data;
|
||||
char *composite;
|
||||
char *expected_file;
|
||||
char *comment;
|
||||
};
|
||||
struct item data[] = {
|
||||
/* 0*/ { BARCODE_CODE128, -1, -1, -1, 1, -1, -1, -1, 0, 0, "112233", "EEDDCC", "A", "", "../data/tif/code128_fgbg.tif", "" },
|
||||
/* 1*/ { BARCODE_CODE128, -1, -1, -1, 1, -1, -1, -1, 0, 0, "C00000", "FEDCBACC", "A", "", "../data/tif/code128_bgalpha.tif", "" },
|
||||
/* 2*/ { BARCODE_CODE128, -1, -1, -1, 1, -1, -1, -1, 0, 0, "00000099", "FEDCBA", "A", "", "../data/tif/code128_fgalpha.tif", "" },
|
||||
/* 3*/ { BARCODE_CODE128, -1, -1, -1, 1, -1, -1, -1, 0, 0, "00000099", "FEDCBACC", "A", "", "../data/tif/code128_fgbgalpha.tif", "" },
|
||||
/* 4*/ { BARCODE_CODE128, -1, -1, CMYK_COLOUR, 1, -1, -1, -1, 0, 0, "C00000", "FEDCBA", "A", "", "../data/tif/code128_cmyk.tif", "" },
|
||||
/* 5*/ { BARCODE_CODE128, -1, -1, CMYK_COLOUR, 1, -1, -1, -1, 0, 0, "C0000099", "FEDCBACC", "A", "", "../data/tif/code128_cmyk_fgbgalpha.tif", "" },
|
||||
/* 6*/ { BARCODE_ULTRA, -1, -1, -1, 1, -1, -1, -1, 0, 0, "C00000", "FEDCBACC", "1234", "", "../data/tif/ultra_bgalpha.tif", "" },
|
||||
/* 7*/ { BARCODE_ULTRA, -1, -1, -1, 1, -1, -1, -1, 0, 0, "000000BB", "FEDCBA", "1234", "", "../data/tif/ultra_fgalpha.tif", "" },
|
||||
/* 8*/ { BARCODE_ULTRA, -1, -1, -1, 1, -1, -1, -1, 0, 0, "000000BB", "FEDCBACC", "1234", "", "../data/tif/ultra_fgbgalpha.tif", "" },
|
||||
/* 9*/ { BARCODE_ULTRA, -1, -1, -1, 1, -1, -1, -1, 0, 0, "000000BB", "", "1234", "", "../data/tif/ultra_fgalpha_nobg.tif", "" },
|
||||
/* 10*/ { BARCODE_ULTRA, -1, -1, -1, 1, -1, -1, -1, 0, 0, "", "FEDCBACC", "1234", "", "../data/tif/ultra_bgalpha_nofg.tif", "" },
|
||||
/* 11*/ { BARCODE_ULTRA, -1, -1, -1, -1, -1, -1, -1, 0, 0.5f, "", "", "1", "", "../data/tif/ultra_odd.tif", "" },
|
||||
/* 12*/ { BARCODE_HANXIN, UNICODE_MODE, -1, -1, -1, -1, 4, 84, 0, 2, "", "", "1", "", "../data/tif/hanxin_v84_l4_scale2.tif", "" },
|
||||
/* 13*/ { BARCODE_AZTEC, -1, -1, -1, -1, -1, -1, 32, 0, 0, "4BE055", "", "1", "", "../data/tif/aztec_v32_fg.tif", "" },
|
||||
/* 14*/ { BARCODE_DAFT, -1, -1, -1, -1, -1, -1, -1, 1, 0.5f, "", "", "F", "", "../data/tif/daft_scale0.5.tif", "" },
|
||||
};
|
||||
int data_size = ARRAY_SIZE(data);
|
||||
|
||||
char *data_dir = "../data/tif";
|
||||
char *tif = "out.tif";
|
||||
char escaped[1024];
|
||||
int escaped_size = 1024;
|
||||
char *text;
|
||||
|
||||
if (generate) {
|
||||
if (!testUtilExists(data_dir)) {
|
||||
ret = mkdir(data_dir, 0755);
|
||||
assert_zero(ret, "mkdir(%s) ret %d != 0\n", data_dir, ret);
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
int length = testUtilSetSymbol(symbol, data[i].symbology, data[i].input_mode, -1 /*eci*/, data[i].option_1, data[i].option_2, -1, data[i].output_options, data[i].data, -1, debug);
|
||||
if (data[i].show_hrt != -1) {
|
||||
symbol->show_hrt = data[i].show_hrt;
|
||||
}
|
||||
if (data[i].height) {
|
||||
symbol->height = data[i].height;
|
||||
}
|
||||
if (data[i].scale) {
|
||||
symbol->scale = data[i].scale;
|
||||
}
|
||||
if (data[i].border_width != -1) {
|
||||
symbol->border_width = data[i].border_width;
|
||||
}
|
||||
if (data[i].whitespace_width != -1) {
|
||||
symbol->whitespace_width = data[i].whitespace_width;
|
||||
}
|
||||
if (*data[i].fgcolour) {
|
||||
strcpy(symbol->fgcolour, data[i].fgcolour);
|
||||
}
|
||||
if (*data[i].bgcolour) {
|
||||
strcpy(symbol->bgcolour, data[i].bgcolour);
|
||||
}
|
||||
if (strlen(data[i].composite)) {
|
||||
text = data[i].composite;
|
||||
strcpy(symbol->primary, data[i].data);
|
||||
} else {
|
||||
text = data[i].data;
|
||||
}
|
||||
int text_length = strlen(text);
|
||||
|
||||
ret = ZBarcode_Encode(symbol, (unsigned char *) text, text_length);
|
||||
assert_zero(ret, "i:%d %s ZBarcode_Encode ret %d != 0 %s\n", i, testUtilBarcodeName(data[i].symbology), ret, symbol->errtxt);
|
||||
|
||||
strcpy(symbol->outfile, tif);
|
||||
ret = ZBarcode_Print(symbol, 0);
|
||||
assert_zero(ret, "i:%d %s ZBarcode_Print %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), symbol->outfile, ret);
|
||||
|
||||
if (generate) {
|
||||
printf(" /*%3d*/ { %s, %s, %d, %s, %d, %d, %d, %d, %d, %.5g, \"%s\",\"%s\", \"%s\", \"%s\", \"%s\", \"%s\" },\n",
|
||||
i, testUtilBarcodeName(data[i].symbology), testUtilInputModeName(data[i].input_mode), data[i].border_width, testUtilOutputOptionsName(data[i].output_options),
|
||||
data[i].whitespace_width, data[i].show_hrt, data[i].option_1, data[i].option_2, data[i].height, data[i].scale, data[i].fgcolour, data[i].bgcolour,
|
||||
testUtilEscape(data[i].data, length, escaped, escaped_size), data[i].composite, data[i].expected_file, data[i].comment);
|
||||
ret = rename(symbol->outfile, data[i].expected_file);
|
||||
assert_zero(ret, "i:%d rename(%s, %s) ret %d != 0\n", i, symbol->outfile, data[i].expected_file, ret);
|
||||
if (have_identify) {
|
||||
ret = testUtilVerifyIdentify(data[i].expected_file, debug);
|
||||
assert_zero(ret, "i:%d %s identify %s ret %d != 0\n", i, testUtilBarcodeName(data[i].symbology), data[i].expected_file, ret);
|
||||
}
|
||||
} else {
|
||||
assert_nonzero(testUtilExists(symbol->outfile), "i:%d testUtilExists(%s) == 0\n", i, symbol->outfile);
|
||||
assert_nonzero(testUtilExists(data[i].expected_file), "i:%d testUtilExists(%s) == 0\n", i, data[i].expected_file);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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 },
|
||||
{ "test_print", test_print, 1, 1, 1 },
|
||||
};
|
||||
|
||||
testRun(argc, argv, funcs, ARRAY_SIZE(funcs));
|
||||
|
591
backend/tif.c
591
backend/tif.c
@ -3,7 +3,7 @@
|
||||
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2016 - 2020 Robin Stuart <rstuart114@gmail.com>
|
||||
Copyright (C) 2016 - 2021 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -35,43 +35,238 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include "common.h"
|
||||
#include "tif.h"
|
||||
#include "tif_lzw.h"
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
#include <endian.h>
|
||||
# if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define TIF_BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* PhotometricInterpretation */
|
||||
#define TIF_PMI_WHITEISZERO 0
|
||||
#define TIF_PMI_BLACKISZERO 1
|
||||
#define TIF_PMI_RGB 2
|
||||
#define TIF_PMI_PALETTE_COLOR 3
|
||||
#define TIF_PMI_SEPARATED 5 /* CMYK */
|
||||
|
||||
/* Compression */
|
||||
#define TIF_NO_COMPRESSION 1
|
||||
#define TIF_LZW 5
|
||||
|
||||
static void to_color_map(unsigned char rgb[4], tiff_color_t *color_map_entry) {
|
||||
color_map_entry->red = (rgb[0] << 8) | rgb[0];
|
||||
color_map_entry->green = (rgb[1] << 8) | rgb[1];
|
||||
color_map_entry->blue = (rgb[2] << 8) | rgb[2];
|
||||
}
|
||||
|
||||
static void to_cmyk(unsigned char rgb[3], unsigned char alpha, unsigned char *cmyk) {
|
||||
unsigned char max = rgb[0];
|
||||
if (rgb[1] > max) {
|
||||
max = rgb[1];
|
||||
}
|
||||
if (rgb[2] > max) {
|
||||
max = rgb[2];
|
||||
}
|
||||
cmyk[0] = max - rgb[0];
|
||||
cmyk[1] = max - rgb[1];
|
||||
cmyk[2] = max - rgb[2];
|
||||
cmyk[3] = 0xff - max;
|
||||
cmyk[4] = alpha;
|
||||
|
||||
}
|
||||
|
||||
INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf) {
|
||||
int fgred, fggrn, fgblu, bgred, bggrn, bgblu;
|
||||
unsigned char fg[4], bg[4];
|
||||
int i;
|
||||
int pmi; /* PhotometricInterpretation */
|
||||
int rows_per_strip, strip_count;
|
||||
unsigned int free_memory;
|
||||
int rows_last_strip;
|
||||
int bytes_per_strip;
|
||||
uint16_t bits_per_sample;
|
||||
int samples_per_pixel;
|
||||
int pixels_per_sample;
|
||||
unsigned char map[128];
|
||||
tiff_color_t color_map[256] = {0};
|
||||
unsigned char palette[32][5];
|
||||
int color_map_size = 0;
|
||||
int extra_samples = 0;
|
||||
uint32_t free_memory;
|
||||
int row, column, strip;
|
||||
int strip_row;
|
||||
unsigned int bytes_put;
|
||||
long total_bytes_put;
|
||||
FILE *tif_file;
|
||||
unsigned char *pb;
|
||||
int compression = TIF_NO_COMPRESSION;
|
||||
tif_lzw_state lzw_state;
|
||||
long file_pos;
|
||||
#ifdef _MSC_VER
|
||||
uint32_t* strip_offset;
|
||||
uint32_t* strip_bytes;
|
||||
unsigned char *strip_buf;
|
||||
#endif
|
||||
|
||||
tiff_header_t header;
|
||||
tiff_ifd_t ifd;
|
||||
uint16_t temp;
|
||||
uint16_t entries = 0;
|
||||
tiff_tag_t tags[20];
|
||||
uint32_t offset = 0;
|
||||
int update_offsets[20];
|
||||
int offsets = 0;
|
||||
int ifd_size;
|
||||
uint32_t temp32;
|
||||
|
||||
fgred = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
|
||||
fggrn = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
|
||||
fgblu = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
|
||||
bgred = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
|
||||
bggrn = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
|
||||
bgblu = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
|
||||
fg[0] = (16 * ctoi(symbol->fgcolour[0])) + ctoi(symbol->fgcolour[1]);
|
||||
fg[1] = (16 * ctoi(symbol->fgcolour[2])) + ctoi(symbol->fgcolour[3]);
|
||||
fg[2] = (16 * ctoi(symbol->fgcolour[4])) + ctoi(symbol->fgcolour[5]);
|
||||
bg[0] = (16 * ctoi(symbol->bgcolour[0])) + ctoi(symbol->bgcolour[1]);
|
||||
bg[1] = (16 * ctoi(symbol->bgcolour[2])) + ctoi(symbol->bgcolour[3]);
|
||||
bg[2] = (16 * ctoi(symbol->bgcolour[4])) + ctoi(symbol->bgcolour[5]);
|
||||
|
||||
if (strlen(symbol->fgcolour) > 6) {
|
||||
fg[3] = (16 * ctoi(symbol->fgcolour[6])) + ctoi(symbol->fgcolour[7]);
|
||||
} else {
|
||||
fg[3] = 0xff;
|
||||
}
|
||||
|
||||
if (strlen(symbol->bgcolour) > 6) {
|
||||
bg[3] = (16 * ctoi(symbol->bgcolour[6])) + ctoi(symbol->bgcolour[7]);
|
||||
} else {
|
||||
bg[3] = 0xff;
|
||||
}
|
||||
|
||||
if (symbol->symbology == BARCODE_ULTRA) {
|
||||
static const int ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' };
|
||||
static unsigned char ultra_rgbs[8][3] = {
|
||||
{ 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 */
|
||||
};
|
||||
|
||||
if (symbol->output_options & CMYK_COLOUR) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
map[ultra_chars[i]] = i;
|
||||
to_cmyk(ultra_rgbs[i], fg[3], palette[i]);
|
||||
}
|
||||
map['0'] = 8;
|
||||
to_cmyk(bg, bg[3], palette[8]);
|
||||
map['1'] = 9;
|
||||
to_cmyk(fg, fg[3], palette[9]);
|
||||
|
||||
pmi = TIF_PMI_SEPARATED;
|
||||
bits_per_sample = 8;
|
||||
if (fg[3] == 0xff && bg[3] == 0xff) { /* If no alpha */
|
||||
samples_per_pixel = 4;
|
||||
} else {
|
||||
samples_per_pixel = 5;
|
||||
extra_samples = 1; /* Associated alpha */
|
||||
}
|
||||
pixels_per_sample = 1;
|
||||
} else {
|
||||
for (i = 0; i < 8; i++) {
|
||||
map[ultra_chars[i]] = i;
|
||||
memcpy(palette[i], ultra_rgbs[i], 3);
|
||||
palette[i][3] = fg[3];
|
||||
}
|
||||
map['0'] = 8;
|
||||
memcpy(palette[8], bg, 4);
|
||||
map['1'] = 9;
|
||||
memcpy(palette[9], fg, 4);
|
||||
|
||||
if (fg[3] == 0xff && bg[3] == 0xff) { /* If no alpha */
|
||||
pmi = TIF_PMI_PALETTE_COLOR;
|
||||
for (i = 0; i < 10; i++) {
|
||||
to_color_map(palette[i], &color_map[i]);
|
||||
}
|
||||
bits_per_sample = 4;
|
||||
samples_per_pixel = 1;
|
||||
pixels_per_sample = 2;
|
||||
color_map_size = 16; /* 2**BitsPerSample */
|
||||
} else {
|
||||
pmi = TIF_PMI_RGB;
|
||||
bits_per_sample = 8;
|
||||
samples_per_pixel = 4;
|
||||
pixels_per_sample = 1;
|
||||
extra_samples = 1; /* Associated alpha */
|
||||
}
|
||||
}
|
||||
} else { /* fg/bg only */
|
||||
if (symbol->output_options & CMYK_COLOUR) {
|
||||
map['0'] = 0;
|
||||
to_cmyk(bg, bg[3], palette[0]);
|
||||
map['1'] = 1;
|
||||
to_cmyk(fg, fg[3], palette[1]);
|
||||
|
||||
pmi = TIF_PMI_SEPARATED;
|
||||
bits_per_sample = 8;
|
||||
if (fg[3] == 0xff && bg[3] == 0xff) { /* If no alpha */
|
||||
samples_per_pixel = 4;
|
||||
} else {
|
||||
samples_per_pixel = 5;
|
||||
extra_samples = 1; /* Associated alpha */
|
||||
}
|
||||
pixels_per_sample = 1;
|
||||
} else if (bg[0] == 0xff && bg[1] == 0xff && bg[2] == 0xff && bg[3] == 0xff
|
||||
&& fg[0] == 0 && fg[1] == 0 && fg[2] == 0 && fg[3] == 0xff) {
|
||||
map['0'] = 0;
|
||||
map['1'] = 1;
|
||||
|
||||
pmi = TIF_PMI_WHITEISZERO;
|
||||
bits_per_sample = 1;
|
||||
samples_per_pixel = 1;
|
||||
pixels_per_sample = 8;
|
||||
} else if (bg[0] == 0 && bg[1] == 0 && bg[2] == 0 && bg[3] == 0xff
|
||||
&& fg[0] == 0xff && fg[1] == 0xff && fg[2] == 0xff && fg[3] == 0xff) {
|
||||
map['0'] = 1;
|
||||
map['1'] = 0;
|
||||
|
||||
pmi = TIF_PMI_BLACKISZERO;
|
||||
bits_per_sample = 1;
|
||||
samples_per_pixel = 1;
|
||||
pixels_per_sample = 8;
|
||||
} else {
|
||||
map['0'] = 0;
|
||||
memcpy(palette[0], bg, 4);
|
||||
map['1'] = 1;
|
||||
memcpy(palette[1], fg, 4);
|
||||
|
||||
pmi = TIF_PMI_PALETTE_COLOR;
|
||||
for (i = 0; i < 2; i++) {
|
||||
to_color_map(palette[i], &color_map[i]);
|
||||
}
|
||||
if (fg[3] == 0xff && bg[3] == 0xff) { /* If no alpha */
|
||||
bits_per_sample = 4;
|
||||
samples_per_pixel = 1;
|
||||
pixels_per_sample = 2;
|
||||
color_map_size = 16; /* 2**BitsPerSample */
|
||||
} else {
|
||||
bits_per_sample = 8;
|
||||
samples_per_pixel = 2;
|
||||
pixels_per_sample = 1;
|
||||
color_map_size = 256; /* 2**BitsPerSample */
|
||||
extra_samples = 1; /* Associated alpha */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
rows_per_strip = (8192 * pixels_per_sample) / (symbol->bitmap_width * samples_per_pixel);
|
||||
if (rows_per_strip == 0) {
|
||||
rows_per_strip = 1;
|
||||
}
|
||||
@ -79,43 +274,56 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
/* Suppresses clang-tidy clang-analyzer-core.VLASize warning */
|
||||
assert(symbol->bitmap_height > 0);
|
||||
|
||||
if (rows_per_strip >= symbol->bitmap_height) {
|
||||
strip_count = 1;
|
||||
rows_per_strip = rows_last_strip = symbol->bitmap_height;
|
||||
} else {
|
||||
strip_count = symbol->bitmap_height / rows_per_strip;
|
||||
if ((symbol->bitmap_height % rows_per_strip) != 0) {
|
||||
rows_last_strip = symbol->bitmap_height % rows_per_strip;
|
||||
if (rows_last_strip != 0) {
|
||||
strip_count++;
|
||||
}
|
||||
|
||||
if (rows_per_strip > symbol->bitmap_height) {
|
||||
rows_per_strip = symbol->bitmap_height;
|
||||
rows_per_strip = rows_last_strip = symbol->bitmap_height;
|
||||
}
|
||||
}
|
||||
assert(strip_count > 0); /* Suppress clang-analyzer-core.UndefinedBinaryOperatorResult */
|
||||
|
||||
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);
|
||||
printf("TIFF (%dx%d) Strip Count %d, Rows Per Strip %d\n", symbol->bitmap_width, symbol->bitmap_height,
|
||||
strip_count, rows_per_strip);
|
||||
}
|
||||
|
||||
bytes_per_strip = rows_per_strip * ((symbol->bitmap_width + pixels_per_sample - 1) / pixels_per_sample)
|
||||
* samples_per_pixel;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
uint32_t strip_offset[strip_count];
|
||||
uint32_t strip_bytes[strip_count];
|
||||
unsigned char strip_buf[bytes_per_strip + 1];
|
||||
#else
|
||||
strip_offset = (uint32_t *) _alloca(strip_count * sizeof(uint32_t));
|
||||
strip_bytes = (uint32_t *) _alloca(strip_count * sizeof(uint32_t));
|
||||
strip_buf = (unsigned char *) _alloca(bytes_per_strip + 1);
|
||||
#endif
|
||||
free_memory = 8;
|
||||
free_memory = sizeof(tiff_header_t);
|
||||
|
||||
for (i = 0; i < strip_count; i++) {
|
||||
strip_offset[i] = free_memory;
|
||||
if (i != (strip_count - 1)) {
|
||||
strip_bytes[i] = rows_per_strip * symbol->bitmap_width * 3;
|
||||
strip_bytes[i] = bytes_per_strip;
|
||||
} else {
|
||||
if ((symbol->bitmap_height % rows_per_strip) != 0) {
|
||||
strip_bytes[i] = (symbol->bitmap_height % rows_per_strip) * symbol->bitmap_width * 3;
|
||||
if (rows_last_strip) {
|
||||
strip_bytes[i] = rows_last_strip * ((symbol->bitmap_width + pixels_per_sample - 1) / pixels_per_sample)
|
||||
* samples_per_pixel;
|
||||
} else {
|
||||
strip_bytes[i] = rows_per_strip * symbol->bitmap_width * 3;
|
||||
strip_bytes[i] = bytes_per_strip;
|
||||
}
|
||||
}
|
||||
free_memory += strip_bytes[i];
|
||||
if ((free_memory % 2) == 1) {
|
||||
free_memory++;
|
||||
}
|
||||
if (free_memory & 1) {
|
||||
free_memory++; // IFD must be on word boundary
|
||||
}
|
||||
|
||||
if (free_memory > 0xffff0000) {
|
||||
@ -133,184 +341,232 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
#endif
|
||||
tif_file = stdout;
|
||||
} else {
|
||||
if (!(tif_file = fopen(symbol->outfile, "wb"))) {
|
||||
if (!(tif_file = fopen(symbol->outfile, "wb+"))) {
|
||||
strcpy(symbol->errtxt, "672: Can't open output file");
|
||||
return ZINT_ERROR_FILE_ACCESS;
|
||||
}
|
||||
compression = TIF_LZW;
|
||||
tif_lzw_init(&lzw_state);
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header.byte_order = 0x4949;
|
||||
#ifdef TIF_BIG_ENDIAN
|
||||
header.byte_order = 0x4D4D; // "MM" big-endian
|
||||
#else
|
||||
header.byte_order = 0x4949; // "II" little-endian
|
||||
#endif
|
||||
header.identity = 42;
|
||||
header.offset = free_memory;
|
||||
|
||||
fwrite(&header, sizeof(tiff_header_t), 1, tif_file);
|
||||
free_memory += sizeof(tiff_ifd_t);
|
||||
total_bytes_put = sizeof(tiff_header_t);
|
||||
|
||||
/* Pixel data */
|
||||
pb = pixelbuf;
|
||||
strip = 0;
|
||||
strip_row = 0;
|
||||
bytes_put = 0;
|
||||
for (row = 0; row < symbol->bitmap_height; row++) {
|
||||
for (column = 0; column < symbol->bitmap_width; column++) {
|
||||
switch(pixelbuf[(row * symbol->bitmap_width) + column]) {
|
||||
case 'W': // White
|
||||
putc(255, tif_file);
|
||||
putc(255, tif_file);
|
||||
putc(255, tif_file);
|
||||
break;
|
||||
case 'C': // Cyan
|
||||
putc(0, tif_file);
|
||||
putc(255, tif_file);
|
||||
putc(255, tif_file);
|
||||
break;
|
||||
case 'B': // Blue
|
||||
putc(0, tif_file);
|
||||
putc(0, tif_file);
|
||||
putc(255, tif_file);
|
||||
break;
|
||||
case 'M': // Magenta
|
||||
putc(255, tif_file);
|
||||
putc(0, tif_file);
|
||||
putc(255, tif_file);
|
||||
break;
|
||||
case 'R': // Red
|
||||
putc(255, tif_file);
|
||||
putc(0, tif_file);
|
||||
putc(0, tif_file);
|
||||
break;
|
||||
case 'Y': // Yellow
|
||||
putc(255, tif_file);
|
||||
putc(255, tif_file);
|
||||
putc(0, tif_file);
|
||||
break;
|
||||
case 'G': // Green
|
||||
putc(0, tif_file);
|
||||
putc(255, tif_file);
|
||||
putc(0, tif_file);
|
||||
break;
|
||||
case 'K': // Black
|
||||
putc(0, tif_file);
|
||||
putc(0, tif_file);
|
||||
putc(0, tif_file);
|
||||
break;
|
||||
case '1':
|
||||
putc(fgred, tif_file);
|
||||
putc(fggrn, tif_file);
|
||||
putc(fgblu, tif_file);
|
||||
break;
|
||||
default:
|
||||
putc(bgred, tif_file);
|
||||
putc(bggrn, tif_file);
|
||||
putc(bgblu, tif_file);
|
||||
break;
|
||||
if (samples_per_pixel == 1) {
|
||||
if (bits_per_sample == 1) { /* WHITEISZERO or BLACKISZERO */
|
||||
for (column = 0; column < symbol->bitmap_width; column += 8) {
|
||||
unsigned char byte = 0;
|
||||
for (i = 0; i < 8 && column + i < symbol->bitmap_width; i++, pb++) {
|
||||
byte |= map[*pb] << (7 - i);
|
||||
}
|
||||
strip_buf[bytes_put++] = byte;
|
||||
}
|
||||
} else { /* bits_per_sample == 4, PALETTE_COLOR with no alpha */
|
||||
for (column = 0; column < symbol->bitmap_width; column += 2) {
|
||||
unsigned char byte = map[*pb++] << 4;
|
||||
if (column + 1 < symbol->bitmap_width) {
|
||||
byte |= map[*pb++];
|
||||
}
|
||||
strip_buf[bytes_put++] = byte;
|
||||
}
|
||||
}
|
||||
} else if (samples_per_pixel == 2) { /* PALETTE_COLOR with alpha */
|
||||
for (column = 0; column < symbol->bitmap_width; column++) {
|
||||
int idx = map[*pb++];
|
||||
strip_buf[bytes_put++] = idx;
|
||||
strip_buf[bytes_put++] = palette[idx][3];
|
||||
}
|
||||
} else { /* samples_per_pixel >= 4, RGB with alpha (4) or CMYK with (5) or without (4) alpha */
|
||||
for (column = 0; column < symbol->bitmap_width; column++) {
|
||||
int idx = map[*pb++];
|
||||
memcpy(&strip_buf[bytes_put], &palette[idx], samples_per_pixel);
|
||||
bytes_put += samples_per_pixel;
|
||||
}
|
||||
bytes_put += 3;
|
||||
}
|
||||
|
||||
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);
|
||||
strip_row++;
|
||||
|
||||
if (strip_row == rows_per_strip || (strip == strip_count - 1 && strip_row == rows_last_strip)) {
|
||||
// End of strip
|
||||
if (compression == TIF_LZW) {
|
||||
file_pos = ftell(tif_file);
|
||||
if (!tif_lzw_encode(&lzw_state, tif_file, strip_buf, bytes_put)) { /* Only fails if can't malloc */
|
||||
tif_lzw_cleanup(&lzw_state);
|
||||
fclose(tif_file); /* Only use LZW if not STDOUT, so ok to close */
|
||||
strcpy(symbol->errtxt, "673: Failed to malloc LZW hash table");
|
||||
return ZINT_ERROR_MEMORY;
|
||||
}
|
||||
bytes_put = ftell(tif_file) - file_pos;
|
||||
if (bytes_put != strip_bytes[strip]) {
|
||||
int diff = bytes_put - strip_bytes[strip];
|
||||
strip_bytes[strip] = bytes_put;
|
||||
for (i = strip + 1; i < strip_count; i++) {
|
||||
strip_offset[i] += diff;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fwrite(strip_buf, 1, bytes_put, tif_file);
|
||||
}
|
||||
strip++;
|
||||
total_bytes_put += bytes_put;
|
||||
bytes_put = 0;
|
||||
strip_row = 0;
|
||||
/* Suppress clang-analyzer-core.UndefinedBinaryOperatorResult */
|
||||
assert(strip < strip_count || row + 1 == symbol->bitmap_height);
|
||||
}
|
||||
}
|
||||
|
||||
if (total_bytes_put & 1) {
|
||||
putc(0, tif_file); // IFD must be on word boundary
|
||||
total_bytes_put++;
|
||||
}
|
||||
|
||||
if (compression == TIF_LZW) {
|
||||
tif_lzw_cleanup(&lzw_state);
|
||||
|
||||
file_pos = ftell(tif_file);
|
||||
fseek(tif_file, 4, SEEK_SET);
|
||||
free_memory = file_pos;
|
||||
fwrite(&free_memory, 4, 1, tif_file);
|
||||
fseek(tif_file, file_pos, SEEK_SET);
|
||||
}
|
||||
|
||||
/* Image File Directory */
|
||||
ifd.entries = 14;
|
||||
ifd.offset = 0;
|
||||
tags[entries].tag = 0x0100; // ImageWidth
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = symbol->bitmap_width;
|
||||
|
||||
ifd.new_subset.tag = 0xfe;
|
||||
ifd.new_subset.type = 4;
|
||||
ifd.new_subset.count = 1;
|
||||
ifd.new_subset.offset = 0;
|
||||
tags[entries].tag = 0x0101; // ImageLength - number of rows
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = symbol->bitmap_height;
|
||||
|
||||
ifd.image_width.tag = 0x0100;
|
||||
ifd.image_width.type = 3; // SHORT
|
||||
ifd.image_width.count = 1;
|
||||
ifd.image_width.offset = symbol->bitmap_width;
|
||||
|
||||
ifd.image_length.tag = 0x0101;
|
||||
ifd.image_length.type = 3; // SHORT
|
||||
ifd.image_length.count = 1;
|
||||
ifd.image_length.offset = symbol->bitmap_height;
|
||||
|
||||
ifd.bits_per_sample.tag = 0x0102;
|
||||
ifd.bits_per_sample.type = 3; // SHORT
|
||||
ifd.bits_per_sample.count = 3;
|
||||
ifd.bits_per_sample.offset = free_memory;
|
||||
free_memory += 6;
|
||||
|
||||
ifd.compression.tag = 0x0103;
|
||||
ifd.compression.type = 3;
|
||||
ifd.compression.count = 1;
|
||||
ifd.compression.offset = 1; // Uncompressed
|
||||
|
||||
ifd.photometric.tag = 0x0106;
|
||||
ifd.photometric.type = 3; // SHORT
|
||||
ifd.photometric.count = 1;
|
||||
ifd.photometric.offset = 2; // RGB Model
|
||||
|
||||
ifd.strip_offsets.tag = 0x0111;
|
||||
ifd.strip_offsets.type = 4; // LONG
|
||||
ifd.strip_offsets.count = strip_count;
|
||||
if (strip_count == 1) {
|
||||
ifd.strip_offsets.offset = strip_offset[0];
|
||||
if (samples_per_pixel != 1 || bits_per_sample != 1) {
|
||||
tags[entries].tag = 0x0102; // BitsPerSample
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = samples_per_pixel;
|
||||
if (samples_per_pixel == 1) {
|
||||
tags[entries++].offset = bits_per_sample;
|
||||
} else if (samples_per_pixel == 2) { /* 2 SHORTS fit into LONG offset so packed into offset */
|
||||
tags[entries++].offset = (bits_per_sample << 16) | bits_per_sample;
|
||||
} else {
|
||||
ifd.strip_offsets.offset = free_memory;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
free_memory += samples_per_pixel * 2;
|
||||
}
|
||||
}
|
||||
|
||||
tags[entries].tag = 0x0103; // Compression
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = compression;
|
||||
|
||||
tags[entries].tag = 0x0106; // PhotometricInterpretation
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = pmi;
|
||||
|
||||
tags[entries].tag = 0x0111; // StripOffsets
|
||||
tags[entries].type = 4; // LONG
|
||||
tags[entries].count = strip_count;
|
||||
if (strip_count == 1) {
|
||||
tags[entries++].offset = strip_offset[0];
|
||||
} else {
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
free_memory += strip_count * 4;
|
||||
}
|
||||
|
||||
ifd.samples_per_pixel.tag = 0x0115;
|
||||
ifd.samples_per_pixel.type = 3;
|
||||
ifd.samples_per_pixel.count = 1;
|
||||
ifd.samples_per_pixel.offset = 3;
|
||||
if (samples_per_pixel > 1) {
|
||||
tags[entries].tag = 0x0115; // SamplesPerPixel
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = samples_per_pixel;
|
||||
}
|
||||
|
||||
ifd.rows_per_strip.tag = 0x0116;
|
||||
ifd.rows_per_strip.type = 4;
|
||||
ifd.rows_per_strip.count = 1;
|
||||
ifd.rows_per_strip.offset = rows_per_strip;
|
||||
tags[entries].tag = 0x0116; // RowsPerStrip
|
||||
tags[entries].type = 4; // LONG
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = rows_per_strip;
|
||||
|
||||
ifd.strip_byte_counts.tag = 0x0117;
|
||||
ifd.strip_byte_counts.type = 4;
|
||||
ifd.strip_byte_counts.count = strip_count;
|
||||
tags[entries].tag = 0x0117; // StripByteCounts
|
||||
tags[entries].type = 4; // LONG
|
||||
tags[entries].count = strip_count;
|
||||
if (strip_count == 1) {
|
||||
ifd.strip_byte_counts.offset = strip_bytes[0];
|
||||
tags[entries++].offset = strip_bytes[0];
|
||||
} else {
|
||||
ifd.strip_byte_counts.offset = free_memory;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
free_memory += strip_count * 4;
|
||||
}
|
||||
|
||||
ifd.x_resolution.tag = 0x011a;
|
||||
ifd.x_resolution.type = 5;
|
||||
ifd.x_resolution.count = 1;
|
||||
ifd.x_resolution.offset = free_memory;
|
||||
tags[entries].tag = 0x011a; // XResolution
|
||||
tags[entries].type = 5; // RATIONAL
|
||||
tags[entries].count = 1;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
free_memory += 8;
|
||||
|
||||
ifd.y_resolution.tag = 0x011b;
|
||||
ifd.y_resolution.type = 5;
|
||||
ifd.y_resolution.count = 1;
|
||||
ifd.y_resolution.offset = free_memory;
|
||||
// free_memory += 8;
|
||||
tags[entries].tag = 0x011b; // YResolution
|
||||
tags[entries].type = 5; // RATIONAL
|
||||
tags[entries].count = 1;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
free_memory += 8;
|
||||
|
||||
ifd.planar_config.tag = 0x11c;
|
||||
ifd.planar_config.type = 3;
|
||||
ifd.planar_config.count = 1;
|
||||
ifd.planar_config.offset = 1;
|
||||
tags[entries].tag = 0x0128; // ResolutionUnit
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = 2; // Inches
|
||||
|
||||
ifd.resolution_unit.tag = 0x0128;
|
||||
ifd.resolution_unit.type = 3;
|
||||
ifd.resolution_unit.count = 1;
|
||||
ifd.resolution_unit.offset = 2; // Inches
|
||||
if (color_map_size) {
|
||||
tags[entries].tag = 0x0140; // ColorMap
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = color_map_size * 3;
|
||||
update_offsets[offsets++] = entries;
|
||||
tags[entries++].offset = free_memory;
|
||||
//free_memory += color_map_size * 3 * 2; /* Unnecessary as long as last use */
|
||||
}
|
||||
|
||||
fwrite(&ifd, sizeof(tiff_ifd_t), 1, tif_file);
|
||||
if (extra_samples) {
|
||||
tags[entries].tag = 0x0152; // ExtraSamples
|
||||
tags[entries].type = 3; // SHORT
|
||||
tags[entries].count = 1;
|
||||
tags[entries++].offset = extra_samples;
|
||||
}
|
||||
|
||||
/* Bits per sample */
|
||||
temp = 8;
|
||||
fwrite(&temp, 2, 1, tif_file); // Red Bytes
|
||||
fwrite(&temp, 2, 1, tif_file); // Green Bytes
|
||||
fwrite(&temp, 2, 1, tif_file); // Blue Bytes
|
||||
ifd_size = sizeof(entries) + sizeof(tiff_tag_t) * entries + sizeof(offset);
|
||||
for (i = 0; i < offsets; i++) {
|
||||
tags[update_offsets[i]].offset += ifd_size;
|
||||
}
|
||||
|
||||
fwrite(&entries, sizeof(entries), 1, tif_file);
|
||||
fwrite(&tags, sizeof(tiff_tag_t), entries, tif_file);
|
||||
fwrite(&offset, sizeof(offset), 1, tif_file);
|
||||
total_bytes_put += ifd_size;
|
||||
|
||||
if (samples_per_pixel > 2) {
|
||||
for (i = 0; i < samples_per_pixel; i++) {
|
||||
fwrite(&bits_per_sample, sizeof(bits_per_sample), 1, tif_file);
|
||||
}
|
||||
total_bytes_put += sizeof(bits_per_sample) * samples_per_pixel;
|
||||
}
|
||||
|
||||
if (strip_count != 1) {
|
||||
/* Strip offsets */
|
||||
@ -322,6 +578,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
for (i = 0; i < strip_count; i++) {
|
||||
fwrite(&strip_bytes[i], 4, 1, tif_file);
|
||||
}
|
||||
total_bytes_put += strip_count * 8;
|
||||
}
|
||||
|
||||
/* X Resolution */
|
||||
@ -329,16 +586,36 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, unsigned char *pixelbuf)
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
temp32 = 1;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
total_bytes_put += 8;
|
||||
|
||||
/* Y Resolution */
|
||||
temp32 = 72;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
temp32 = 1;
|
||||
fwrite(&temp32, 4, 1, tif_file);
|
||||
total_bytes_put += 8;
|
||||
|
||||
if (color_map_size) {
|
||||
for (i = 0; i < color_map_size; i++) {
|
||||
fwrite(&color_map[i].red, 2, 1, tif_file);
|
||||
}
|
||||
for (i = 0; i < color_map_size; i++) {
|
||||
fwrite(&color_map[i].green, 2, 1, tif_file);
|
||||
}
|
||||
for (i = 0; i < color_map_size; i++) {
|
||||
fwrite(&color_map[i].blue, 2, 1, tif_file);
|
||||
}
|
||||
total_bytes_put += 6 * color_map_size;
|
||||
}
|
||||
|
||||
if (symbol->output_options & BARCODE_STDOUT) {
|
||||
fflush(tif_file);
|
||||
} else {
|
||||
if (ftell(tif_file) != total_bytes_put) {
|
||||
fclose(tif_file);
|
||||
strcpy(symbol->errtxt, "674: Failed to write all output");
|
||||
return ZINT_ERROR_FILE_WRITE;
|
||||
}
|
||||
fclose(tif_file);
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2016-2017 Robin Stuart <rstuart114@gmail.com>
|
||||
Copyright (C) 2016-2021 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
@ -29,6 +29,8 @@
|
||||
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
*/
|
||||
/* vim: set ts=4 sw=4 et : */
|
||||
|
||||
#ifndef TIF_H
|
||||
#define TIF_H
|
||||
|
||||
@ -58,24 +60,11 @@ extern "C" {
|
||||
uint32_t offset;
|
||||
} tiff_tag_t;
|
||||
|
||||
typedef struct tiff_ifd {
|
||||
uint16_t entries;
|
||||
tiff_tag_t new_subset;
|
||||
tiff_tag_t image_width;
|
||||
tiff_tag_t image_length;
|
||||
tiff_tag_t bits_per_sample;
|
||||
tiff_tag_t compression;
|
||||
tiff_tag_t photometric;
|
||||
tiff_tag_t strip_offsets;
|
||||
tiff_tag_t samples_per_pixel;
|
||||
tiff_tag_t rows_per_strip;
|
||||
tiff_tag_t strip_byte_counts;
|
||||
tiff_tag_t x_resolution;
|
||||
tiff_tag_t y_resolution;
|
||||
tiff_tag_t planar_config;
|
||||
tiff_tag_t resolution_unit;
|
||||
uint32_t offset;
|
||||
} tiff_ifd_t;
|
||||
typedef struct tiff_color {
|
||||
uint16_t red;
|
||||
uint16_t green;
|
||||
uint16_t blue;
|
||||
} tiff_color_t;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
@ -84,5 +73,3 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#endif /* TIF_H */
|
||||
|
||||
|
||||
|
373
backend/tif_lzw.h
Normal file
373
backend/tif_lzw.h
Normal file
@ -0,0 +1,373 @@
|
||||
/* tif_lzw.h - LZW compression for TIFF
|
||||
|
||||
libzint - the open source barcode library
|
||||
Copyright (C) 2021 Robin Stuart <rstuart114@gmail.com>
|
||||
|
||||
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 : */
|
||||
|
||||
#ifndef TIF_LZW_H
|
||||
#define TIF_LZW_H
|
||||
|
||||
/*
|
||||
* Adapted from TIFF Library 4.2.0 libtiff/tif_lzw.c */
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
* Copyright (c) 1991-1997 Silicon Graphics, Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and
|
||||
* its documentation for any purpose is hereby granted without fee, provided
|
||||
* that (i) the above copyright notices and this permission notice appear in
|
||||
* all copies of the software and related documentation, and (ii) the names of
|
||||
* Sam Leffler and Silicon Graphics may not be used in any advertising or
|
||||
* publicity relating to the software without the specific, prior written
|
||||
* permission of Sam Leffler and Silicon Graphics.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
|
||||
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
|
||||
* ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
|
||||
* OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
||||
* WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
|
||||
* LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* TIFF Library.
|
||||
* Rev 5.0 Lempel-Ziv & Welch Compression Support
|
||||
*
|
||||
* This code is derived from the compress program whose code is
|
||||
* derived from software contributed to Berkeley by James A. Woods,
|
||||
* derived from original work by Spencer Thomas and Joseph Orost.
|
||||
*
|
||||
* The original Berkeley copyright notice appears below in its entirety.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1985, 1986 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* James A. Woods, derived from original work by Spencer Thomas
|
||||
* and Joseph Orost.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that the above copyright notice and this paragraph are
|
||||
* duplicated in all such forms and that any documentation,
|
||||
* advertising materials, and other materials related to such
|
||||
* distribution and use acknowledge that the software was developed
|
||||
* by the University of California, Berkeley. The name of the
|
||||
* University may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#define MAXCODE(n) ((1L << (n)) - 1)
|
||||
|
||||
/*
|
||||
* The TIFF spec specifies that encoded bit
|
||||
* strings range from 9 to 12 bits.
|
||||
*/
|
||||
#define BITS_MIN 9 /* start with 9 bits */
|
||||
#define BITS_MAX 12 /* max of 12 bit strings */
|
||||
/* predefined codes */
|
||||
#define CODE_CLEAR 256 /* code to clear string table */
|
||||
#define CODE_EOI 257 /* end-of-information code */
|
||||
#define CODE_FIRST 258 /* first free code entry */
|
||||
#define CODE_MAX MAXCODE(BITS_MAX)
|
||||
#define HSIZE 9001L /* 91% occupancy */
|
||||
#define HSHIFT (13 - 8)
|
||||
|
||||
/*
|
||||
* Encoding-specific state.
|
||||
*/
|
||||
typedef uint16_t tif_lzw_hcode; /* codes fit in 16 bits */
|
||||
typedef struct {
|
||||
long hash;
|
||||
tif_lzw_hcode code;
|
||||
} tif_lzw_hash;
|
||||
|
||||
#define CHECK_GAP 10000 /* ratio check interval */
|
||||
|
||||
/*
|
||||
* State block.
|
||||
*/
|
||||
typedef struct {
|
||||
tif_lzw_hash *enc_hashtab; /* kept separate for small machines */
|
||||
} tif_lzw_state;
|
||||
|
||||
/*
|
||||
* LZW Encoding.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Reset encoding hash table.
|
||||
*/
|
||||
static void tif_lzw_cl_hash(tif_lzw_state *sp) {
|
||||
register tif_lzw_hash *hp = &sp->enc_hashtab[HSIZE - 1];
|
||||
register long i = HSIZE - 8;
|
||||
|
||||
do {
|
||||
i -= 8;
|
||||
hp[-7].hash = -1;
|
||||
hp[-6].hash = -1;
|
||||
hp[-5].hash = -1;
|
||||
hp[-4].hash = -1;
|
||||
hp[-3].hash = -1;
|
||||
hp[-2].hash = -1;
|
||||
hp[-1].hash = -1;
|
||||
hp[ 0].hash = -1;
|
||||
hp -= 8;
|
||||
} while (i >= 0);
|
||||
|
||||
for (i += 8; i > 0; i--, hp--) {
|
||||
hp->hash = -1;
|
||||
}
|
||||
}
|
||||
|
||||
#define CALCRATIO(sp, rat) { \
|
||||
if (incount > 0x007fffff) { /* NB: shift will overflow */ \
|
||||
rat = outcount >> 8; \
|
||||
rat = (rat == 0 ? 0x7fffffff : incount / rat); \
|
||||
} else \
|
||||
rat = (incount << 8) / outcount; \
|
||||
}
|
||||
|
||||
/* Explicit 0xff masking to make icc -check=conversions happy */
|
||||
#define PutNextCode(op_file, c) { \
|
||||
nextdata = (nextdata << nbits) | c; \
|
||||
nextbits += nbits; \
|
||||
putc((nextdata >> (nextbits - 8)) & 0xff, op_file); \
|
||||
nextbits -= 8; \
|
||||
if (nextbits >= 8) { \
|
||||
putc((nextdata >> (nextbits - 8)) & 0xff, op_file); \
|
||||
nextbits -= 8; \
|
||||
} \
|
||||
outcount += nbits; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a chunk of pixels.
|
||||
*
|
||||
* Uses an open addressing double hashing (no chaining) on the
|
||||
* prefix code/next character combination. We do a variant of
|
||||
* Knuth's algorithm D (vol. 3, sec. 6.4) along with G. Knott's
|
||||
* relatively-prime secondary probe. Here, the modular division
|
||||
* first probe is gives way to a faster exclusive-or manipulation.
|
||||
* Also do block compression with an adaptive reset, whereby the
|
||||
* code table is cleared when the compression ratio decreases,
|
||||
* but after the table fills. The variable-length output codes
|
||||
* are re-sized at this point, and a CODE_CLEAR is generated
|
||||
* for the decoder.
|
||||
*/
|
||||
static int tif_lzw_encode(tif_lzw_state *sp, FILE *op_file, const unsigned char *bp, int cc) {
|
||||
register long fcode;
|
||||
register tif_lzw_hash *hp;
|
||||
register int h, c;
|
||||
tif_lzw_hcode ent;
|
||||
long disp;
|
||||
|
||||
int nbits; /* # of bits/code */
|
||||
int maxcode; /* maximum code for nbits */
|
||||
int free_ent; /* next free entry in hash table */
|
||||
unsigned long nextdata; /* next bits of i/o */
|
||||
long nextbits; /* # of valid bits in nextdata */
|
||||
long checkpoint; /* point at which to clear table */
|
||||
long ratio; /* current compression ratio */
|
||||
long incount; /* (input) data bytes encoded */
|
||||
long outcount; /* encoded (output) bytes */
|
||||
|
||||
/*
|
||||
* Reset encoding state at the start of a strip.
|
||||
*/
|
||||
if (sp->enc_hashtab == NULL) {
|
||||
sp->enc_hashtab = (tif_lzw_hash *) malloc(HSIZE * sizeof(tif_lzw_hash));
|
||||
if (sp->enc_hashtab == NULL) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
tif_lzw_cl_hash(sp); /* clear hash table */
|
||||
|
||||
nbits = BITS_MIN;
|
||||
maxcode = MAXCODE(BITS_MIN);
|
||||
free_ent = CODE_FIRST;
|
||||
nextdata = 0;
|
||||
nextbits = 0;
|
||||
checkpoint = CHECK_GAP;
|
||||
ratio = 0;
|
||||
incount = 0;
|
||||
outcount = 0;
|
||||
|
||||
ent = (tif_lzw_hcode) -1;
|
||||
|
||||
if (cc > 0) {
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
ent = *bp++; cc--; incount++;
|
||||
}
|
||||
while (cc > 0) {
|
||||
c = *bp++; cc--; incount++;
|
||||
fcode = ((long)c << BITS_MAX) + ent;
|
||||
h = (c << HSHIFT) ^ ent; /* xor hashing */
|
||||
#ifdef _WINDOWS
|
||||
/*
|
||||
* Check hash index for an overflow.
|
||||
*/
|
||||
if (h >= HSIZE) {
|
||||
h -= HSIZE;
|
||||
}
|
||||
#endif
|
||||
hp = &sp->enc_hashtab[h];
|
||||
if (hp->hash == fcode) {
|
||||
ent = hp->code;
|
||||
continue;
|
||||
}
|
||||
if (hp->hash >= 0) {
|
||||
/*
|
||||
* Primary hash failed, check secondary hash.
|
||||
*/
|
||||
disp = HSIZE - h;
|
||||
if (h == 0) {
|
||||
disp = 1;
|
||||
}
|
||||
do {
|
||||
/*
|
||||
* Avoid pointer arithmetic because of
|
||||
* wraparound problems with segments.
|
||||
*/
|
||||
if ((h -= disp) < 0) {
|
||||
h += HSIZE;
|
||||
}
|
||||
hp = &sp->enc_hashtab[h];
|
||||
if (hp->hash == fcode) {
|
||||
ent = hp->code;
|
||||
goto hit;
|
||||
}
|
||||
} while (hp->hash >= 0);
|
||||
}
|
||||
/*
|
||||
* New entry, emit code and add to table.
|
||||
*/
|
||||
PutNextCode(op_file, ent);
|
||||
ent = (tif_lzw_hcode) c;
|
||||
hp->code = (tif_lzw_hcode) (free_ent++);
|
||||
hp->hash = fcode;
|
||||
if (free_ent == CODE_MAX - 1) {
|
||||
/* table is full, emit clear code and reset */
|
||||
tif_lzw_cl_hash(sp);
|
||||
ratio = 0;
|
||||
incount = 0;
|
||||
outcount = 0;
|
||||
free_ent = CODE_FIRST;
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
nbits = BITS_MIN;
|
||||
maxcode = MAXCODE(BITS_MIN);
|
||||
} else {
|
||||
/*
|
||||
* If the next entry is going to be too big for
|
||||
* the code size, then increase it, if possible.
|
||||
*/
|
||||
if (free_ent > maxcode) {
|
||||
nbits++;
|
||||
assert(nbits <= BITS_MAX);
|
||||
maxcode = (int) MAXCODE(nbits);
|
||||
} else if (incount >= checkpoint) {
|
||||
long rat;
|
||||
/*
|
||||
* Check compression ratio and, if things seem
|
||||
* to be slipping, clear the hash table and
|
||||
* reset state. The compression ratio is a
|
||||
* 24+8-bit fractional number.
|
||||
*/
|
||||
checkpoint = incount + CHECK_GAP;
|
||||
CALCRATIO(sp, rat);
|
||||
if (rat <= ratio) {
|
||||
tif_lzw_cl_hash(sp);
|
||||
ratio = 0;
|
||||
incount = 0;
|
||||
outcount = 0;
|
||||
free_ent = CODE_FIRST;
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
nbits = BITS_MIN;
|
||||
maxcode = MAXCODE(BITS_MIN);
|
||||
} else {
|
||||
ratio = rat;
|
||||
}
|
||||
}
|
||||
}
|
||||
hit:
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish off an encoded strip by flushing the last
|
||||
* string and tacking on an End Of Information code.
|
||||
*/
|
||||
if (ent != (tif_lzw_hcode) -1) {
|
||||
|
||||
PutNextCode(op_file, ent);
|
||||
free_ent++;
|
||||
|
||||
if (free_ent == CODE_MAX - 1) {
|
||||
/* table is full, emit clear code and reset */
|
||||
outcount = 0;
|
||||
PutNextCode(op_file, CODE_CLEAR);
|
||||
nbits = BITS_MIN;
|
||||
} else {
|
||||
/*
|
||||
* If the next entry is going to be too big for
|
||||
* the code size, then increase it, if possible.
|
||||
*/
|
||||
if (free_ent > maxcode) {
|
||||
nbits++;
|
||||
assert(nbits <= BITS_MAX);
|
||||
}
|
||||
}
|
||||
}
|
||||
PutNextCode(op_file, CODE_EOI);
|
||||
/* Explicit 0xff masking to make icc -check=conversions happy */
|
||||
if (nextbits > 0) {
|
||||
putc((nextdata << (8 - nextbits)) & 0xff, op_file);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void tif_lzw_cleanup(tif_lzw_state *sp) {
|
||||
if (sp->enc_hashtab) {
|
||||
free(sp->enc_hashtab);
|
||||
}
|
||||
}
|
||||
|
||||
static void tif_lzw_init(tif_lzw_state *sp) {
|
||||
sp->enc_hashtab = NULL;
|
||||
}
|
||||
|
||||
#endif /* TIF_LZW_H */
|
@ -275,6 +275,7 @@ extern "C" {
|
||||
#define ZINT_ERROR_ENCODING_PROBLEM 9
|
||||
#define ZINT_ERROR_FILE_ACCESS 10
|
||||
#define ZINT_ERROR_MEMORY 11
|
||||
#define ZINT_ERROR_FILE_WRITE 12
|
||||
|
||||
// File types
|
||||
#define OUT_BUFFER 0
|
||||
|
@ -1037,6 +1037,9 @@ ZINT_ERROR_FILE_ACCESS | Zint was unable to open the requested output
|
||||
| problem.
|
||||
ZINT_ERROR_MEMORY | Zint ran out of memory. This should only be a
|
||||
| problem with legacy systems.
|
||||
ZINT_ERROR_FILE_WRITE | Zint failed to write all contents to the
|
||||
| requested output file. This should only occur
|
||||
| if the output disk becomes full.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
To catch errors use an integer variable as shown in the code below:
|
||||
|
@ -53,6 +53,7 @@ HEADERS += barcodeitem.h \
|
||||
..\backend\sjis.h \
|
||||
..\backend\stdint_msvc.h \
|
||||
..\backend\tif.h \
|
||||
..\backend\tif_lzw.h \
|
||||
..\backend\zint.h \
|
||||
..\backend\zintconfig.h \
|
||||
|
||||
|
@ -936,10 +936,10 @@ p, li { white-space: pre-wrap; }
|
||||
<item row="3" column="3">
|
||||
<widget class="QCheckBox" name="chkCMYK">
|
||||
<property name="toolTip">
|
||||
<string>Use CMYK colour space in EPS output</string>
|
||||
<string>Use CMYK colour space in EPS/TIF output</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CMY&K (EPS)</string>
|
||||
<string>CMY&K (EPS/TIF)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
|
@ -210,6 +210,7 @@
|
||||
<ClInclude Include="..\backend\sjis.h" />
|
||||
<ClInclude Include="..\backend\stdint_msvc.h" />
|
||||
<ClInclude Include="..\backend\tif.h" />
|
||||
<ClInclude Include="..\backend\tif_lzw.h" />
|
||||
<ClInclude Include="..\backend\zint.h" />
|
||||
<ClInclude Include="..\backend\zintconfig.h" />
|
||||
</ItemGroup>
|
||||
|
@ -617,6 +617,10 @@
|
||||
RelativePath="..\backend\tif.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\backend\tif_lzw.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\backend\zint.h"
|
||||
>
|
||||
|
@ -389,6 +389,7 @@
|
||||
<ClInclude Include="..\..\backend\sjis.h" />
|
||||
<ClInclude Include="..\..\backend\stdint_msvc.h" />
|
||||
<ClInclude Include="..\..\backend\tif.h" />
|
||||
<ClInclude Include="..\..\backend\tif_lzw.h" />
|
||||
<ClInclude Include="..\..\backend\zint.h" />
|
||||
<ClInclude Include="..\..\backend\zintconfig.h" />
|
||||
</ItemGroup>
|
||||
|
@ -157,6 +157,7 @@
|
||||
<ClInclude Include="..\..\backend\sjis.h" />
|
||||
<ClInclude Include="..\..\backend\stdint_msvc.h" />
|
||||
<ClInclude Include="..\..\backend\tif.h" />
|
||||
<ClInclude Include="..\..\backend\tif_lzw.h" />
|
||||
<ClInclude Include="..\..\backend\zint.h" />
|
||||
<ClInclude Include="..\..\backend\zintconfig.h" />
|
||||
</ItemGroup>
|
||||
|
@ -210,6 +210,7 @@
|
||||
<ClInclude Include="..\..\backend\sjis.h" />
|
||||
<ClInclude Include="..\..\backend\stdint_msvc.h" />
|
||||
<ClInclude Include="..\..\backend\tif.h" />
|
||||
<ClInclude Include="..\..\backend\tif_lzw.h" />
|
||||
<ClInclude Include="..\..\backend\zint.h" />
|
||||
<ClInclude Include="..\..\backend\zintconfig.h" />
|
||||
</ItemGroup>
|
||||
|
Loading…
Reference in New Issue
Block a user