Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/thirdparty/zint/backend/tif.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/thirdparty/zint/backend/tif.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,611 @@ +/* tif.c - Aldus Tagged Image File Format support */ +/* + libzint - the open source barcode library + Copyright (C) 2016-2024 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. + */ +/* SPDX-License-Identifier: BSD-3-Clause */ + +#include <assert.h> +#include <errno.h> +#include <math.h> +#include <stdio.h> +#include "common.h" +#include "filemem.h" +#include "output.h" +#include "tif.h" +#include "tif_lzw.h" + +/* 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(const 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(const char *colour, unsigned char *cmyk) { + int cyan, magenta, yellow, black; + unsigned char alpha; + + (void) out_colour_get_cmyk(colour, &cyan, &magenta, &yellow, &black, &alpha); + cmyk[0] = (unsigned char) roundf(cyan * 0xFF / 100.0f); + cmyk[1] = (unsigned char) roundf(magenta * 0xFF / 100.0f); + cmyk[2] = (unsigned char) roundf(yellow * 0xFF / 100.0f); + cmyk[3] = (unsigned char) roundf(black * 0xFF / 100.0f); + cmyk[4] = alpha; +} + +/* TIFF Revision 6.0 https://www.adobe.io/content/dam/udp/en/open/standards/tiff/TIFF6.pdf */ +INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pixelbuf) { + unsigned char fg[4], bg[4]; + int i; + int pmi; /* PhotometricInterpretation */ + int rows_per_strip, strip_count; + 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; + size_t free_memory; + int row, column, strip; + int strip_row; + unsigned int bytes_put; + long total_bytes_put; + struct filemem fm; + struct filemem *const fmp = &fm; + const unsigned char *pb; + int compression = TIF_NO_COMPRESSION; + tif_lzw_state lzw_state; + long file_pos; + const int output_to_stdout = symbol->output_options & BARCODE_STDOUT; + uint32_t *strip_offset; + uint32_t *strip_bytes; + unsigned char *strip_buf; + + tiff_header_t header; + 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; + uint16_t temp16; + + (void) out_colour_get_rgb(symbol->fgcolour, &fg[0], &fg[1], &fg[2], &fg[3]); + (void) out_colour_get_rgb(symbol->bgcolour, &bg[0], &bg[1], &bg[2], &bg[3]); + + if (symbol->symbology == BARCODE_ULTRA) { + static const unsigned char ultra_chars[8] = { 'W', 'C', 'B', 'M', 'R', 'Y', 'G', 'K' }; + + if (symbol->output_options & CMYK_COLOUR) { + static const unsigned char ultra_cmyks[8][4] = { + { 0, 0, 0, 0 }, /* White */ + { 0xFF, 0, 0, 0 }, /* Cyan */ + { 0xFF, 0xFF, 0, 0 }, /* Blue */ + { 0, 0xFF, 0, 0 }, /* Magenta */ + { 0, 0xFF, 0xFF, 0 }, /* Red */ + { 0, 0, 0xFF, 0 }, /* Yellow */ + { 0xFF, 0, 0xFF, 0 }, /* Green */ + { 0, 0, 0, 0xFF }, /* Black */ + }; + for (i = 0; i < 8; i++) { + map[ultra_chars[i]] = i; + memcpy(palette[i], ultra_cmyks[i], 4); + palette[i][4] = fg[3]; + } + map['0'] = 8; + to_cmyk(symbol->bgcolour, palette[8]); + map['1'] = 9; + to_cmyk(symbol->fgcolour, 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 { + static const 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 */ + }; + 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(symbol->bgcolour, palette[0]); + map['1'] = 1; + to_cmyk(symbol->fgcolour, 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'] = 0; + map['1'] = 1; + + 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 * pixels_per_sample) / (symbol->bitmap_width * samples_per_pixel); + if (rows_per_strip == 0) { + rows_per_strip = 1; + } + + /* 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; + 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 = 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, Pixels Per Sample %d, Samples Per Pixel %d, PMI %d\n", + symbol->bitmap_width, symbol->bitmap_height, strip_count, rows_per_strip, pixels_per_sample, + samples_per_pixel, pmi); + } + + bytes_per_strip = rows_per_strip * ((symbol->bitmap_width + pixels_per_sample - 1) / pixels_per_sample) + * samples_per_pixel; + + strip_offset = (uint32_t *) z_alloca(sizeof(uint32_t) * strip_count); + strip_bytes = (uint32_t *) z_alloca(sizeof(uint32_t) * strip_count); + strip_buf = (unsigned char *) z_alloca(bytes_per_strip + 1); + + free_memory = sizeof(tiff_header_t); + + for (i = 0; i < strip_count; i++) { + strip_offset[i] = (uint32_t) free_memory; + if (i != (strip_count - 1)) { + strip_bytes[i] = bytes_per_strip; + } else { + 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] = bytes_per_strip; + } + } + free_memory += strip_bytes[i]; + } + if (free_memory & 1) { + free_memory++; /* IFD must be on word boundary */ + } + + if (free_memory > 0xffff0000) { + return errtxt(ZINT_ERROR_MEMORY, symbol, 670, "TIF output file size too big"); + } + + /* Open output file in binary mode */ + if (!fm_open(fmp, symbol, "wb")) { + return errtxtf(ZINT_ERROR_FILE_ACCESS, symbol, 672, "Could not open TIF output file (%1$d: %2$s)", fmp->err, + strerror(fmp->err)); + } + if (!output_to_stdout) { + compression = TIF_LZW; + tif_lzw_init(&lzw_state); + } + + /* Header */ + out_le_u16(header.byte_order, 0x4949); /* "II" little-endian */ + out_le_u16(header.identity, 42); + out_le_u32(header.offset, free_memory); + + fm_write(&header, sizeof(tiff_header_t), 1, fmp); + 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++) { + 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++) { + const 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++) { + const int idx = map[*pb++]; + memcpy(&strip_buf[bytes_put], &palette[idx], samples_per_pixel); + bytes_put += samples_per_pixel; + } + } + + 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 = fm_tell(fmp); + if (!tif_lzw_encode(&lzw_state, fmp, strip_buf, bytes_put)) { /* Only fails if can't malloc */ + tif_lzw_cleanup(&lzw_state); + (void) fm_close(fmp, symbol); + return errtxt(ZINT_ERROR_MEMORY, symbol, 673, "Insufficient memory for TIF LZW hash table"); + } + bytes_put = fm_tell(fmp) - file_pos; + if (bytes_put != strip_bytes[strip]) { + const 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 { + fm_write(strip_buf, 1, bytes_put, fmp); + } + 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) { + fm_putc(0, fmp); /* IFD must be on word boundary */ + total_bytes_put++; + } + + if (compression == TIF_LZW) { + tif_lzw_cleanup(&lzw_state); + + file_pos = fm_tell(fmp); + fm_seek(fmp, 4, SEEK_SET); + free_memory = file_pos; + temp32 = (uint32_t) free_memory; + /* Shouldn't happen as `free_memory` checked above to be <= 0xffff0000 & should only decrease */ + if (free_memory != temp32 || (long) free_memory != file_pos) { + (void) fm_close(fmp, symbol); + return errtxt(ZINT_ERROR_MEMORY, symbol, 982, "TIF output file size too big"); + } + out_le_u32(temp32, temp32); + fm_write(&temp32, 4, 1, fmp); + fm_seek(fmp, file_pos, SEEK_SET); + } + + /* Image File Directory */ + out_le_u16(tags[entries].tag, 0x0100); /* ImageWidth */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, symbol->bitmap_width); + + out_le_u16(tags[entries].tag, 0x0101); /* ImageLength - number of rows */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, symbol->bitmap_height); + + if (samples_per_pixel != 1 || bits_per_sample != 1) { + out_le_u16(tags[entries].tag, 0x0102); /* BitsPerSample */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, samples_per_pixel); + if (samples_per_pixel == 1) { + out_le_u32(tags[entries++].offset, bits_per_sample); + } else if (samples_per_pixel == 2) { /* 2 SHORTS fit into LONG offset so packed into offset */ + out_le_u32(tags[entries++].offset, (bits_per_sample << 16) | bits_per_sample); + } else { + update_offsets[offsets++] = entries; + tags[entries++].offset = (uint32_t) free_memory; + free_memory += samples_per_pixel * 2; + } + } + + out_le_u16(tags[entries].tag, 0x0103); /* Compression */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, compression); + + out_le_u16(tags[entries].tag, 0x0106); /* PhotometricInterpretation */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, pmi); + + out_le_u16(tags[entries].tag, 0x0111); /* StripOffsets */ + out_le_u16(tags[entries].type, 4); /* LONG */ + out_le_u32(tags[entries].count, strip_count); + if (strip_count == 1) { + out_le_u32(tags[entries++].offset, strip_offset[0]); + } else { + update_offsets[offsets++] = entries; + tags[entries++].offset = (uint32_t) free_memory; + free_memory += strip_count * 4; + } + + if (samples_per_pixel > 1) { + out_le_u16(tags[entries].tag, 0x0115); /* SamplesPerPixel */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, samples_per_pixel); + } + + out_le_u16(tags[entries].tag, 0x0116); /* RowsPerStrip */ + out_le_u16(tags[entries].type, 4); /* LONG */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, rows_per_strip); + + out_le_u16(tags[entries].tag, 0x0117); /* StripByteCounts */ + out_le_u16(tags[entries].type, 4); /* LONG */ + out_le_u32(tags[entries].count, strip_count); + if (strip_count == 1) { + out_le_u32(tags[entries++].offset, strip_bytes[0]); + } else { + update_offsets[offsets++] = entries; + tags[entries++].offset = (uint32_t) free_memory; + free_memory += strip_count * 4; + } + + out_le_u16(tags[entries].tag, 0x011a); /* XResolution */ + out_le_u16(tags[entries].type, 5); /* RATIONAL */ + out_le_u32(tags[entries].count, 1); + update_offsets[offsets++] = entries; + tags[entries++].offset = (uint32_t) free_memory; + free_memory += 8; + + out_le_u16(tags[entries].tag, 0x011b); /* YResolution */ + out_le_u16(tags[entries].type, 5); /* RATIONAL */ + out_le_u32(tags[entries].count, 1); + update_offsets[offsets++] = entries; + tags[entries++].offset = (uint32_t) free_memory; + free_memory += 8; + + out_le_u16(tags[entries].tag, 0x0128); /* ResolutionUnit */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + if (symbol->dpmm) { + out_le_u32(tags[entries++].offset, 3); /* Centimetres */ + } else { + out_le_u32(tags[entries++].offset, 2); /* Inches */ + } + + if (color_map_size) { + out_le_u16(tags[entries].tag, 0x0140); /* ColorMap */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, color_map_size * 3); + update_offsets[offsets++] = entries; + tags[entries++].offset = (uint32_t) free_memory; + /* free_memory += color_map_size * 3 * 2; Unnecessary as long as last use */ + } + + if (extra_samples) { + out_le_u16(tags[entries].tag, 0x0152); /* ExtraSamples */ + out_le_u16(tags[entries].type, 3); /* SHORT */ + out_le_u32(tags[entries].count, 1); + out_le_u32(tags[entries++].offset, extra_samples); + } + + ifd_size = sizeof(entries) + sizeof(tiff_tag_t) * entries + sizeof(offset); + for (i = 0; i < offsets; i++) { + out_le_u32(tags[update_offsets[i]].offset, tags[update_offsets[i]].offset + ifd_size); + } + + out_le_u16(temp16, entries); + fm_write(&temp16, sizeof(entries), 1, fmp); + fm_write(&tags, sizeof(tiff_tag_t), entries, fmp); + out_le_u32(offset, offset); + fm_write(&offset, sizeof(offset), 1, fmp); + total_bytes_put += ifd_size; + + if (samples_per_pixel > 2) { + out_le_u16(bits_per_sample, bits_per_sample); + for (i = 0; i < samples_per_pixel; i++) { + fm_write(&bits_per_sample, sizeof(bits_per_sample), 1, fmp); + } + total_bytes_put += sizeof(bits_per_sample) * samples_per_pixel; + } + + if (strip_count != 1) { + /* Strip offsets */ + for (i = 0; i < strip_count; i++) { + out_le_u32(temp32, strip_offset[i]); + fm_write(&temp32, 4, 1, fmp); + } + + /* Strip byte lengths */ + for (i = 0; i < strip_count; i++) { + out_le_u32(temp32, strip_bytes[i]); + fm_write(&temp32, 4, 1, fmp); + } + total_bytes_put += strip_count * 8; + } + + /* XResolution */ + out_le_u32(temp32, symbol->dpmm ? symbol->dpmm : 72); + fm_write(&temp32, 4, 1, fmp); + out_le_u32(temp32, symbol->dpmm ? 10 /*cm*/ : 1); + fm_write(&temp32, 4, 1, fmp); + total_bytes_put += 8; + + /* YResolution */ + out_le_u32(temp32, symbol->dpmm ? symbol->dpmm : 72); + fm_write(&temp32, 4, 1, fmp); + out_le_u32(temp32, symbol->dpmm ? 10 /*cm*/ : 1); + fm_write(&temp32, 4, 1, fmp); + total_bytes_put += 8; + + if (color_map_size) { + for (i = 0; i < color_map_size; i++) { + fm_write(&color_map[i].red, 2, 1, fmp); + } + for (i = 0; i < color_map_size; i++) { + fm_write(&color_map[i].green, 2, 1, fmp); + } + for (i = 0; i < color_map_size; i++) { + fm_write(&color_map[i].blue, 2, 1, fmp); + } + total_bytes_put += 6 * color_map_size; + } + + if (fm_error(fmp)) { + errtxtf(0, symbol, 679, "Incomplete write of TIF output (%1$d: %2$s)", fmp->err, strerror(fmp->err)); + (void) fm_close(fmp, symbol); + return ZINT_ERROR_FILE_WRITE; + } + + if (!output_to_stdout) { + if (fm_tell(fmp) != total_bytes_put) { + (void) fm_close(fmp, symbol); + return errtxt(ZINT_ERROR_FILE_WRITE, symbol, 674, "Failed to write all TIF output"); + } + } + if (!fm_close(fmp, symbol)) { + return errtxtf(ZINT_ERROR_FILE_WRITE, symbol, 981, "Failure on closing TIF output file (%1$d: %2$s)", + fmp->err, strerror(fmp->err)); + } + + return 0; +} + +/* vim: set ts=4 sw=4 et : */
