1
0
mirror of https://git.code.sf.net/p/zint/code synced 2026-01-06 11:37:27 +00:00

- BMP/EMF/PCX/TIF: fix endianness on big-endian machines (note TIF

now always written as little-endian - simplifies testing)
- READMEs: add date updated
This commit is contained in:
gitlost
2024-01-17 01:45:45 +00:00
parent cf04ac15b0
commit bead450f38
16 changed files with 317 additions and 265 deletions

View File

@@ -1,7 +1,7 @@
/* tif.c - Aldus Tagged Image File Format support */
/*
libzint - the open source barcode library
Copyright (C) 2016-2023 Robin Stuart <rstuart114@gmail.com>
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
@@ -69,10 +69,6 @@ static void to_cmyk(const char *colour, unsigned char *cmyk) {
cmyk[4] = alpha;
}
static int is_big_endian(void) {
return (*((const uint16_t *)"\x11\x22") == 0x1122);
}
/* 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];
@@ -113,6 +109,7 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
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]);
@@ -323,13 +320,9 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
}
/* Header */
if (is_big_endian()) {
header.byte_order = 0x4D4D; /* "MM" big-endian */
} else {
header.byte_order = 0x4949; /* "II" little-endian */
}
header.identity = 42;
header.offset = (uint32_t) free_memory;
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);
@@ -422,29 +415,30 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
(void) fm_close(fmp, symbol);
return ZINT_ERROR_MEMORY;
}
out_le_u32(temp32, temp32);
fm_write(&temp32, 4, 1, fmp);
fm_seek(fmp, file_pos, SEEK_SET);
}
/* Image File Directory */
tags[entries].tag = 0x0100; /* ImageWidth */
tags[entries].type = 3; /* SHORT */
tags[entries].count = 1;
tags[entries++].offset = symbol->bitmap_width;
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);
tags[entries].tag = 0x0101; /* ImageLength - number of rows */
tags[entries].type = 3; /* SHORT */
tags[entries].count = 1;
tags[entries++].offset = symbol->bitmap_height;
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) {
tags[entries].tag = 0x0102; /* BitsPerSample */
tags[entries].type = 3; /* SHORT */
tags[entries].count = samples_per_pixel;
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) {
tags[entries++].offset = bits_per_sample;
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 */
tags[entries++].offset = (bits_per_sample << 16) | bits_per_sample;
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;
@@ -452,21 +446,21 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
}
}
tags[entries].tag = 0x0103; /* Compression */
tags[entries].type = 3; /* SHORT */
tags[entries].count = 1;
tags[entries++].offset = compression;
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);
tags[entries].tag = 0x0106; /* PhotometricInterpretation */
tags[entries].type = 3; /* SHORT */
tags[entries].count = 1;
tags[entries++].offset = pmi;
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);
tags[entries].tag = 0x0111; /* StripOffsets */
tags[entries].type = 4; /* LONG */
tags[entries].count = strip_count;
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) {
tags[entries++].offset = strip_offset[0];
out_le_u32(tags[entries++].offset, strip_offset[0]);
} else {
update_offsets[offsets++] = entries;
tags[entries++].offset = (uint32_t) free_memory;
@@ -474,78 +468,81 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
}
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;
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);
}
tags[entries].tag = 0x0116; /* RowsPerStrip */
tags[entries].type = 4; /* LONG */
tags[entries].count = 1;
tags[entries++].offset = rows_per_strip;
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);
tags[entries].tag = 0x0117; /* StripByteCounts */
tags[entries].type = 4; /* LONG */
tags[entries].count = strip_count;
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) {
tags[entries++].offset = strip_bytes[0];
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;
}
tags[entries].tag = 0x011a; /* XResolution */
tags[entries].type = 5; /* RATIONAL */
tags[entries].count = 1;
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;
tags[entries].tag = 0x011b; /* YResolution */
tags[entries].type = 5; /* RATIONAL */
tags[entries].count = 1;
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;
tags[entries].tag = 0x0128; /* ResolutionUnit */
tags[entries].type = 3; /* SHORT */
tags[entries].count = 1;
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) {
tags[entries++].offset = 3; /* Centimetres */
out_le_u32(tags[entries++].offset, 3); /* Centimetres */
} else {
tags[entries++].offset = 2; /* Inches */
out_le_u32(tags[entries++].offset, 2); /* Inches */
}
if (color_map_size) {
tags[entries].tag = 0x0140; /* ColorMap */
tags[entries].type = 3; /* SHORT */
tags[entries].count = color_map_size * 3;
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) {
tags[entries].tag = 0x0152; /* ExtraSamples */
tags[entries].type = 3; /* SHORT */
tags[entries].count = 1;
tags[entries++].offset = 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++) {
tags[update_offsets[i]].offset += ifd_size;
out_le_u32(tags[update_offsets[i]].offset, tags[update_offsets[i]].offset + ifd_size);
}
fm_write(&entries, sizeof(entries), 1, fmp);
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);
}
@@ -555,27 +552,29 @@ INTERNAL int tif_pixel_plot(struct zint_symbol *symbol, const unsigned char *pix
if (strip_count != 1) {
/* Strip offsets */
for (i = 0; i < strip_count; i++) {
fm_write(&strip_offset[i], 4, 1, fmp);
out_le_u32(temp32, strip_offset[i]);
fm_write(&temp32, 4, 1, fmp);
}
/* Strip byte lengths */
for (i = 0; i < strip_count; i++) {
fm_write(&strip_bytes[i], 4, 1, fmp);
out_le_u32(temp32, strip_bytes[i]);
fm_write(&temp32, 4, 1, fmp);
}
total_bytes_put += strip_count * 8;
}
/* XResolution */
temp32 = symbol->dpmm ? symbol->dpmm : 72;
out_le_u32(temp32, symbol->dpmm ? symbol->dpmm : 72);
fm_write(&temp32, 4, 1, fmp);
temp32 = symbol->dpmm ? 10 /*cm*/ : 1;
out_le_u32(temp32, symbol->dpmm ? 10 /*cm*/ : 1);
fm_write(&temp32, 4, 1, fmp);
total_bytes_put += 8;
/* YResolution */
temp32 = symbol->dpmm ? symbol->dpmm : 72;
out_le_u32(temp32, symbol->dpmm ? symbol->dpmm : 72);
fm_write(&temp32, 4, 1, fmp);
temp32 = symbol->dpmm ? 10 /*cm*/ : 1;
out_le_u32(temp32, symbol->dpmm ? 10 /*cm*/ : 1);
fm_write(&temp32, 4, 1, fmp);
total_bytes_put += 8;