47static void check(
const char* what,
int ok) {
50 fprintf(stderr,
"FAIL %s\n", what);
58static void put16(
unsigned char* p, uint16_t v,
int be) {
59 p[be ? 0 : 1] = (
unsigned char)(v >> 8);
60 p[be ? 1 : 0] = (
unsigned char)(v & 0xff);
67static void put32(
unsigned char* p, uint32_t v,
int be) {
70 for (i = 0; i < 4; i++)
71 p[be ? i : 3 - i] = (
unsigned char)(v >> (24 - 8 * i));
81static void put_entry(
unsigned char* e, uint16_t tag, uint16_t
type, uint32_t count, uint32_t value,
int be) {
84 put32(e + 4, count, be);
85 put32(e + 8, value, be);
93static size_t build(
unsigned char* buf,
int be) {
94 const float floats[2] = {1.5f, -0.25f};
98 buf[0] = buf[1] = (
unsigned char)(be ?
'M' :
'I');
100 put32(buf + 4, 8, be);
101 put16(buf + 8, 5, be);
103 put_entry(buf + 10, 50708, 2, 12, 80, be);
105 put16(buf + 22 + 8, 21, be);
106 put_entry(buf + 34, 50721, 10, 3, 96, be);
107 put_entry(buf + 46, 50938, 11, 2, 120, be);
108 put_entry(buf + 58, 50939, 11, 64, 200, be);
109 memcpy(buf + 80,
"Test Camera", 12);
110 put32(buf + 96, (uint32_t)8309, be);
111 put32(buf + 100, 10000, be);
112 put32(buf + 104, (uint32_t)-1786, be);
113 put32(buf + 108, 10000, be);
114 put32(buf + 112, 5, be);
115 put32(buf + 116, 0, be);
116 for (i = 0; i < 2; i++) {
119 memcpy(&bits, &floats[i],
sizeof(bits));
120 put32(buf + 120 + 4 * i, bits, be);
128 unsigned char buf[256];
129 size_t len =
build(buf, be);
131 double v[4] = {0, 0, 0, 0};
134 check(
"the buffer parses", tiff != NULL);
141 strcmp(text,
"Test Camera") == 0);
142 check(
"ASCII is cut to the room given",
146 fabs(v[0] - 0.8309) < 1e-9 && fabs(v[1] + 0.1786) < 1e-9 &&
154 check(
"free clears the pointer", tiff == NULL);
159 unsigned char buf[256];
160 size_t len =
build(buf, 0);
166 put32(buf + 4, 250, 0);
169 put16(buf + 8, 60, 0);
170 check(
"a directory longer than the buffer is refused",
n_tiff_parse(buf, len) == NULL);
177 unsigned char* data = NULL;
183 fprintf(stderr,
"cannot read %s\n", path);
188 fprintf(stderr,
"%s is not TIFF structured\n", path);
192 printf(
"%s: %s endian, magic 0x%04x, %zu entries\n", path, tiff->
big_endian ?
"big" :
"little",
194 for (i = 0; i < tiff->
count; i++)
210int main(
int argc,
char** argv) {
213 while ((opt = getopt(argc, argv,
"V:")) != -1) {
215 fprintf(stderr,
"Usage: %s [-V LOG_LEVEL] [file]\n", argv[0]);
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.