n_tiff: build small TIFF structured buffers in both byte orders, read their tags back, and refuse broken ones.
n_tiff: build small TIFF structured buffers in both byte orders, read their tags back, and refuse broken ones. With a file argument, list the tags of that file's first directory instead.
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
static void check(
const char* what,
int ok) {
if (!ok) {
fprintf(stderr, "FAIL %s\n", what);
}
}
static void put16(
unsigned char* p, uint16_t v,
int be) {
p[be ? 0 : 1] = (unsigned char)(v >> 8);
p[be ? 1 : 0] = (unsigned char)(v & 0xff);
}
static void put32(
unsigned char* p, uint32_t v,
int be) {
int i = 0;
for (i = 0; i < 4; i++)
p[be ? i : 3 - i] = (unsigned char)(v >> (24 - 8 * i));
}
static void put_entry(
unsigned char* e, uint16_t tag, uint16_t
type, uint32_t count, uint32_t value,
int be) {
}
static size_t build(
unsigned char* buf,
int be) {
const float floats[2] = {1.5f, -0.25f};
int i = 0;
memset(buf, 0, 256);
buf[0] = buf[1] = (unsigned char)(be ? 'M' : 'I');
put16(buf + 22 + 8, 21, be);
memcpy(buf + 80, "Test Camera", 12);
put32(buf + 96, (uint32_t)8309, be);
put32(buf + 100, 10000, be);
put32(buf + 104, (uint32_t)-1786, be);
put32(buf + 108, 10000, be);
for (i = 0; i < 2; i++) {
uint32_t bits = 0;
memcpy(&bits, &floats[i], sizeof(bits));
put32(buf + 120 + 4 * i, bits, be);
}
return 256;
}
unsigned char buf[256];
size_t len =
build(buf, be);
double v[4] = {0, 0, 0, 0};
char text[64];
check(
"the buffer parses", tiff != NULL);
if (!tiff)
return;
strcmp(text, "Test Camera") == 0);
check(
"ASCII is cut to the room given",
fabs(v[0] - 0.8309) < 1e-9 && fabs(v[1] + 0.1786) < 1e-9 &&
v[2] == 0.0);
text[0] == '\0');
check(
"free clears the pointer", tiff == NULL);
}
unsigned char buf[256];
size_t len =
build(buf, 0);
buf[0] = 'X';
check(
"a directory longer than the buffer is refused",
n_tiff_parse(buf, len) == NULL);
}
unsigned char* data = NULL;
size_t len = 0;
size_t i = 0;
fprintf(stderr, "cannot read %s\n", path);
return 1;
}
if (!tiff) {
fprintf(stderr, "%s is not TIFF structured\n", path);
free(data);
return 1;
}
printf(
"%s: %s endian, magic 0x%04x, %zu entries\n", path, tiff->
big_endian ?
"big" :
"little",
for (i = 0; i < tiff->
count; i++)
free(data);
return 0;
}
int main(
int argc,
char** argv) {
while ((opt = getopt(argc, argv, "V:")) != -1) {
if (opt != 'V') {
fprintf(stderr, "Usage: %s [-V LOG_LEVEL] [file]\n", argv[0]);
return 2;
}
}
if (optind < argc)
}
static void type(N_GUI_CTX *gui, const char *s)
Type a whole string into whatever has focus.
static void check(const char *what, int ok)
Count and print a failed condition.
static size_t build(unsigned char *buf, int be)
Build a DCP shaped buffer: a name, a short, three signed rationals, two floats, and one entry pointin...
static void put16(unsigned char *p, uint16_t v, int be)
Write a 16 bit value in a byte order.
static void put32(unsigned char *p, uint32_t v, int be)
Write a 32 bit value in a byte order.
static void test_order(int be)
Parse a built buffer and check every value.
static void test_broken(void)
Broken buffers are refused, never read out of bounds.
static int list_file(const char *path)
List the tags of a file's first directory.
static void put_entry(unsigned char *e, uint16_t tag, uint16_t type, uint32_t count, uint32_t value, int be)
Write one directory entry.
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL ).
int n_file_read_bounded(const char *path, size_t max_size, unsigned char **out, size_t *out_len)
read a whole file into a freshly allocated, NUL-terminated buffer, refusing a file larger than max_si...
N_TIFF_ENTRY * entries
the entries whose values lie inside the buffer, in file order
uint16_t type
TIFF field type, 1 BYTE to 12 DOUBLE.
uint32_t count
number of values
int big_endian
1 for "MM" (Motorola, big endian), 0 for "II"
uint16_t magic
the 16 bit value after the byte order mark
N_TIFF * n_tiff_parse(const unsigned char *data, size_t len)
Parse the first directory of a TIFF structured buffer.
size_t n_tiff_count(const N_TIFF *tiff, uint16_t tag)
How many values a tag has.
size_t n_tiff_get_doubles(const N_TIFF *tiff, uint16_t tag, double *out, size_t max)
Read a numeric tag as doubles.
#define N_TIFF_MAGIC_DCP
The magic of an Adobe DCP camera profile, "RC" read little endian.
const N_TIFF_ENTRY * n_tiff_find(const N_TIFF *tiff, uint16_t tag)
Find an entry by tag.
int n_tiff_get_ascii(const N_TIFF *tiff, uint16_t tag, char *out, size_t out_len)
Read an ASCII tag.
void n_tiff_free(N_TIFF **tiff)
Release a parse, and set the pointer to NULL.
The first directory of a TIFF structured buffer.
Common headers and low-level functions & define.
Files configuration header.
Reading the tags of a TIFF structured buffer.