diff --git a/tools/jpeginfo.c b/tools/jpeginfo.c index 0a5f2ae..4545746 100644 --- a/tools/jpeginfo.c +++ b/tools/jpeginfo.c @@ -324,6 +324,120 @@ tiffer_next_entry(struct tiffer *self, struct tiffer_entry *entry) return true; } +// --- TIFF/Exif/MPF/* tags ---------------------------------------------------- + +struct tiff_entry { + const char *name; + uint16_t tag; +}; + +static struct tiff_entry tiff_entries[] = { + {"NewSubfileType", 254}, + {"SubfileType", 255}, + {"ImageWidth", 256}, + {"ImageLength", 257}, + {"BitsPerSample", 258}, + {"Compression", 259}, + {"PhotometricInterpretation", 262}, + {"Threshholding", 263}, + {"CellWidth", 264}, + {"CellLength", 265}, + {"FillOrder", 266}, + {"DocumentName", 269}, + {"ImageDescription", 270}, + {"Make", 271}, + {"Model", 272}, + {"StripOffsets", 273}, + {"Orientation", 274}, + {"SamplesPerPixel", 277}, + {"RowsPerStrip", 278}, + {"StripByteCounts", 279}, + {"MinSampleValue", 280}, + {"MaxSampleValue", 281}, + {"XResolution", 282}, + {"YResolution", 283}, + {"PlanarConfiguration", 284}, + {"PageName", 285}, + {"XPosition", 286}, + {"YPosition", 287}, + {"FreeOffsets", 288}, + {"FreeByteCounts", 289}, + {"GrayResponseUnit", 290}, + {"GrayResponseCurve", 291}, + {"T4Options", 292}, + {"T6Options", 293}, + {"ResolutionUnit", 296}, + {"PageNumber", 297}, + {"TransferFunction", 301}, + {"Software", 305}, + {"DateTime", 306}, + {"Artist", 315}, + {"HostComputer", 316}, + {"Predictor", 317}, + {"WhitePoint", 318}, + {"PrimaryChromaticities", 319}, + {"ColorMap", 320}, + {"HalftoneHints", 321}, + {"TileWidth", 322}, + {"TileLength", 323}, + {"TileOffsets", 324}, + {"TileByteCounts", 325}, + {"InkSet", 332}, + {"InkNames", 333}, + {"NumberOfInks", 334}, + {"DotRange", 336}, + {"TargetPrinter", 337}, + {"ExtraSamples", 338}, + {"SampleFormat", 339}, + {"SMinSampleValue", 340}, + {"SMaxSampleValue", 341}, + {"TransferRange", 342}, + {"JPEGProc", 512}, + {"JPEGInterchangeFormat", 513}, + {"JPEGInterchangeFormatLngth", 514}, + {"JPEGRestartInterval", 515}, + {"JPEGLosslessPredictors", 517}, + {"JPEGPointTransforms", 518}, + {"JPEGQTables", 519}, + {"JPEGDCTables", 520}, + {"JPEGACTables", 521}, + {"YCbCrCoefficients", 529}, + {"YCbCrSubSampling", 530}, + {"YCbCrPositioning", 531}, + {"ReferenceBlackWhite", 532}, + {"Copyright", 33432}, + {} +}; + +// Compression +static struct tiff_entry tiff_compression_values[] = { + {"Uncompressed", 1}, + {"CCITT 1D", 2}, + {"Group 3 Fax", 3}, + {"Group 4 Fax", 4}, + {"LZW", 5}, + {"JPEG", 6}, + {"PackBits", 32773}, + {} +}; + +// PhotometricInterpretation +static struct tiff_entry tiff_photometric_interpretation_values[] = { + {"WhiteIsZero", 0}, + {"BlackIsZero", 1}, + {"RGB", 2}, + {"RGB Palette", 3}, + {"Transparency mask", 4}, + {"CMYK", 5}, + {"YCbCr", 6}, + {"CIELab", 8}, + {} +}; + +// TODO(p): Insert tags and values from other documentation, +// so far only Appendix A from TIFF 6.0 is present. +// There are still quite a few missing constant names from there. + // --- Analysis ---------------------------------------------------------------- static jv @@ -351,6 +465,17 @@ add_error(jv o, const char *message) // --- Exif -------------------------------------------------------------------- +// TODO(p): Decode more and better. +static jv +process_exif_entry(jv o, const struct tiffer_entry *entry) +{ + for (const struct tiff_entry *p = tiff_entries; p->name; p++) { + if (p->tag == entry->tag) + return add_to_subarray(o, "TIFF", jv_string(p->name)); + } + return add_to_subarray(o, "TIFF", jv_number(entry->tag)); +} + static jv parse_exif(jv o, const uint8_t *p, size_t len) { @@ -358,11 +483,11 @@ parse_exif(jv o, const uint8_t *p, size_t len) if (!tiffer_init(&T, p, len)) return add_warning(o, "invalid Exif"); - // TODO(p): Decode more and better. + // TODO(p): Turn this into an array of objects indexed by tag name. struct tiffer_entry entry; while (tiffer_next_ifd(&T)) { while (tiffer_next_entry(&T, &entry)) { - o = add_to_subarray(o, "TIFF", jv_number(entry.tag)); + o = process_exif_entry(o, &entry); } } return o;